mirror of
https://github.com/stablyai/orca.git
synced 2026-10-24 00:04:01 +00:00
fix(terminal): restore only the WSLENV names the credential guard forwards
The guard forwards `GIT_TERMINAL_PROMPT`, `GCM_INTERACTIVE` and the indexed config protocol into WSLENV -- never `GIT_ASKPASS`/`SSH_ASKPASS`. Restoration removed all four scalars, so a WSLENV token the guard never added was stripped from an unguarded child purely because it postdated the pre-guard snapshot, destroying the user's own WSL forwarding. Both sides now read one exported constant, so the ratchet keeps them coupled.
This commit is contained in:
@@ -98,6 +98,26 @@ describe('restoreUnguardedGitCredentialEnv marker handling', () => {
|
||||
expect(env.GIT_CONFIG_KEY_1).toBe('credential.guiPrompt')
|
||||
})
|
||||
|
||||
// The guard forwards only its scalars and the indexed-config protocol into
|
||||
// WSLENV -- never the askpass names. Removing a name the guard never added
|
||||
// strips the user's own WSL forwarding, which is the leak's mirror image.
|
||||
it('keeps a WSLENV name the guard never forwards, even when it appeared after the guard', () => {
|
||||
const saved = takeGitCredentialGuardEnv()
|
||||
try {
|
||||
const env: Record<string, string> = { WSLENV: 'MY_VAR/u' }
|
||||
const pre = captureGitCredentialGuardPreGuardState(env)
|
||||
Object.assign(env, gitCredentialPromptGuardEnv(env, 'win32') as Record<string, string>)
|
||||
recordGitCredentialGuardProvenance(env, pre, { appendedConfig: true, forwardToWsl: true })
|
||||
// The user forwards their own askpass into WSL from inside the guarded pane.
|
||||
env.WSLENV = `${env.WSLENV}:GIT_ASKPASS/p`
|
||||
|
||||
expect(restoreUnguardedGitCredentialEnv(env)).toBe(true)
|
||||
expect(env.WSLENV).toBe('MY_VAR/u:GIT_ASKPASS/p')
|
||||
} finally {
|
||||
restoreGitCredentialGuardEnv(saved)
|
||||
}
|
||||
})
|
||||
|
||||
// A marker that names no config base did not append config, so nothing indexed
|
||||
// in this environment is Orca's — including a pair that looks exactly like ours.
|
||||
it('never removes indexed config when the marker claims no config base', () => {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {
|
||||
GIT_CREDENTIAL_GUARD_CONFIG_ENTRIES,
|
||||
GIT_CREDENTIAL_GUARD_WSLENV_SCALAR_KEYS,
|
||||
readValidGitConfigEnvCount
|
||||
} from './git-credential-prompt-env'
|
||||
import { addWslEnvKeys } from './wsl-env'
|
||||
@@ -187,9 +188,11 @@ function restoreWslEnv(env: Record<string, string>, state: RestoreState): void {
|
||||
if (priorNames.has(name)) {
|
||||
return true
|
||||
}
|
||||
// Why: the guard never forwards the askpass names, so a WSLENV token it
|
||||
// never added is the user's even when it postdates the pre-guard snapshot.
|
||||
return !(
|
||||
name === TERMINAL_GIT_CREDENTIAL_GUARD_RESTORE_ENV ||
|
||||
(SCALAR_KEYS as readonly string[]).includes(name) ||
|
||||
(GIT_CREDENTIAL_GUARD_WSLENV_SCALAR_KEYS as readonly string[]).includes(name) ||
|
||||
GIT_CONFIG_PROTOCOL_KEY_RE.test(name)
|
||||
)
|
||||
})
|
||||
|
||||
@@ -89,6 +89,15 @@ export const GIT_CREDENTIAL_GUARD_CONFIG_ENTRIES = [
|
||||
['credential.guiPrompt', 'false']
|
||||
] as const satisfies readonly (readonly [key: string, value: string])[]
|
||||
|
||||
/**
|
||||
* The scalar guard variables the guard forwards into WSL. Provenance reads it so
|
||||
* restoration removes exactly the names the guard adds to WSLENV and no others.
|
||||
*/
|
||||
export const GIT_CREDENTIAL_GUARD_WSLENV_SCALAR_KEYS = [
|
||||
'GIT_TERMINAL_PROMPT',
|
||||
'GCM_INTERACTIVE'
|
||||
] as const
|
||||
|
||||
/**
|
||||
* Disable interactive Git credential UI while preserving cached credentials
|
||||
* and caller-provided askpass programs.
|
||||
@@ -115,7 +124,7 @@ export function gitCredentialPromptGuardEnv(
|
||||
readValidGitConfigEnvCount(next) === null
|
||||
? []
|
||||
: Object.keys(next).filter((key) => GIT_CONFIG_WSLENV_KEY_RE.test(key))
|
||||
addWslEnvKeys(next, ['GIT_TERMINAL_PROMPT', 'GCM_INTERACTIVE', ...configKeys])
|
||||
addWslEnvKeys(next, [...GIT_CREDENTIAL_GUARD_WSLENV_SCALAR_KEYS, ...configKeys])
|
||||
}
|
||||
return next
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user