Skip to content

fix(cli): refuse malformed flags, symlinked roots, and IPv6 breakage - #39

Merged
altaywtf merged 2 commits into
mainfrom
fix/audit-round-1
Sep 18, 2026
Merged

altaywtf merged 2 commits into
mainfrom
fix/audit-round-1

Conversation

@altaywtf

Copy link
Copy Markdown
Member

Four defects from a CLI audit, plus the test baseline that should have caught them. They share a shape: a malformed or unusual input reaches a default instead of an error.

Behavior changes

Unknown flag names are rejected. vref convert --dryrun parsed cleanly and ran a real conversion, deleting the originals. --keepsource, --forc, --dry_run all degraded the same way. Each command now has an allowed-flag list and raises VREF_UNKNOWN_FLAG.

Path flags must carry a value. --out, --dir, and --host used getString, which cannot tell an absent flag from an empty one — so --out= from an automation variable that expanded to nothing overwrote the published .vref/index.html and exited 0. getRequiredString already existed for exactly this, with a docstring describing this failure, and was applied only to --manifest.

serve and validate refuse symlinked roots. serve resolved --dir lexically and never walked it, so a checked-out .vref symlink turned it into a file server for the link's target — realPathInside canonicalises both sides, so containment was measured against that target rather than the repo. validateGallery had the same gap on the manifest, masked by the per-asset loop until screenshots is empty. Both now match what build, convert, and manifest add already did.

serve --host ::1 works. The base http://::1:4173 is unparseable; the TypeError was caught by the request handler and answered 400 for every request, while the server reported success and printed an unopenable URL. The request base is now fixed — only the pathname is ever read — and the reported url brackets IPv6 literals.

These make previously-silent invocations fail. That is the point, but it is a real change for any wrapper passing an extra flag.

Test baseline

test/vref.test.ts never imported path-safety.ts — the entire sandbox for a tool that writes files from agent-supplied JSON. Four of six safeManifestAssetPath rejections and both resolveInsideCwd rejections were unreachable from the suite. It now tests each branch directly.

43 distinct VREF_* codes existed in src/; 3 were asserted. The rest were pinned by English message substring, which is backwards — code is what consumers branch on, message is meant to be rewordable. 28 assertions moved to codes; 20 distinct codes are now covered.

describe is pinned to the flags cli.ts implements, in both directions. It immediately caught --help missing from all seven command schemas. --fields now advertises its accepted values per command instead of a prose scope string — additive, and it is the one list an agent needs to use the flag correctly.

73 tests → 98. Every new guard was checked by reverting it and confirming the suite fails.

Not included

Findings 6–18 from the audit: updatedAt never refreshed, convert --only <typo> reporting success, unencoded asset paths in href/src, Host/nosniff on the local server, Effect RC types in the published .d.mts, docs omitting .jpeg, and the CI OS matrix.

An audit of the CLI surfaced four defects that share a shape: a malformed or
unusual input reaching a default instead of an error.

`vref convert --dryrun` parsed cleanly and ran a real conversion, deleting the
originals; `--out=` from an automation variable that expanded to nothing
overwrote the published gallery. `getRequiredString` already existed for exactly
this and was applied only to `--manifest`. Unknown flag names are now rejected
per command, and `--out`, `--dir`, and `--host` must carry a value.

`serve` resolved its root lexically and never walked it for symlinks, so a
checked-out `.vref` symlink made it a file server for the link's target —
`realPathInside` canonicalises both sides, so containment was measured against
that target. `validateGallery` had the same gap on the manifest, masked until
`screenshots` is empty. Both now match every other caller.

`serve --host ::1` built the base `http://::1:4173`, which is unparseable; the
throw was caught and answered 400 for every request while the server reported
success. The request base is now fixed, since only the pathname is read, and the
reported url brackets IPv6 literals.

Behind all of it, the sandbox had no direct tests: 4 of 6 asset-path rejections
were unreachable from the suite, and 43 error codes were covered by 3 assertions
against English message text. Path safety is now tested per branch, assertions
moved to codes, and `describe` is pinned to the flags the CLI implements — which
immediately caught `--help` missing from all seven command schemas.
Copilot AI lite review requested due to automatic review settings September 18, 2026 11:35
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 18, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-18T11:48:55.113368Z 4ed907b New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Copilot 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.

🟡 Changes recommended

There are a couple of small but concrete correctness/portability issues in the updated code/tests (notably URL formatting for already-bracketed IPv6 hosts and OS-specific path expectations in a new test) that should be addressed before approval.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

This PR tightens the vref CLI’s safety guarantees by failing fast on malformed inputs (unknown flags, missing flag values, symlinked roots) and fixes serve URL handling for IPv6, backed by an expanded test baseline and updated user/skill documentation.

Changes:

  • Reject unknown flag names and reject “present but valueless” path flags instead of silently falling back to defaults.
  • Refuse symlinked roots for serve and symlinked manifests for validate, aligning behavior across commands.
  • Fix serve request URL parsing and reported URLs for IPv6 literals; expand tests to assert VREF_* codes and cover path-safety branches.
File summaries
File Description
test/vref.test.ts Expands suite to cover new guards and assert stable VREF_* error codes; adds direct path-safety tests and describe/CLI drift checks.
src/serve.ts Refuses symlinked serve roots; fixes IPv6 URL parsing and reports bracketed IPv6 base URLs.
src/describe.ts Adds per-command --fields accepted values and includes --help in described schemas.
src/cli.ts Introduces explicit allowed flag lists per command; uses required-string parsing for path flags; exports field/flag lists to keep tests and describe in sync.
src/build.ts Ensures symlinked manifest paths are rejected even when screenshots array is empty.
skills/vref/references/manifest.md Updates skill reference to reflect stricter flag handling and points users to vref describe for --fields values.
docs/VREF.md Documents new “refuse malformed flags / symlink roots” behavior and clarifies safety rules.
Review details
  • Files reviewed: 7/7 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/serve.ts
Comment thread test/vref.test.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f32b1d8e26

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/describe.ts
Comment thread src/cli.ts Outdated
`getRequiredStringFrom` returned on the first alias it found, so
`--out x --output-path=` passed the empty override straight through the guard
it was added for. Every supplied alias is now validated before one is chosen.

`build --check` returns a validate result and so accepts a narrower --fields
set than `build`, but describe advertised only the wider one. Publishing the
accepted values made that contradiction machine-readable, so describe now
carries checkValues and a test holds it to what the check branch validates.

`formatHost` would double-bracket an already-bracketed literal. listen()
rejects one with ENOTFOUND before the url is built, so the guard is defensive
and says so rather than carrying a test that cannot run.

Path-safety expectations now build with join() instead of hard-coded POSIX
strings.

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4ed907ba0c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/cli.ts
Comment thread test/vref.test.ts
@altaywtf
altaywtf merged commit 5a73707 into main Sep 18, 2026
2 checks passed
@altaywtf
altaywtf deleted the fix/audit-round-1 branch September 18, 2026 12:13
putio-ci Bot added a commit that referenced this pull request Sep 18, 2026
## [1.3.2](v1.3.1...v1.3.2) (2026-09-18)

### Bug Fixes

* **cli:** refuse malformed flags, symlinked roots, and IPv6 breakage ([#39](#39)) ([5a73707](5a73707))
@putio-ci

putio-ci Bot commented Sep 18, 2026

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 1.3.2 🎉

The release is available on:

Your semantic-release bot 📦🚀

@putio-ci putio-ci Bot added the released label Sep 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants