revert(sandbox): withdraw the credential-document read denial
The `readDenyPaths` policy field shipped in the previous commit broke Linux confinement outright. bwrap has to create the `/dev/null` bind's mount point inside a tree its own profile has already made read-only, so it refused the entire confinement whenever the parent directory was absent — every host that has not stored a credential yet, including a fresh install: bwrap: Can't mkdir parents for /home/runner/.dsh/.env: Read-only file system which the executor correctly classifies as SANDBOX_UNAVAILABLE, so every confined bash call failed closed. Landlock cannot subtract from its own `/` read grant, so it reported `partial` enforcement on every confined call for a file it never hid, with no way to switch the denial off (schemastery fills an omitted array with `[]`, so empty and omitted were indistinguishable). A protection that breaks confinement where it works and misreports it where it does not is worse than a documented absence. Revert the field, both expressible backends, the enforcement downgrade, and the policy default; state the residue plainly in the credentials-local READMEs — file mode stops other OS users, not the model — and keep the OS-keychain provider recorded as the real answer. The narrower discipline stands: no surface hoists the credential document into `process.env`, and the model is never handed a resolved path to it.
This commit is contained in:
@@ -11,7 +11,6 @@ import { join, resolve } from 'node:path'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import { Context } from 'cordis'
|
||||
import type { BashRunResult, CollectedOutput } from '@deepseek-ai/dsh-bash'
|
||||
import { resolveDshHome } from '@deepseek-ai/dsh-paths'
|
||||
import { SANDBOX_UNAVAILABLE, SandboxProvider, SandboxUnavailableError } from '@deepseek-ai/dsh-sandbox'
|
||||
import type { ConfinedArgv, SandboxExecutionPolicy, SandboxMode, SandboxPolicy } from '@deepseek-ai/dsh-sandbox'
|
||||
import { SandboxPolicyService } from '@deepseek-ai/dsh-sandbox-policy'
|
||||
@@ -75,11 +74,8 @@ function runResult(exitCode: number | null, stderr: string): BashRunResult {
|
||||
return { exitCode, signal: null, timedOut: false, aborted: false, timeoutMs: 1000, stdout: output(''), stderr: output(stderr) }
|
||||
}
|
||||
|
||||
/** The policy home's default read denial: the harness credential document. */
|
||||
const DEFAULT_DENY = [resolve(resolveDshHome(), '.env')]
|
||||
|
||||
function executionPolicy(mode: SandboxMode, workspaceRoot = resolve(process.cwd())): SandboxExecutionPolicy {
|
||||
return { mode, workspaceRoot, readDenyPaths: DEFAULT_DENY }
|
||||
return { mode, workspaceRoot }
|
||||
}
|
||||
|
||||
describe('the provider hand-off', () => {
|
||||
@@ -90,7 +86,7 @@ describe('the provider hand-off', () => {
|
||||
expect(result.sandbox).toEqual({ mode: 'read-only', denied: false, enforcement: 'full' })
|
||||
expect(calls).toEqual([{
|
||||
argv: ['bash', '-c', 'echo \'a b\' "c\'d"'],
|
||||
policy: { mode: 'read-only', workspaceRoot: resolve(process.cwd()), readDenyPaths: DEFAULT_DENY },
|
||||
policy: { mode: 'read-only', workspaceRoot: resolve(process.cwd()) },
|
||||
}])
|
||||
})
|
||||
|
||||
@@ -107,7 +103,7 @@ describe('the provider hand-off', () => {
|
||||
const { bash, calls } = await setup({ mode: 'workspace-write' })
|
||||
const result = await bash.run(bash.resolve({ command: 'true' }))
|
||||
expect(result.sandbox).toEqual({ mode: 'workspace-write', denied: false, enforcement: 'full' })
|
||||
expect(calls[0]?.policy).toEqual({ mode: 'workspace-write', workspaceRoot: resolve(process.cwd()), readDenyPaths: DEFAULT_DENY })
|
||||
expect(calls[0]?.policy).toEqual({ mode: 'workspace-write', workspaceRoot: resolve(process.cwd()) })
|
||||
})
|
||||
|
||||
it('an explicit workspaceRoot on the policy wins', async () => {
|
||||
|
||||
Reference in New Issue
Block a user