Files
deepseek-harness/packages/bash/bash-sandbox/tests/landlock.e2e.ts
imccyu ec601ca13d build(vendor): rescope the vendored Cordis packages into @deepseek-ai
Machine-produced by `pnpm run rescope-vendor --apply` plus the regeneration it
prints: `pnpm install` for the lockfile, `pnpm run gen-third-party-notices`,
`verify-translation-pairing --write` for the touched bilingual pairs,
`gen-doc-graphs`, and one typert snapshot whose ids embed character offsets.
`pnpm run rescope-vendor --check` verifies the result.

Renames nine vendored packages (cordis, cosmokit, schemastery and the six
@cordisjs plugins) and every reference that resolves them: manifest names and
dependency keys, module specifiers including declare-module merges, cordis.yml
plugin names, tsconfig paths, every Markdown fence, and `docs/` prose.
Directory names, upstream versions, and dependency ranges are unchanged, so
vendor/README.md still reads as an upstream snapshot; its manifest table gains
an upstream-name column so THIRD_PARTY_NOTICES keeps MIT attribution pointed
at each fork's origin.

The tutorial tier follows the rename end to end: its yaml fences named plugins
the Loader can no longer resolve, its `ts ignore-check` fences disagreed with
the compiled fences beside them, and its prose quoted both. The contracts that
told readers to keep upstream names — the root convention and the vendoring
cookbook's tree comment and manifest invariant — now say to rescope instead.

Two rules read `@deepseek-ai/` as "another workspace plugin": the client bundle
purity gate now names the vendored libraries a browser bundle inlines, and the
files where a bare `cordis` is an agent-preset id keep that product data.
2026-08-10 22:04:13 +08:00

105 lines
5.2 KiB
TypeScript

import { spawnSync } from 'node:child_process'
import { existsSync, readFileSync } from 'node:fs'
import { mkdtemp, rm } from 'node:fs/promises'
import { homedir, tmpdir } from 'node:os'
import { join } from 'node:path'
import { afterEach, describe, expect, it } from 'vitest'
import { Context } from '@deepseek-ai/cordis'
import { launcherPath } from '@deepseek-ai/node-addon-landlock-run'
import { LocalSandboxProvider } from '@deepseek-ai/dsh-sandbox-local'
import { SandboxPolicyService } from '@deepseek-ai/dsh-sandbox-policy'
import { SandboxBashExecutor } from '@deepseek-ai/dsh-bash-sandbox'
import LocalSubprocessService from '@deepseek-ai/dsh-subprocess-local'
/**
* KEYLESS consumer-integration proof: the REAL `LocalSandboxProvider` (bwrap
* rung forced off, so the workspace `landlock-run` launcher confines) underneath the
* REAL `SandboxBashExecutor`, driven through the executor's public run/start
* paths. Verifies the WORLD (files exist or don't) plus the stamped result
* facts; the backend-only confinement proofs live with
* `@deepseek-ai/dsh-sandbox-local`.
*
* Self-skips when the running kernel does not enforce Landlock. CI builds the launcher from
* `native/landlock-run` before running this file.
*/
const probe = spawnSync(launcherPath(), ['--probe'], { timeout: 5_000, encoding: 'utf8' })
const landlockUsable = probe.status === 0
/** The kernel's enforcement level from the probe report — stamped facts below must match it. */
const enforcement = /partially enforced/.test(probe.stdout ?? '') ? 'partial' : 'full'
let ctx: Context | undefined
const tempDirs: string[] = []
afterEach(async () => {
await ctx?.fiber.dispose()
ctx = undefined
await Promise.all(tempDirs.splice(0).map(dir => rm(dir, { recursive: true, force: true })))
})
async function tempDir(base: string): Promise<string> {
const dir = await mkdtemp(join(base, 'dsh-landlock-e2e-'))
tempDirs.push(dir)
return dir
}
async function sandboxedBash(workspace: string, mode: 'read-only' | 'workspace-write'): Promise<SandboxBashExecutor> {
ctx = new Context()
await ctx.plugin(LocalSandboxProvider, {})
;(ctx.sandbox as LocalSandboxProvider).internals = { probeBwrap: () => false }
await ctx.plugin(SandboxPolicyService, { mode, workspaceRoot: workspace })
await ctx.plugin(LocalSubprocessService)
await ctx.plugin(SandboxBashExecutor, { cwd: workspace, timeoutMs: 30_000 })
return ctx.bash as SandboxBashExecutor
}
describe.skipIf(!landlockUsable)('bash-sandbox: real Landlock confinement through ctx.bash', () => {
it('read-only denies a write — the file must NOT exist, the result carries denial + enforcement facts', async () => {
const workdir = await tempDir(tmpdir())
const bash = await sandboxedBash(workdir, 'read-only')
const result = await bash.run(bash.resolve({ command: `echo hi > ${workdir}/denied.txt` }))
expect(result.exitCode).not.toBe(0)
expect(result.sandbox).toEqual({ mode: 'read-only', denied: true, enforcement })
expect(existsSync(join(workdir, 'denied.txt'))).toBe(false)
})
it('workspace-write lands a write inside the workspace root and still denies one beside it', async () => {
const workdir = await tempDir(homedir())
const outside = await tempDir(homedir())
const bash = await sandboxedBash(workdir, 'workspace-write')
const inside = await bash.run(bash.resolve({ command: `printf landlock-ok > ${workdir}/allowed.txt` }))
expect(inside.exitCode).toBe(0)
expect(inside.sandbox).toEqual({ mode: 'workspace-write', denied: false, enforcement })
expect(readFileSync(join(workdir, 'allowed.txt'), 'utf8')).toBe('landlock-ok')
const denied = await bash.run(bash.resolve({ command: `echo hi > ${outside}/denied.txt` }))
expect(denied.exitCode).not.toBe(0)
expect(denied.sandbox).toEqual({ mode: 'workspace-write', denied: true, enforcement })
expect(existsSync(join(outside, 'denied.txt'))).toBe(false)
})
it('classifies a background denial once the task settles', async () => {
const workdir = await tempDir(homedir())
const bash = await sandboxedBash(workdir, 'read-only')
const task = bash.start(bash.resolve({ command: `echo hi > ${workdir}/bg-denied.txt` }))
await task.done
expect(task.sandbox).toEqual({ mode: 'read-only', denied: true, enforcement })
expect(existsSync(join(workdir, 'bg-denied.txt'))).toBe(false)
})
it('an approved escalated retry — the spec-level workspace-write override — lands the exact write read-only denied', async () => {
const workdir = await tempDir(homedir())
const bash = await sandboxedBash(workdir, 'read-only')
const command = `printf escalated > ${workdir}/escalated.txt`
const strict = await bash.run(bash.resolve({ command }))
expect(strict.exitCode).not.toBe(0)
expect(strict.sandbox).toEqual({ mode: 'read-only', denied: true, enforcement: enforcement })
expect(existsSync(join(workdir, 'escalated.txt'))).toBe(false)
const retried = await bash.run(bash.resolve({ command, sandboxPolicy: { mode: 'workspace-write', workspaceRoot: workdir } }))
expect(retried.exitCode).toBe(0)
expect(retried.sandbox).toEqual({ mode: 'workspace-write', denied: false, enforcement: enforcement })
expect(readFileSync(join(workdir, 'escalated.txt'), 'utf8')).toBe('escalated')
})
})