kit 1.36.0
Added
kit self-audit— kit checks its own source for the bug-classes the paranoid audit found. A deterministic, zero-LLM, local-first self-check that runs 12 rules over kit's own tree and asserts every CI-referenced script path actually exists on disk. It self-targets kit (resolves the package byname === "sandstream-kit", anchored to the module dir, never the cwd), so it audits kit even when invoked from a consumer project, and skips gracefully if kit's source isn't found.- Gating (error) rules: R11 every
.github/workflows/*run:script (node/python/npm run) resolves to a real file/script (the exacttriage.pyfalse-green class), R1 unannotated|| truein a CI step, R3 secret/state file written world-readable (octal mode is value-checked:0o644/0o777fail,0o600/0o400pass), R6import()/require()of a non-literal spec without name-validation and path-containment (window-scanned, so a Prettier line-wrap can't hide it), R7 attacker-controlled data interpolated into::error::/JUnit XML/step-summary without escaping, R9 a write to the hash-chained.kit-audit.jsonloutside the chaining writer. - Warn rules: R1
continue-on-error: true, R1b NaN/invalid timestamp treated as fresh, R2 secret value reaching argv/error text, R4 untrusted spec used before its validator, R8 a mutating MCP tool missing its read-only guard (fail-closed: everykit_*tool is enumerated, not a hardcoded subset). - Advisories (info): R10 third-party CLI invoked by bare name (PATH-hijack surface), R5 env var that relaxes a check to skip. These are aggregated to one line per class and never counted as warnings or gated on.
- Flags:
--format=text|github|gitlab,--json,--fail-on-warning,--only=<ids>,--list-rules. Output reuses kit's existing CI-annotation/JUnit emit and exit-code convention. A new warn-onlyself-auditjob runs in kit's own CI (gated so a reintroduced gating-class regression blocks the security gate).
- Gating (error) rules: R11 every
Security
- Live GitHub-annotation injection fixed in the MCP server.
kit_ci's--format=githubemitter interpolated config-controlled checkcategory/name/detailraw into::error::/::warning::lines; it now escapes them via the sharedescapeWorkflowCmd(the annotation-forgery classself-auditR7 exists to catch — found by dogfooding the new rule). - Dead, fail-open SAST step removed.
security.ymlrannpx eslint --plugin security … || truewhere the plugin was never installed (the command crashed and|| truemasked it, so the step ran zero rules and always passed). Removed; Semgrep remains the real SAST gate. kit_loginnow honors read-only mode. It performs outward auth + mutatesprocess.envbut lacked anisReadOnlyMode()guard (surfaced by the fail-closed R8 rule); it now refuses under read-only mode like the other mutating MCP tools.
Changed
SecurityCheckResult.categorywidened to admitself-audit/<class>values (drops two unsafeascasts). The duplicated source-file walkers incheck-tests.tsandcheck-design.tsare consolidated into a sharedsrc/source-walk.ts(behavior-preserving). The CI-output escapers (escapeWorkflowCmd/xmlEscape) moved tosrc/utils/ci-escape.tsso the MCP server can reuse them without importing the CLI entrypoint.
Full changelog: https://github.com/sandstream/kit/blob/v1.36.0/CHANGELOG.md
Verify this release:
git tag -v v1.36.0
npm audit signatures