fix(sandbox): evidence-gate runner failures (round 1)

This commit is contained in:
Hypatia May
2026-08-03 17:31:08 +08:00
parent 6a3caea277
commit 6343d8f6e6
51 changed files with 805 additions and 140 deletions

View File

@@ -0,0 +1,38 @@
# Keyless partial-Landlock composition: replay the authored model turns and
# replace the shipping provider with a deterministic older-ABI stand-in.
- id: base
name: '@cordisjs/plugin-include'
config:
path: ./cordis.yml
patches:
- id: llm-deepseek
name: '@deepseek-ai/dsh-llm-deepseek'
disabled: true
- id: sandbox
name: '@deepseek-ai/dsh-sandbox-local'
disabled: true
- id: acp-agent
name: '@deepseek-ai/dsh-acp-demo'
config:
provider: deepseek-official
model: deepseek-v4-flash
persistenceRoot: !!js process.env.DSH_SNAPSHOT_SESSIONS_ROOT ?? './.sessions'
persistenceCompression: none
workspaceContext:
maxBytes: 65536
persona: |
You are a coding assistant powered by the {{model}} model. Your working directory is {{cwd}}. Your bash tool runs under a file sandbox — a `[sandbox: file access denied …]` result is policy, not a command bug.
Verify your work by running the code or tests. Keep answers brief and factual.
- insert:
- id: llm-replay
name: '@deepseek-ai/dsh-llm-replay'
config:
providers:
- id: deepseek-official
name: DeepSeek
models:
- id: deepseek-v4-flash
- id: deepseek-v4-pro
- id: partial-landlock-sandbox
name: './tests/fixtures/partial-landlock-sandbox.ts'

View File

@@ -0,0 +1,13 @@
# Live counterpart for the partial-Landlock snapshot overlay. It replaces only
# the sandbox provider; the authored scenario is skipped in record mode.
- id: base
name: '@cordisjs/plugin-include'
config:
path: ./cordis.yml
patches:
- id: sandbox
name: '@deepseek-ai/dsh-sandbox-local'
disabled: true
- insert:
- id: partial-landlock-sandbox
name: './tests/fixtures/partial-landlock-sandbox.ts'

View File

@@ -47,6 +47,7 @@ const SUBAGENT_DURABILITY_FAILURE_CONFIG = fileURLToPath(
const LSP_CONFIG = fileURLToPath(new URL('./lsp.cordis.yml', import.meta.url))
const WEB_CONFIG = fileURLToPath(new URL('../web.cordis.yml', import.meta.url))
const FS_SEARCH_CONFIG = fileURLToPath(new URL('./fs-search.cordis.yml', import.meta.url))
const PARTIAL_LANDLOCK_CONFIG = fileURLToPath(new URL('../partial-landlock.cordis.yml', import.meta.url))
const FS_SEARCH_BIN = fileURLToPath(new URL('./fixtures/fs-search-bin', import.meta.url))
const SNAPSHOTS_DIR = join(dirname(fileURLToPath(import.meta.url)), 'snapshots')
const PACKED_CHUNKS_SOURCE = 'hook-cc-pretool-deny'
@@ -131,6 +132,18 @@ const SCENARIOS: Scenario[] = [
configPath: PTY_CONFIG,
},
{ name: 'bash-tool-turn', hasModelTurn: true, recorded: true },
// Authored keyless replay through a test-only partial-Landlock provider:
// the exact compatibility notice must stay ordinary stderr when the wrapped
// `false` command exits 1, rather than becoming SANDBOX_UNAVAILABLE.
{
name: 'partial-landlock-child-failure',
hasModelTurn: true,
recorded: false,
headerClass: 'sandbox',
configPath: PARTIAL_LANDLOCK_CONFIG,
env: { DSH_PERMISSION_MODE: 'read-only' },
posixOnly: true,
},
{ name: 'todo-write', hasModelTurn: true, recorded: true },
{
name: 'skill-load',

View File

@@ -0,0 +1,26 @@
import type { ConfinedArgv, SandboxPolicy } from '@deepseek-ai/dsh-sandbox'
import { SandboxProvider } from '@deepseek-ai/dsh-sandbox'
const NOTICE = 'landlock-run: partial enforcement (older Landlock ABI)'
/** Snapshot-only provider that reproduces an older-ABI Landlock launch. */
export default class PartialLandlockSandboxProvider extends SandboxProvider {
confine(argv: readonly string[], _policy: SandboxPolicy): ConfinedArgv {
return {
argv: [
'bash',
'-c',
`printf '%s\\n' '${NOTICE}' >&2; exec "$@"`,
'partial-landlock-run',
...argv,
],
enforcement: 'partial',
denialSignatures: ['permission denied'],
runnerFailureRules: [{
allowedExitCodes: [125],
fatalSignatures: ['landlock-run: '],
informationalLines: [NOTICE],
}],
}
}
}

View File

@@ -0,0 +1,7 @@
{
"steps": [
{ "op": "initialize" },
{ "op": "newSession" },
{ "op": "prompt", "text": "Use the bash tool to run exactly: false. Then reply with exactly CHILD_EXIT_PRESERVED and stop." }
]
}

View File

@@ -0,0 +1,26 @@
{"type":"session","version":0,"id":"44444444-4444-4444-8444-444444444444","createdAt":1785218500000,"cwd":"{{cwd}}","delegationDepth":0}
{"type":"turn/start","seq":0,"time":1785218500001,"data":{"turn":1,"trigger":{"kind":"message","source":{"kind":"user"}}}}
{"type":"user/message","seq":1,"time":1785218500002,"data":{"content":[{"type":"text","text":"Use the bash tool to run exactly: false. Then reply with exactly CHILD_EXIT_PRESERVED and stop."}],"source":{"kind":"user"},"role":"user","id":"44444444-4444-4444-8444-444444444445"},"surfaceOp":"append"}
{"type":"session/title","seq":2,"time":1785218500003,"data":{"title":"Use the bash tool to","messageSeqs":[1],"source":{"kind":"fallback"}}}
{"type":"user/message","seq":3,"time":1785218500004,"data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent DSH file policy: read-only. Any available operation enforced by the DSH file sandbox cannot modify files in the standing mode. Do not refuse a required modification from this policy alone: try an available tool normally and follow any denial and escalation guidance it returns.\n\nApproval policy: ask. Operations that require approval may ask through the configured answerers; without an available answerer, the request fails closed."}],"source":{"kind":"plugin","plugin":"@deepseek-ai/dsh-system-prompt"},"role":"user","id":"44444444-4444-4444-8444-444444444446"},"surfaceOp":"append"}
{"type":"step/start","seq":4,"time":1785218500005,"data":{"turn":1,"step":1}}
{"type":"request/header","seq":5,"time":1785218500006,"data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-flash"},"system":"{{system}}","tools":"{{tools}}"},"reason":"initial"}}
{"type":"request/context","seq":6,"time":1785218500007,"data":{"provider":"deepseek-official","model":"deepseek-v4-flash"}}
{"type":"assistant/chunk","seq":7,"time":1785218500008,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}}}
{"type":"assistant/chunk","seq":8,"time":1785218500009,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":0,"id":"partial-landlock-call","name":"bash","argumentsDelta":"{\"command\":\"false\",\"description\":\"Exit with status one\"}"}}}
{"type":"assistant/chunk","seq":9,"time":1785218500010,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"partial-landlock-call","name":"bash","arguments":"{\"command\":\"false\",\"description\":\"Exit with status one\"}"}}}}
{"type":"assistant/chunk","seq":10,"time":1785218500011,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":1,"outputTokens":1}}}}
{"type":"assistant/chunk","seq":11,"time":1785218500012,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}}
{"type":"assistant/message","seq":12,"time":1785218500013,"data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"partial-landlock-call","name":"bash","arguments":"{\"command\":\"false\",\"description\":\"Exit with status one\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"44444444-4444-4444-8444-444444444447"},"usage":{"inputTokens":1,"outputTokens":1}},"sourceEventSeqs":[7,8,9,10,11],"surfaceOp":"append"}
{"type":"tool/call","seq":13,"time":1785218500014,"data":{"turn":1,"step":1,"callId":"partial-landlock-call","name":"bash","arguments":"{\"command\":\"false\",\"description\":\"Exit with status one\"}"}}
{"type":"tool/result","seq":14,"time":1785218500015,"data":{"turn":1,"step":1,"message":{"source":{"kind":"tool","callId":"partial-landlock-call"},"content":[{"type":"tool-result","toolCallId":"partial-landlock-call","content":[{"type":"text","text":"[stderr]\nlandlock-run: partial enforcement (older Landlock ABI)\n[exit code: 1]"}],"isError":false}],"role":"user","id":"44444444-4444-4444-8444-444444444448"}},"sourceEventSeqs":[13],"surfaceOp":"append"}
{"type":"step/end","seq":15,"time":1785218500016,"data":{"turn":1,"step":1}}
{"type":"step/start","seq":16,"time":1785218500017,"data":{"turn":1,"step":2}}
{"type":"assistant/chunk","seq":17,"time":1785218500018,"data":{"turn":1,"step":2,"chunk":{"type":"block-start","index":0,"blockType":"text"}}}
{"type":"assistant/chunk","seq":18,"time":1785218500019,"data":{"turn":1,"step":2,"chunk":{"type":"text-delta","index":0,"text":"CHILD_EXIT_PRESERVED"}}}
{"type":"assistant/chunk","seq":19,"time":1785218500020,"data":{"turn":1,"step":2,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"CHILD_EXIT_PRESERVED"}}}}
{"type":"assistant/chunk","seq":20,"time":1785218500021,"data":{"turn":1,"step":2,"chunk":{"type":"usage","usage":{"inputTokens":1,"outputTokens":1}}}}
{"type":"assistant/chunk","seq":21,"time":1785218500022,"data":{"turn":1,"step":2,"chunk":{"type":"finish","reason":{"kind":"stop"}}}}
{"type":"assistant/message","seq":22,"time":1785218500023,"data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"text","text":"CHILD_EXIT_PRESERVED"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-flash"},"id":"44444444-4444-4444-8444-444444444449"},"usage":{"inputTokens":1,"outputTokens":1}},"sourceEventSeqs":[17,18,19,20,21],"surfaceOp":"append"}
{"type":"step/end","seq":23,"time":1785218500024,"data":{"turn":1,"step":2}}
{"type":"turn/end","seq":24,"time":1785218500025,"data":{"turn":1,"reason":{"kind":"completed"}}}

View File

@@ -0,0 +1,4 @@
{"jsonrpc":"2.0","id":1,"result":{"protocolVersion":1,"agentInfo":{"name":"deepseek-harness-acp","version":"0.0.1"},"agentCapabilities":{"promptCapabilities":{"image":false,"audio":false,"embeddedContext":false}},"authMethods":[]}}
{"jsonrpc":"2.0","id":2,"result":{"sessionId":"{{sessionId}}"}}
{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"CHILD_EXIT_PRESERVED"}}}}
{"jsonrpc":"2.0","id":3,"result":{"stopReason":"end_turn"}}