Skip to content

[front] Fix sandbox function staging reads against symlink swap (TOCTOU) - #30191

Open
fontanierh wants to merge 2 commits into
mainfrom
staging-integrity
Open

[front] Fix sandbox function staging reads against symlink swap (TOCTOU)#30191
fontanierh wants to merge 2 commits into
mainfrom
staging-integrity

Conversation

@fontanierh

Copy link
Copy Markdown
Contributor

Description

buildSandboxFunctionOnSandbox and getDatabaseSchemaOnSandbox stage artifacts in agent-writable /tmp dirs as agent-proxied, then read them back through the provider file API, which envd serves as root while following symlinks. Code running as the agent on the same sandbox VM could swap a staging file for a symlink to a root-only file (e.g. /run/dust/egress-secrets.json) between the exec and the read, and the root read would return that file's content to the caller or persist it as a published function bundle.

Each producing exec now appends a marker and per-file sha256 lines after the dsbx output, and the read-back content is verified against those hashes before use, failing closed on any mismatch:

  • swap before the capture: the capture itself fails (set -e; sha256sum cannot open the swapped target as agent-proxied)
  • swap after the capture: content no longer hashes equal
  • error messages never carry content, so a swapped-in file cannot leak through the error path either

Follow-ups not in this PR: same hardening for any future provider.readFile/writeFile caller under agent-writable paths, and the dsbx port-80 Host pinning issue tracked separately.

Tests

  • New staging_integrity.test.ts for the split/verify helpers.
  • New swap-detection tests in build_on_sandbox.test.ts and a new dsbx_db.test.ts covering the schema flow (match, swapped file, missing hash).
  • Full lib/api/sandbox_functions and lib/api/sandbox suites pass locally in a dust-hive env (70 + 363 tests).

Risk

Low. Only the two staging flows change; both fail closed on any anomaly (missing marker, missing hash, mismatch), so worst case is a failed publish/schema read that the model can retry. Rollback is a revert.

Deploy Plan

Standard deploy.

buildSandboxFunctionOnSandbox and getDatabaseSchemaOnSandbox stage artifacts
in agent-writable /tmp dirs as agent-proxied, then read them back through the
provider file API, which envd serves as root while following symlinks. Code
running as the agent on the same sandbox VM could swap a staging file for a
symlink to a root-only file (e.g. /run/dust/egress-secrets.json) between the
exec and the read, and the root read would return that file's content to the
caller or persist it as a published function bundle.

Pin each artifact to the sha256 captured at the end of the producing exec and
fail closed on mismatch. A swap before the capture fails the capture itself
(set -e: sha256sum cannot open the swapped target as agent-proxied); a swap
after the capture no longer hashes equal. Error messages never carry content,
so a swapped-in file cannot leak through the error path either.
@vercel

vercel Bot commented Aug 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Actions Updated (UTC)
playground Ignored Ignored Preview Aug 7, 2026 1:21pm
storybook Ignored Ignored Preview Aug 7, 2026 1:21pm

Request Review

@dust-agent dust-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coding Rules LGTM \o/

…sing hash

Review feedback: anchor the stdout split on the last full-line marker so a
model printing the marker string cannot shadow the real capture or truncate
its own output mid-stream, and include the exec stderr in the missing-hash
error so a failed capture (e.g. sha256sum denied on a swapped target) is
debuggable.

@zmarouf zmarouf left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. I tried poking and the only thing I found was the sha256sum format that GNU based.
But the check fails closed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants