Skip to content

fix(security): enforce one canonical bunfig spelling for the release-age policy (P00c) - #31

Merged
kamescg merged 2 commits into
update/v1.1.0-alphafrom
codex/p00c-guard-toml-forms
Oct 19, 2026
Merged

kamescg merged 2 commits into
update/v1.1.0-alphafrom
codex/p00c-guard-toml-forms

Conversation

@jonathanprozzi

Copy link
Copy Markdown
Member

Child PR of the v1.1.0-alpha umbrella (#15).

Current (train)

The supply-chain guard reads bunfig.toml with two line regexes that match only a bare minimumReleaseAge or minimumReleaseAgeExcludes key, anywhere in the file. Bun parses the file as TOML, so a quoted key ("minimumReleaseAgeExcludes" = [...]), a dotted key, a quoted header or an inline install = { ... } table sets the same keys unseen. The reverse also holds: a policy key under some other table satisfies the guard while Bun applies no age floor. This is the weakness #23 held out.

Need

Every spelling Bun would read as install.minimumReleaseAge or install.minimumReleaseAgeExcludes is either evaluated with the value Bun would see or rejected with a diagnostic that names it. No TOML parser is available to the guard under Node in CI and no dependency may be added, so it enforces one canonical spelling instead.

Reconciliation

  • scripts/guard-supply-chain-policy.mjs: accepts exactly one bare [install] header, minimumReleaseAge = <decimal digits> and an optional single-line minimumReleaseAgeExcludes = ["..."], trailing comments tolerated. Anything else Bun could read as one of those keys fails with an unsupported bunfig representation: diagnostic: quoted, literal or dotted policy keys; policy keys outside [install]; ["install"], [[install]] or inline install tables; duplicate headers or keys; non-decimal ages; multi-line or non-string exclusion arrays. One line, one reason. Sub-tables such as [install.scopes] keep working.
  • Second commit: every non-policy key and value is opaque. The scanner steps over multi-line arrays and strings in unrelated sections and recognises """ and ''' by the current quote state, so a ''' inside an ordinary string is content.
  • scripts/guard-supply-chain-policy.test.mjs: one regression per rejected spelling, positive controls for the live file, the review reproductions verbatim. Existing tests unchanged in intent.
  • No documentation change: neither README.md nor docs/release.md describes how to write the policy.

Held out

  • Not a TOML parser: an unterminated multi-line value fails closed, and recovery from invalid TOML is out of scope.
  • The --minimum-release-age flag is already linted in workflows; a BUN_CONFIG_* override in a workflow env: block is not. Untouched here.
  • The other half of chore(security): retire the expired contracts-v2 release-age exception (P00b) #23's follow-up, extending test fixtures to workspace manifests and workflows, is not in this PR.

Evidence

  • bun run guard:supply-chain: passes, exit 0.
  • node --test scripts/guard-supply-chain-policy.test.mjs: 54 pass, 0 fail, including the frozen-install byte comparison. The 15 tests the second commit adds were written first: 13 failed before the fix, all 15 pass after it.
  • Independent review ran 78 configuration variants: no bypass, two false rejections (valid multi-line values in unrelated sections, and triple-quote substrings inside ordinary strings). Both fixed in the second commit; re-review of 44 variants found no mismatch.

Review notes

Base update/v1.1.0-alpha, rebased onto #23 (now merged); this closes the follow-up #23 recorded. Read the comment block at the top of checkBunPolicy first, then scanValueBoundary, then the tests.

…olicy and reject every other spelling (P00c)

The supply-chain guard read bunfig.toml with two line regexes that matched
only a bare, unquoted `minimumReleaseAge` / `minimumReleaseAgeExcludes` key
anywhere in the file. Bun parses the file as TOML, so a quoted key
(`"minimumReleaseAgeExcludes" = ["typescript"]`), a dotted key
(`install.minimumReleaseAge = 0`), a quoted table header or an inline
`install = { ... }` table set the same keys without the guard seeing them,
and a policy key written under some other table satisfied the guard while
Bun applied no age floor at all. Surfaced in review of the P00b change.

The guard runs under Node with no TOML parser, and no new dependency is
allowed, so it now enforces one canonical spelling instead of parsing TOML:
a single bare `[install]` header, `minimumReleaseAge = <decimal digits>`,
and optionally a single-line `minimumReleaseAgeExcludes = ["..."]`, with
trailing comments tolerated. Every other representation that Bun could read
as one of those keys fails with an `unsupported bunfig representation:`
diagnostic naming it: quoted, literal or dotted policy keys anywhere; policy
keys under other tables or `[install.*]` sub-tables; `["install"]`,
`[[install]]` or inline install tables; duplicate headers or keys;
non-decimal age values; multi-line or non-string exclusion arrays.
Legitimate `[install.*]` sub-tables keep working.

Tests: one regression per probe (quoted, literal and dotted keys, quoted
header, misplaced key, inline table, duplicate header, underscored integer,
multi-line array, hash inside a string) plus positive controls for the live
file. Gates: `bun run guard:supply-chain` exit 0; `node --test
scripts/guard-supply-chain-policy.test.mjs` 39 passed, 0 failed, including
the frozen-install reproducibility test.

Identity impact: none.
…he bunfig policy linter (P00c fix round)

Review of the canonical-form linter found two false rejections: a valid
multi-line array or multi-line string under an unrelated section (`[test]
preload = [ ... ]`, `[install.cache] dir = """ ... """`) was rejected and its
continuation lines were read as assignments; and a `'''` or `"""` substring
inside an ordinary single-line string was taken for a multi-line delimiter.

The scanner now treats every non-policy key and value as opaque: it tracks
value boundaries across lines (arrays with trailing commas, comments and
nesting; basic and literal multi-line strings) and recognises delimiters by
the current quote state, so only the two policy keys and the install table
are ever judged. A policy key with a multi-line value is still rejected.

Regressions: the reviewer's reproductions verbatim, a string whose content
looks like a policy assignment, nested and commented multi-line arrays,
escaped quotes and `#` inside strings. Gates: `bun run guard:supply-chain`
exit 0; `node --test scripts/guard-supply-chain-policy.test.mjs` 54 passed,
0 failed.
@kamescg
kamescg merged commit c1c7401 into update/v1.1.0-alpha Oct 19, 2026
1 check passed
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