Skip to content

ADR-1506: Move the praetor pin to 0af07a733e65 to drop the braces chain from the documentation gate's lock

  • Status: Accepted
  • Date: 2026-10-03
  • Deciders: lusoris
  • Tags: ci, governance, standards, security

Context

OpenSSF Scorecard's Vulnerabilities check reports one finding on this repository: braces 3.0.3 in tools/markdownlint/package-lock.json (GHSA-vfj7-8cjw-p6xm, stack exhaustion on deeply nested brace patterns). The file is praetor's locked documentation gate, vendored byte for byte, and the pin from ADR-1351 (6c772713a133) locks markdownlint-cli2 0.23.3, which reaches braces through micromatch, globby and fast-glob. No fixed braces release exists and every package in the chain is at its latest release, so a lock refresh cannot clear it. An ignore entry would only hide it.

Praetor removed the chain at the source: ebb248e75 (praetor #756, "lint Markdown without braces or micromatch") makes the gate depend on markdownlint 0.41.1 directly. At the praetor head 0af07a733e65 the lock holds 74 packages and no braces; osv-scanner scan source -L tools/markdownlint/package-lock.json reports no issue there and one issue (braces 3.0.3) on the tree before this move.

The pin is the newest praetor main commit at or after ebb248e75. All four commits from ebb248e75 to 0af07a733e65 pass their CI (13 to 14 successful checks each, one skipped); 0af07a733e65 is the head.

Decision

Move PRAETOR_REF in .github/workflows/standards-gate.yml from 6c772713a133 to 0af07a733e6534269b435cea185da4d1df7aba0c, under the conditions of ADR-1351: the files the engine writes are regenerated by the engine in a throwaway copy of the tree (adopt --force --lock-source-root <praetor source at the pin>, then compile-context on the repository's own AGENTS.md) and copied back where audit reports them stale; the baseline is re-recorded with the new engine from a clean clone on the final tree.

  • Vendored and generated files that change: tools/markdownlint/{package.json,package-lock.json,verify.mjs}, tools/figures/{README.md,astro.mjs}, the compiled context files (the register block only), .config/archetypes/facets/api-public.yaml, .standards.lock, .gitattributes, renovate.json, the DevContainer bundle (.devcontainer/praetor-source.00*.b64, Dockerfile.praetor, devcontainer.json) and the README governance figure.
  • The new engine adds a required Go API compatibility gate: tools/apicompat/gate/main.go and .github/workflows/praetor-api.yml (job Go API Compatibility, go-apidiff over every tracked Go module). Audit fails without them, so they are adopted unchanged. The rendered ruleset template names the new context. It is a template only; the live ruleset is unchanged.
  • The repository's AGENTS.md harness is kept; adopt --force also writes .gemini/settings.json and praetorctl hook entries into .claude/settings.json, .codex/hooks.json and .vscode/settings.json. None is copied, as in ADR-1351.
  • The new engine scans shell, GitHub Actions and systemd files. On the same tree the old engine records 227 within 227 (no growth) and the new one 506 (503 after this PR). Three of the 506 came from code: scripts/ci/build-macos-tester-bundle.sh added two curl calls without a deadline and a || true that hid a failure after the baseline was recorded. The PR fixes them (--max-time 600, rm -rf instead of 2>/dev/null || true), so every one of the 276 entries added to the baseline comes from an engine check and none from code. The baseline is recorded with --allow-increase and that reason: 227 to 503.

Alternatives considered

Option Pros Cons Why not chosen
Ignore the advisory in osv-scanner.toml next to the lock No pin move The lock is vendored and byte-locked by audit, so the file would be a repository-only addition for a finding praetor already removed; the ignore expires and must be renewed The cause is gone upstream
Refresh the lock inside the vendored file None Audit hashes the file; no fixed braces release exists Impossible
Pin ebb248e75 (first commit without braces) Smallest delta Misses three later fixes, among them the HISS baseline stability and the devcontainer bundle The newest green commit is the better engine
Move the pin and hand-edit only tools/markdownlint/ Smaller diff Audit also reports the compiled context, .standards.lock and the DevContainer stale Engine output is the only accepted source
Move the pin to 0af07a733e65 (chosen) Removes the finding at its source; engine current The baseline figure rises by the shell scan; one more required workflow file

Consequences

  • Positive: Scorecard's Vulnerabilities check has nothing to report from the documentation gate. The markdown lint gate lints the docs as before: on this tree, with the old and the new gate, make docs-lint passes with no finding, and a planted heading error is reported identically by both (only the tool's version banner line differs).
  • Negative: The recorded count rises from 227 to 503 because the engine now reads 186 shell files, the GitHub Actions workflows and systemd units. Go API Compatibility is a new workflow; it compares exported Go APIs against the pull request's base and runs on every pull request.
  • Neutral / follow-ups: Every hook engine on a workstation moves with the merge (the two engines do not read each other's trees); a branch rebases onto the merged pin first.

Supply-chain impact

  • Removed dependencies: markdownlint-cli2, braces, micromatch, globby, fast-glob and their transitive packages leave the documentation gate's lock. tools/markdownlint/package.json depends on js-yaml 5.4.2, jsonc-parser 3.3.1, markdownlint 0.41.1, micromark 4.0.3, micromark-extension-mdxjs 3.0.0, parse5 8.0.1 and smol-toml 1.9.0.
  • Build-time fetches: Go API Compatibility fetches go-apidiff through the Go module proxy. The workflow pins every action by commit SHA.
  • CVE surface delta: narrows; GHSA-vfj7-8cjw-p6xm leaves the tree.

References

  • req (paraphrased): move the praetor pin to the newest green commit at or after the one that removes the braces chain, so Scorecard's only Vulnerabilities finding clears (coordinator brief, 2026-10-03).
  • ADR-1351: the shape of a pin move; ADR-1249: the ratchet.
  • Praetor #756 at ebb248e75, praetor head 0af07a733e65.