v1.88.1.0 fix: harden credential boundaries and owned state (#2942)

* fix(settings): preserve symlinked settings targets

Resolve the selected target for locking, mutation, backup, and rollback; refuse target changes and preserve private modes. Addresses #2830.

* fix(redact): bind masking to original detected spans

Inspired by #2929's anchored-span diagnosis; independently implemented using normalization offsets. Addresses #2930 and the relocation portion of #2912 without changing detection sensitivity.

* fix(evals): exclude operator credentials from prefix admission

Adapts the credential-suffix screen proposed in #2636, with real launched-child regression coverage and deliberate provider-auth exceptions.

* fix(artifacts): retain custom allowlist rules on reinitialization

Preserve the exact user-owned suffix and publish only a successfully assembled replacement. Independently implements the repair reported in #2907.

* test(cso): verify exact masked reads and unmaskable payload refusal

* fix(cso): preserve exact filesystem identities through lease recovery

Preserve 64-bit device/inode identity and nanosecond race checks. Add native NTFS lifecycle coverage for #2927; retain ambiguous legacy-state refusal without claiming Windows PID-reuse recovery is resolved.

* fix(redact): bind pre-push scans to destination and preserve seam context

Uses #2935 (bd07318) as source evidence for push-target range and slice-overlap defects. Independently implemented; no cherry-pick or release metadata adoption.

* test(ci): gate native agent ownership and settings links on macOS

* fix(browse): bind agent lifetimes and cleanup to owned generations

Uses #2931 by Chris Hutton / Claude Fable 5.1 as attributed design input; independently implemented without broad sweeps or copied code. Keep uncertain children and locks rather than deleting foreign state.

* test(ci): include concurrent shutdown controls in the native macOS gate

* v1.88.1.0 fix: harden credential boundaries and owned state

* fix(redact): preserve target provenance and scan boundary semantics

* test(artifacts): read managed rules from atomic allowlist assembly

* fix: preserve native exit observations and fixture prerequisites

* fix: preserve UTF-16 offsets through redaction normalization
This commit is contained in:
Garry Tan
2026-09-23 08:54:53 -04:00
committed by GitHub
parent 636175d349
commit b9706f3635
42 changed files with 2719 additions and 339 deletions
+43
View File
@@ -116,6 +116,49 @@ describe('buildHermeticEnv allowlist', () => {
expect(e.GH_TOKEN).toBeUndefined(); // not in extraAllow
});
test('prefixes keep CI metadata but do not admit credential-shaped operator names', () => {
const base = {
...CONTAMINATED,
GITHUB_TOKEN: 'synthetic-token',
GITHUB_PERSONAL_ACCESS_TOKEN: 'synthetic-pat',
GITHUB_APP_PRIVATE_KEY: 'synthetic-private-key',
GITHUB_CLIENT_SECRET: 'synthetic-client-secret',
GITHUB_PAT: 'synthetic-pat-short',
EVALS_API_KEY: 'synthetic-eval-key',
GITHUB_SHA: 'abc123',
GITHUB_PATH: '/tmp/actions-path',
GITHUB_TOKENIZER: 'metadata-tokenizer',
GITHUB_KEYRING: 'metadata-keyring',
EVALS_RUN_ID: 'run-123',
EVALS_SELECTION_JSON: '{}',
};
const result = buildHermeticEnv(base, HERMETIC_VARS);
for (const name of [
'GITHUB_TOKEN', 'GITHUB_PERSONAL_ACCESS_TOKEN', 'GITHUB_APP_PRIVATE_KEY',
'GITHUB_CLIENT_SECRET', 'GITHUB_PAT', 'EVALS_API_KEY', 'GH_TOKEN',
]) expect(result[name]).toBeUndefined();
for (const name of [
'GITHUB_ACTIONS', 'GITHUB_SHA', 'GITHUB_PATH', 'GITHUB_TOKENIZER',
'GITHUB_KEYRING', 'EVALS_MODEL', 'EVALS_RUN_ID', 'EVALS_SELECTION_JSON',
]) expect(result[name]).toBe(base[name]);
});
test('explicit provider auth, runner admissions, and overrides still win', () => {
const base = {
...CONTAMINATED,
GITHUB_TOKEN: 'synthetic-token',
GEMINI_API_KEY: 'synthetic-gemini',
};
const result = buildHermeticEnv(base, HERMETIC_VARS, {
GITHUB_APP_PRIVATE_KEY: 'synthetic-override',
}, { extraAllow: ['GEMINI_*', 'GITHUB_TOKEN'] });
expect(result.ANTHROPIC_API_KEY).toBe(base.ANTHROPIC_API_KEY);
expect(result.GEMINI_API_KEY).toBe(base.GEMINI_API_KEY);
expect(result.GITHUB_TOKEN).toBe(base.GITHUB_TOKEN);
expect(result.GITHUB_APP_PRIVATE_KEY).toBe('synthetic-override');
expect(buildHermeticEnv(base, HERMETIC_VARS).GITHUB_TOKEN).toBeUndefined();
});
test('TERM falls back when base omits it', () => {
const base = { ...CONTAMINATED } as NodeJS.ProcessEnv;
delete base.TERM;