Skip to content

fix(devframe): contain remote asset materialization - #328

Merged
antfu merged 1 commit into
mainfrom
fix/remote-assets-traversal
Sep 1, 2026
Merged

fix(devframe): contain remote asset materialization#328
antfu merged 1 commit into
mainfrom
fix/remote-assets-traversal

Conversation

@antfubot

@antfubot antfubot commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

Summary

RemoteAssetsStore.materialize() trusted provider-listed paths after checking only a string prefix. A compromised or buggy custom RemoteAssetsProvider could list a prefixed path whose suffix traverses outside the requested build directory, letting build materialization write files outside targetDir.

Changes

  • Added materializeTarget() in packages/devframe/src/utils/remote-assets.ts: validates each provider-listed path before any fetch or filesystem write — rejecting absolute paths, backslashes (never normalized into a separator), and any suffix whose resolved destination would land outside the target directory (or equal it exactly, since that names the directory itself, not a writable file).
  • materialize() now resolves each destination through this helper instead of joining the raw provider path, and silently skips (does not fetch) any entry that fails validation or falls outside the selected path prefix — matching the existing behavior for ordinary out-of-scope package files (e.g. package.json).
  • Added a regression test covering a prefixed traversal entry, an absolute path entry, a backslash traversal entry, a prefix-confusion entry, and an ordinary outside-prefix file — asserting none of them are fetched or written, while a normal nested asset still materializes correctly.

Verification

  • pnpm exec vitest run packages/devframe/src/utils/remote-assets.test.ts — all 29 tests pass.
  • pnpm --filter devframe typecheck — exit 0.
  • pnpm --filter devframe test (full packages/devframe suite via vitest run packages/devframe, including the tsdown-stale-guard API snapshot) — 578 tests pass.
  • pnpm lint (eslint --cache) — clean.
  • pnpm knip and the monorepo-wide pnpm build/pnpm typecheck currently fail on this environment for reasons unrelated to this change (verified identically on an unmodified checkout of main): knip can't resolve starter/'s workspace-linked dist/ output, and plugins/git's Next.js build hits a pre-existing EACCES on a stray file permission in this sandbox.

This PR was created with the help of an agent.

Validate every provider-listed path before fetching or writing it during
RemoteAssetsStore.materialize(): reject absolute paths, backslashes, and
any suffix whose resolved destination would escape the target directory.
A compromised or buggy custom provider could otherwise list a path that
traverses outside the requested build directory.
@vercel

vercel Bot commented Sep 1, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated
devframe Ready Ready Preview Sep 1, 2026 6:42am UTC
@antfu
antfu merged commit 529c6de into main Sep 1, 2026
13 checks passed
@antfu
antfu deleted the fix/remote-assets-traversal branch September 1, 2026 06:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants