forked from EduCraft/curriculum-project-hub
fix: prove Linux Agent sandbox boundary
This commit is contained in:
@@ -25,7 +25,7 @@ unit is written or enabled.
|
||||
Preflight validates the configured bind host/port, authenticated PostgreSQL
|
||||
access, Node/cph/Prisma, configured and canonical path traversal, and a real
|
||||
bubblewrap namespace. The post-provision phase runs the built Hub dependency
|
||||
graph, a database query, cph and bubblewrap as the service user under
|
||||
graph, a database query, cph, socat and bubblewrap as the service user under
|
||||
`no_new_privs`, matching the systemd security context. HTTP binding is awaited
|
||||
before the Feishu listener starts, so bind failure rejects startup instead of
|
||||
leaving a listener-only process alive.
|
||||
|
||||
+27
-1
@@ -1,7 +1,7 @@
|
||||
# Confine the agent runtime and protect service credentials
|
||||
|
||||
Type: task
|
||||
Status: claimed
|
||||
Status: resolved
|
||||
|
||||
## Question
|
||||
|
||||
@@ -10,3 +10,29 @@ deny sibling tenant workspaces and service files, expose only the minimum safe
|
||||
process environment, use SDK credential protection for secrets, and add an
|
||||
actual Linux sandbox test proving another workspace and every non-provider
|
||||
credential are unreadable while required tools still work.
|
||||
|
||||
## Answer
|
||||
|
||||
The Agent subprocess now receives a replacement environment containing only
|
||||
named runtime values and the selected provider protocol values; PostgreSQL,
|
||||
Feishu and Hub session credentials never cross the process boundary. Provider
|
||||
credentials are additionally denied inside Bash. The SDK must sandbox every
|
||||
command (`failIfUnavailable=true`, `allowUnsandboxedCommands=false`), denies
|
||||
host reads and writes from root, and re-opens only the canonical project
|
||||
workspace plus the reviewed read-only system runtime needed by `cph`.
|
||||
|
||||
SDK config/cache/home and general temp storage live inside the workspace. A
|
||||
short relative `CLAUDE_CODE_TMPDIR` prevents the pinned SDK from falling back
|
||||
to host `/tmp`, while absolute workspace-local `TMPDIR`/`TMP`/`TEMP` remain
|
||||
stable after Bash changes directory. Linux production and CI now require both
|
||||
bubblewrap and `socat`; preflight probes both as the service user. Bounded,
|
||||
credential-redacted SDK stderr is logged with run and project correlation.
|
||||
|
||||
The real Linux proof runs the actual Claude SDK, Bash, bubblewrap, `socat` and
|
||||
release `cph` as UID 1000 with no capabilities and `no_new_privs`. It proves
|
||||
parent, sibling-project, `/tmp` and `/var/tmp` writes are rejected and have no
|
||||
host effect; sibling/service-secret reads fail; platform and provider secrets
|
||||
are absent from Bash; workspace temp remains anchored after `cd`; and `cph`
|
||||
still executes. Final local gates passed: TypeScript check/build, Prisma schema,
|
||||
173 unit tests, 85 mock-provider integration tests, deployment shell syntax,
|
||||
and the dedicated Linux sandbox test.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Close MCP context and file-delivery escape paths
|
||||
|
||||
Type: task
|
||||
Status: claimed
|
||||
Status: resolved
|
||||
|
||||
## Question
|
||||
|
||||
@@ -9,3 +9,20 @@ Restrict file delivery to a realpath/no-follow target inside the current project
|
||||
workspace, remove Git-root access, make inbound Hub writes symlink-safe, and
|
||||
validate every Feishu message/thread result against the run's bound chat before
|
||||
returning data to the model.
|
||||
|
||||
## Answer
|
||||
|
||||
All Agent-facing workspace file reads and writes are anchored to the configured
|
||||
workspace root and current project. Linux uses descriptor-relative, no-follow
|
||||
traversal so a symlink swap cannot escape after validation; unsupported unsafe
|
||||
paths fail closed. Inbound Feishu files use the same boundary. Outbound file
|
||||
delivery no longer accepts the repository Git root or arbitrary absolute
|
||||
paths: it reads a no-follow snapshot from the current project and uploads that
|
||||
snapshot, so the checked object cannot be swapped before delivery.
|
||||
|
||||
The Feishu MCP read surface carries the run's project and bound-chat context.
|
||||
Message and thread results are rejected unless their returned chat matches that
|
||||
binding, and file-delivery MCP calls remain scoped to the same run/project/chat
|
||||
tuple. Unit and integration regressions cover symlink paths, sibling projects,
|
||||
Git-root delivery attempts, swapped files, and cross-chat results; they are
|
||||
included in the final 173-unit/85-integration green gate reported by Issue 16.
|
||||
|
||||
@@ -45,6 +45,8 @@ rollback and recovery, and no known critical security or data-integrity gaps.
|
||||
- [Decide the platform-administrator identity and audit boundary](issues/42-decide-platform-admin-identity-audit.md) — use a dedicated platform Feishu issuer, one peer administrator role, guarded bootstrap and identity-bound invitations, revocable server-side sessions, atomic append-only Platform Audit, and dual-factor offline recovery without a standing break-glass account.
|
||||
- [Restore the checker formatting gate](issues/09-restore-checker-format-gate.md) — pin local and CI Rust/rustfmt/clippy to 1.92.0, apply the canonical workspace format, and keep the full fmt + clippy + 53-test checker gate green.
|
||||
- [Provision a runnable non-root Hub service](issues/10-provision-nonroot-service.md) — install a strictly validated service identity and persistent layout, reject release/workspace overlap, validate complete production configuration and real bind settings, and execute Hub/Prisma/cph/bubblewrap probes as the service user under `no_new_privs` before writing the unit.
|
||||
- [Confine the agent runtime and protect service credentials](issues/16-confine-agent-and-protect-credentials.md) — replace the Agent environment, deny host reads/writes from root, keep every writable SDK path inside the canonical project, require bubblewrap plus socat, emit bounded correlated diagnostics, and prove the boundary with the real Linux SDK under a capability-free non-root identity.
|
||||
- [Close MCP context and file-delivery escape paths](issues/17-close-mcp-data-egress-escapes.md) — use no-follow project-rooted file operations and delivery snapshots, remove Git-root delivery, and bind every Feishu MCP read to the run's project and chat.
|
||||
|
||||
## Fog
|
||||
|
||||
|
||||
Reference in New Issue
Block a user