Skip to content

fix(cli): make the API tolerate null options and context arguments - #4638

Closed
josephfarina wants to merge 2 commits into
fix/security-path-confinementfrom
fix/api-robustness-cleanup
Closed

fix(cli): make the API tolerate null options and context arguments#4638
josephfarina wants to merge 2 commits into
fix/security-path-confinementfrom
fix/api-robustness-cleanup

Conversation

@josephfarina

@josephfarina josephfarina commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Guards every exported API function against null in its optional arguments —
the largest robustness gap the chaos test found. Stacked on #4637;
review/merge that first.

The bug

Every API function used options = {} (and, on two-argument commands,
{cwd = …} = {}) as a default parameter. JavaScript defaults only fire for
undefined — passing an explicit null bypassed them and threw a raw
TypeError: Cannot read properties of null (reading 'cwd') (with no error code
and no AstryxError) instead of a graceful error. This affected the whole
public API surface: 17 functions on the options argument, plus the trailing
context argument on init, upgrade, and themeBuild.

These are all shielded behind the CLI (Commander always passes a real object,
so no end user ever hit them) — but the programmatic API contract is "never a
raw crash for any input," which scripts and integrations rely on.

The fix

  • Coalesce the options argument (options = options ?? {}) as the first
    statement in every affected function.
  • Do the same for the trailing context argument on init, upgrade, and
    themeBuild (an earlier pass fixed only the options slot and left the
    context slot crashing).
  • Add a regression suite that calls every exported command with null in both
    the options and context positions and asserts none throw a bare TypeError.
    It also fails if a new export ships without a case, so this can't silently
    come back. The suite runs from a throwaway temp directory so it never touches
    the repo.

Stack

  1. fix(cli): confine user paths, close DoS vectors, and repair broken paths #4637 — security + DoS + broken paths
  2. fix(cli): make the API tolerate null options and context arguments #4638 (this PR) — API robustness against null arguments
  3. fix(cli): flag collision, stale bundled themes, and codemod edge cases #4639 — flag collision, stale bundled themes, codemod edge cases

Test plan

  • New regression suite — 21 cases, all green
  • init / upgrade / theme suites green (no regression from the
    context-argument change)
  • eslint clean on all touched files

Every exported API function used `options = {}` as a default parameter, which
only activates for `undefined` — passing explicit `null` bypassed it and threw
a raw `TypeError: Cannot read properties of null (reading 'cwd')` (or similar)
instead of a graceful `AstryxError`. This affected 17 of 19 API functions and
was the single largest robustness gap found by the chaos test (45 crashes total).

Add `options = options ?? {};` as the first statement in every affected function
body. This coalesces both `null` and `undefined` before any destructuring or
property access. The fix is one line per function — minimal, safe, and covers
the entire family at once.

Note: these crashes were all API-only (never reachable through the CLI, which
always passes commander's options object), so no end-user ever hit them — but
the programmatic API contract states 'never a raw crash' for any input.
@vercel

vercel Bot commented Aug 1, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
astryx Ready Ready Preview Aug 1, 2026 6:55pm

Request Review

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Aug 1, 2026
The prior fix coalesced null options but left the trailing context object
({cwd}) on the three two-arg commands (init, upgrade, themeBuild) still
destructured with a bare default, so init({}, null) / upgrade({}, null) /
themeBuild(f, {}, null) still threw a raw 'Cannot read properties of null
(reading cwd)'. Normalize the context slot too (ctx = {} + ctx ?? {}).

Add api/null-options.test.mjs: a regression suite that drives every exported
API function with null in both the options and context slots and asserts none
throw a bare TypeError (AstryxError or success is fine). A coverage assertion
fails if a new export ships without a null-tolerance case, so the contract
can't silently regress. The suite runs from a throwaway temp cwd so init's
writes and core-resolution never touch the repo.
@josephfarina josephfarina changed the title fix(cli): API null-options robustness (45 crashes → 0) fix(cli): API null-options + null-context robustness Aug 1, 2026
@josephfarina josephfarina changed the title fix(cli): API null-options + null-context robustness fix(cli): make the API tolerate null options and context arguments Aug 2, 2026
@josephfarina

Copy link
Copy Markdown
Contributor Author

Closing — this change is unnecessary.

The guards defended against callers passing an explicit null for an optional
options/context argument. But a TypeScript consumer can't do that: the
generated types are options?: {...} (i.e. {...} | undefined), so null is a
compile error (TS2345: Argument of type 'null' is not assignable). Verified by
type-checking a consumer that passes null against the emitted .d.mts — every
null call errors, undefined/omitted/real-object calls pass.

The plain options = {} parameter default (already in place) is the idiomatic
JS way to make the argument optional and is sufficient — it handles the only
input a real or typed caller can produce (omitted → undefined). The extra
options = options ?? {} layer only converts a TypeError into an
AstryxError for a contract violation the type system already prevents; the
"crashes" came from a fuzzer poking null into every argument, not a real
caller. Not worth touching ~20 functions for.

The other chaos-test fixes continue in #4639, now rebased directly onto #4637.

@josephfarina
josephfarina deleted the fix/api-robustness-cleanup branch August 2, 2026 16:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Meta Open Source bot.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant