Skip to content

Sandbox CLI output paths (Fixes #124) - #125

Open
alivirgo wants to merge 1 commit into
tt-a1i:mainfrom
alivirgo:fix/cli-output-path-sandbox
Open

Sandbox CLI output paths (Fixes #124)#125
alivirgo wants to merge 1 commit into
tt-a1i:mainfrom
alivirgo:fix/cli-output-path-sandbox

Conversation

@alivirgo

@alivirgo alivirgo commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Apply the same cwd + extension sandbox used for meta.output to CLI output paths, so deliver/render/compare cannot overwrite arbitrary files (e.g. ../marker.env).
  • Keep compare receipts as .json via requiredExtension: '.json' while HTML artifacts still require .html.
  • Add regression tests for CLI escape, non-.html deliver targets, and non-.json receipts.

Fixes #124

Test plan

  • node --test test/output-path.test.mjs (non-symlink cases; symlink tests need Windows Developer Mode / elevated privileges)
  • archify deliver workflow <input> ../outside.env fails and leaves the outside file untouched
  • archify deliver workflow <input> ../escaped.html fails with output/cli-outside-cwd
  • archify compare ... --receipt foo.html fails with output/cli-extension
  • Relative in-cwd .html / .receipt.json outputs still succeed

Made with Cursor

Require CLI artifacts to stay inside cwd with a safe extension, and keep compare receipts as .json under the same boundary. Fixes tt-a1i#124.

Co-authored-by: Cursor <cursoragent@cursor.com>

@jordandunmire97-ai jordandunmire97-ai left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Expanding

@chiang21fcb chiang21fcb left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Thanks for the PR @alivirgo. This is a clean, well-scoped fix.

What I reviewed

  • output-path.mjs: The sandboxSource unification is elegant. All three safety gates (extension, resolved-extension, cwd containment) now apply to both meta and cli paths. The requiredExtension parameter keeps the contract flexible for compare receipts.
  • archify.mjs: The two requiredExtension: '.json' additions for receipt paths are exactly right.
  • output-path.test.mjs: Three new regression tests cover the exact scenarios from #124. The two updated existing tests correctly adapt to the new check order (extension gate runs before alias gate).

Confirmed

  • The ../marker.env overwrite from #124 is blocked by the extension check
  • Compare receipts are gated by .json extension independently
  • Stable diagnostic codes follow the existing output/meta-* pattern
  • All existing tests are updated to match the new behavior

One note

The cwd containment for CLI paths is a reasonable safety choice. If maintainers want to allow absolute CLI paths for power users, that can be relaxed later without changing the extension gate, which is the critical fix.

No blockers. This is ready for maintainer review.

@tt-a1i tt-a1i left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Thanks for the focused sandboxing fix. The source-level direction is sound, but the distributable is stale on this exact head. I compared the committed files with the corresponding entries in archify.zip: both archify/renderers/shared/output-path.mjs and archify/bin/archify.mjs differ from the packaged copies. As a result, users installing the release artifact would not receive the output-path protections this PR adds, even though the repository source has them. Please rebuild archify.zip with the repository's canonical Node 22 build, verify byte-for-byte freshness, and run the current package-smoke/zip-freshness gates after syncing with main.

@tt-a1i tt-a1i left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Additional review of unchanged head e9653ba: the prior stale-ZIP finding still applies, but this is a newly reproduced public CLI regression, not a duplicate package reminder.

[P1] Separate trusted internal renderer targets from user-supplied output paths (archify/renderers/shared/output-path.mjs:268-273,288-315). From archify/, node bin/archify.mjs validate architecture examples/web-app.architecture.json --json now fails output/cli-outside-cwd because commandValidate renders into os.tmpdir while retaining the project cwd. node bin/archify.mjs inspect architecture examples/web-app.architecture.json fails output/cli-extension because its internal renderer target is /dev/null. Parent-versus-head resolver comparison confirms the regression. This blocks ordinary validation/inspection of valid diagrams, not an attempted unsafe user write.

Preserve the external sandbox while giving internal temporary/no-output calls an explicit safe seam, and add successful public validate/inspect regressions. Focused output-path tests: 17 passed, 5 failed; the latter also include fixtures not updated for the extension restriction, so they are not presented as proof of remaining overwrite vulnerabilities. No source edits or merge.

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.

[Bug]: CLI deliver output path can overwrite non-HTML files (meta.output sandboxed; CLI is not)

4 participants