Skip to content

fix(cli): reject invalid/unknown-flag positionals in hand-rolled arg parsers - #222

Merged
Brooooooklyn merged 2 commits into
mainfrom
fix/cli-reject-unknown-flags
Jun 30, 2026
Merged

Brooooooklyn merged 2 commits into
mainfrom
fix/cli-reject-unknown-flags

Conversation

@hyfdev

@hyfdev hyfdev commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

The CLI now rejects a mistyped/unknown flag instead of silently turning it into a project name, hostname, or scaffolded filename.

The bug

Three hand-rolled arg parsers captured an invalid leading-dash token as a positional instead of erroring — unlike every parseArgs({strict}) parser and the sibling branches that already guard:

  • parseProjectArgs (status/link/rollback/cancel): void project status --foo returned name: '--foo', a bogus slug then sent to the platform — even though the sibling delete branch already rejects unknown flags.
  • parseDomainArgs: an unknown flag was captured as the hostname (or silently dropped).
  • parseMiddlewareArgs (void gen): any name was accepted, so void gen middleware --foo scaffolded a file literally named 001.--foo.ts — while the sibling gen parsers (model/migration/cron/queue) all validate the name.

Expected-correct behavior

A leading-dash / invalid token is not a valid positional → reject it, matching the contract the rest of the CLI already enforces.

Minimal repro

parseProjectArgs(['status', '--foo']) returned { subcommand: 'status', name: '--foo' } (should throw project: Unknown flag '--foo'.).

The fix

Add the leading-dash guard the delete branch already uses to the four project branches and the domain parser loop, and give parseMiddlewareArgs the same name regex (/^[a-z_][a-z0-9_-]*$/) its gen siblings already use. No legitimate positional (project slug, dpl_ id, DNS hostname, middleware name) starts with -.

Tests

Regression tests added (project-args.test.ts, new domain-args.test.ts, gen-args.test.ts): 6 unknown-flag rejections that fail on origin/main and pass after, plus happy-path/hyphenated-name guards. Local gate: the three arg test files 63/63; full --project unit zero-collateral vs a clean origin/main baseline (identical pre-existing adapter/init-migration failures, unrelated); packages/void typecheck + lint + fmt clean.

I enumerated every CLI parser to confirm these were the only three hand-rolled ones still swallowing invalid positionals (the rest use strict parseArgs, a subcommand allowlist, or a name regex), so the bug class is fully covered.

Prepared with AI assistance.

@netlify

netlify Bot commented Jun 18, 2026 •

Copy link
Copy Markdown

❌ Deploy Preview for staging-void-cloud failed.

Name Link
🔨 Latest commit 8a449c2
🔍 Latest deploy log https://app.netlify.com/projects/staging-void-cloud/deploys/6a3418d69e86910008610355

Comment thread packages/void/src/cli/gen-args.ts Outdated
@hyfdev
hyfdev marked this pull request as ready for review June 18, 2026 14:53
@hyfdev
hyfdev force-pushed the fix/cli-reject-unknown-flags branch from dc538ab to 8a449c2 Compare June 18, 2026 16:12

Brooooooklyn commented Jun 30, 2026 •

Copy link
Copy Markdown
Member

Merge activity

  • Jun 30, 3:41 AM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Jun 30, 3:42 AM UTC: Graphite rebased this pull request as part of a merge.
  • Jun 30, 3:45 AM UTC: @Brooooooklyn merged this pull request with Graphite.

hyfdev added 2 commits June 30, 2026 03:41
…parsers

The three hand-rolled CLI parsers swallowed an unknown flag (or other
invalid token) as a positional instead of erroring, unlike the
parseArgs(strict) parsers and the sibling branches that already guard:

- parseProjectArgs status/link/rollback/cancel captured a leading flag as
  the project name / deployment id (`void project status --foo` returned
  name='--foo', a bogus slug sent to the platform), though the `delete`
  branch already rejects unknown flags.
- parseDomainArgs captured an unknown flag as the hostname or dropped it.
- parseMiddlewareArgs (gen) accepted any name, so `void gen middleware --foo`
  scaffolded a file literally named `001.--foo.ts` — the sibling gen
  parsers (model/migration/cron/queue) all validate the name and reject it.

Add the leading-dash guard the `delete` branch uses to the four project
branches and the domain parser loop, and give parseMiddlewareArgs the same
name validation its gen siblings already use.
The name-validation regexes in the gen arg parsers were inline literals,
recreating a RegExp on every parser call and duplicating two identical
patterns across five sites. Hoist them to two module-level constants
(NAME_RE for model/migration, NAME_WITH_HYPHENS_RE for middleware/cron/
queue). Behavior is unchanged (anchored, non-global validators).
@Brooooooklyn
Brooooooklyn force-pushed the fix/cli-reject-unknown-flags branch from 8a449c2 to 19244d8 Compare June 30, 2026 03:41
@Brooooooklyn
Brooooooklyn merged commit a22bdfe into main Jun 30, 2026
6 checks passed
@Brooooooklyn
Brooooooklyn deleted the fix/cli-reject-unknown-flags branch June 30, 2026 03:45
cpojer pushed a commit that referenced this pull request Sep 11, 2026
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
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