Skip to content

4.3.0 - the audit release

Choose a tag to compare

@ankurhalder ankurhalder released this 04 Nov 14:06
· 77 commits to main since this release

4.3.0 — the audit release

A full audit of this package — every module read line by line, eight real repositories run end to
end, and adversarial probes of the filesystem, the config loader, the CLI contract and the published
tarball — produced 42 verified defects. This release fixes them, plus the six that needed a decision
first. The three that mattered most were in the two promises this package leads with.

Never leak secrets

  • A quoted credential containing an escaped quote kept its tail in clear — {"password": "p\"ss"} was masked to "[REDACTED]"ss", most of the value readable and the line broken. The whole value is masked now.
  • An unquoted value stopped at %, so a percent-encoded token shipped its tail (?access_token=abc%2Edef lost abc). %, : and ~ are token characters.
  • A .br file was emitted as 341 bytes of U+FFFD from a 186-byte source. .br is in the binary list, and a file that is at least a third undecodable is binary too.
  • Base64-wrapped PEM keys (LS0tLS1CRUdJTi…) are now detected by prefix, without decoding.

Machine-readable output

  • Every usage error wrote 0 bytes to stdout in JSON mode while the docs promised one document per invocation. Usage errors now emit the error document too.
  • An async hook that logged after an await appended text after the JSON payload and the command still exited 0. The redirect is scoped with AsyncLocalStorage; the payload is written once to the real stdout, even when the hook rejects.

Honest artifacts

  • audit.md said "no files exceeded the large file budget" while a third of a document was missing, because the cut came from maxPartBytes. Section 3 reports both causes with a Cut by column, and generate warns when a budget cut actually happened.
  • A part-budget cut carried no omission marker at all; every budget cut now names the budget.
  • The preview tail window lost lines on newline-terminated files — a 10-line file at 2/2 emitted no tail. Fixed, with an honest omission count.
  • A filename could inject a live Markdown link into reports/navigation.md (b](b).ts → [src/b](b)). Labels are escaped; anchors unchanged.
  • full-codebase.json explains the one field it cannot carry: artifacts.fullJson is null inside it, with a selfReference pointing at manifest.json for the real digest.

Robustness

  • A ~6,000-deep tree overflowed the stack after 76 s and wrote nothing; the walk is iterative and capped at 512 levels with a marker and a warning.
  • One >512 MiB text file aborted the run with a raw V8 message and no skip record; it is a per-file read-error skip now.
  • --discovery walk ignored .gitignore escapes (\#, \!, escaped trailing space) and included files git ignores. The parser follows gitignore(5); the matcher is escape-aware.
  • init wrote branch: "main" on every repository, producing a permanent validate warning on any master/vNext default. It writes the branch git reports.
  • validate, report and diff disagreed about what a manifest is; one shared guard requires generatedAt, schemaVersion, a 64-hex fingerprint, counts, totals and the files/skipped/parts arrays.
  • diff ignored schemaVersion, a deleted parts array and changed part digests.
  • A config carrying an unknown key, or exporting null, silently ran on the built-in defaults. Both are errors now.
  • requirements.txt is classified data instead of doc.

Verified on every supported Node version

engines has said >=18; until this release nothing had ever executed on 18 or 20. The publish workflow now runs the full gate on 18, 20 and 22 for every release, and the first honest run found a real defect: on Node 18 a Windows Deny-Read ACE makes existsSync answer false, so validate called an unreadable file "missing from disk". Fixed, and verified on 18.20.4 and 20.19.4.

Full details: CHANGELOG.md