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:
Yichen Jiang
2026-07-30 17:09:42 +08:00
parent 52ae578982
commit a90ccc4453
27 changed files with 38 additions and 262 deletions

View File

@@ -1027,22 +1027,12 @@ export interface Config {
* `process.cwd()`). Normal agent calls use their session cwd instead.
*/
workspaceRoot?: string
/**
* Absolute paths confined executions must not read, whatever their mode
* otherwise permits. Omitted (or empty) denies the harness home's
* credential document (`$DSH_HOME/.env`) — exactly that file, so the model
* keeps the documented access to its own session log under the same home;
* a non-empty list replaces it. Backends that cannot express a read denial
* report `partial` enforcement instead of pretending, and
* `danger-full-access` confines nothing, so no denial applies there at all.
*/
readDenyPaths?: string[]
}
```
Depends on: [`SandboxMode`](core-data-structures/sandbox.md)
Source: [`packages/sandbox/sandbox-policy/src/index.ts:45`](../packages/sandbox/sandbox-policy/src/index.ts)
Source: [`packages/sandbox/sandbox-policy/src/index.ts:44`](../packages/sandbox/sandbox-policy/src/index.ts)
## `@deepseek-ai/dsh-session-persistence-jsonl`