Merge current master into Codex provider

# Conflicts:
#	docs/capability-seams.md
This commit is contained in:
pku-xht
2026-08-05 02:21:49 +08:00
213 changed files with 7278 additions and 684 deletions

View File

@@ -45,7 +45,10 @@ export const SENSITIVE_ENV_PATTERN = /KEY|PASSWORD|SECRET|TOKEN/i
* `HOME`, locale, and proxy variables survive, so child CLIs run normally;
* harness identity never leaks implicitly (a deliberately forwarded
* credential or current `DSH_*` fact goes through the spec's explicit `env`,
* which merges after this scrub). Exported as a plain function so spawners
* which merges after this scrub). Both scrubs match case-insensitively:
* Windows environment names are case-insensitive, so a parent `dsh_*` entry
* would otherwise survive and read back as `$env:DSH_*` in the child;
* deliberate lowercase `dsh_*` names on POSIX are implausible. Exported as a plain function so spawners
* that cannot route through the service (node-pty backends, SDK-managed
* transports) share the one scrub definition.
* @returns a fresh environment object safe to hand to a child spawn.
@@ -53,7 +56,7 @@ export const SENSITIVE_ENV_PATTERN = /KEY|PASSWORD|SECRET|TOKEN/i
export function scrubbedParentEnv(): Record<string, string> {
const env: Record<string, string> = {}
for (const [key, value] of Object.entries(process.env)) {
if (value !== undefined && !SENSITIVE_ENV_PATTERN.test(key) && !key.startsWith(DSH_ENV_PREFIX)) env[key] = value
if (value !== undefined && !SENSITIVE_ENV_PATTERN.test(key) && !key.toUpperCase().startsWith(DSH_ENV_PREFIX)) env[key] = value
}
return env
}

View File

@@ -52,20 +52,23 @@ describe('SubprocessService seam', () => {
await expect(ctx.plugin(SecondService)).rejects.toThrow(/service "subprocess" has been registered/)
})
it('scrubbedParentEnv drops credential-shaped and DSH_ names but keeps PATH', () => {
it('scrubbedParentEnv drops credential-shaped and DSH_ names (case-insensitively) but keeps PATH', () => {
process.env.DSH_SCRUB_PROBE = 'stale'
process.env.dsh_scrub_probe_lower = 'stale'
process.env.SCRUB_PROBE_TOKEN = 'secret'
process.env.SCRUB_PROBE_PASSWORD = 'secret'
process.env.SCRUB_PROBE_PLAIN = 'visible'
try {
const env = scrubbedParentEnv()
expect(env.DSH_SCRUB_PROBE).toBeUndefined()
expect(env.dsh_scrub_probe_lower).toBeUndefined()
expect(env.SCRUB_PROBE_TOKEN).toBeUndefined()
expect(env.SCRUB_PROBE_PASSWORD).toBeUndefined()
expect(env.SCRUB_PROBE_PLAIN).toBe('visible')
expect(env.PATH).toBeDefined()
} finally {
delete process.env.DSH_SCRUB_PROBE
delete process.env.dsh_scrub_probe_lower
delete process.env.SCRUB_PROBE_TOKEN
delete process.env.SCRUB_PROBE_PASSWORD
delete process.env.SCRUB_PROBE_PLAIN