Skip to content

Release 0.8.6 - #164

Merged
Raftersecurity merged 5 commits into
prodfrom
main
Jun 13, 2026
Merged

Release 0.8.6#164
Raftersecurity merged 5 commits into
prodfrom
main

Conversation

@Rome-1

@Rome-1 Rome-1 commented Jun 13, 2026

Copy link
Copy Markdown
Collaborator

Promote 0.8.6 to prod.

Highlights

  • Config-driven hook off-switch (sable-bnl) — disable the PreToolUse hook (whole / secret-scan-only / command-policy-only) via RAFTER_DISABLE_* env vars or global ~/.rafter/config.json agent.hooks.*. Honored only from trusted, machine-owner-owned sources — never project-local .rafter.yml (rafter-secure-design trust-boundary decision; rafter-code-review CLEAN). rafter agent status reports state + source. Node + Python parity, incl. a security negative test.
  • CWE-367 TOCTOU fix in the betterleaks scanner (sable-t0q) — fs.mkdtempSync private dir replaces a predictable Date.now() temp path; parity with Python.
  • Config audit + shared-docs/CONFIG.md (sable-59s/29w) — code-verified reference for the global vs project config layers, the trust boundary, and a toggle matrix mapping every switch to the code that enforces it. Audit surfaced a dead toggle (outputFiltering.redactSecrets/blockPatterns, sable-y2z — documented, not yet wired).

Release mechanics

  • Versions bumped to 0.8.6 in node/package.json, python/pyproject.toml, and both rafter-security-skill.md frontmatter.
  • CHANGELOG [0.8.6] dated 2026-06-13.

🤖 Generated with Claude Code

Rome-1 and others added 5 commits June 10, 2026 00:44
…ce (sable-cs8)

global-setup.ts already builds dist/ once before the (parallel) vitest suite,
but brief/completion/ci-init/github-action each re-ran `pnpm run build`
unconditionally in beforeAll. With fileParallelism enabled, those concurrent
tsc runs rewrite dist/ while other workers spawn `node dist/index.js` — so a
spawn landing mid-rewrite loads a half-written module and dies with e.g.
"SyntaxError: ... does not provide an export named createUpdateBetterleaksCommand"
(observed in CI on tests/brief.test.ts > exits 1 for unknown topic).

Guard each redundant build on !existsSync(dist/index.js), matching the pattern
agent-commands/agent-init-hermes/scan-exclude-paths already use. dist is
guaranteed present from globalSetup, so the guards skip on every normal run and
nothing rewrites dist during parallel execution. Verified: the 4 files + a 5th
CLI-spawning file run green together (223 tests).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…le-6d6/784/83b/t0q)

- sable-6d6: test_all_21_patterns_present asserted ==21 but the HashiCorp Vault
  token (#159) brought it to 22 — a pre-existing red test. Renamed to
  test_all_patterns_present with a floor (>=22) + uniqueness check so adding a
  pattern no longer breaks it. Node has no count assertion (verified).

- sable-784: platform-integration Gemini tests flaked with ENOENT on
  settings.json. Root cause: a full `agent init` install runs ~8-24s, but
  runCli's spawnSync timeout was 15s — under concurrent suite load it tipped
  over, returned status:null, and a downstream readFileSync hit a file the
  killed child never wrote. Raised the default timeout to 60s (covers every
  init call) and added runCliOk() which asserts exit 0 before reading, turning
  an opaque ENOENT into "CLI failed: <stderr>" and catching real regressions.

- sable-83b: notifications.test.ts + audit-logger-lifecycle.test.ts used
  arbitrary 50-100ms setTimeout sleeps for fire-and-forget webhook dispatch,
  flaky under CI load. Positive assertions now poll via vi.waitFor; negative
  assertions use a deterministic setImmediate microtask flush (DNS is mocked,
  so there are no real timers/IO to wait on).

- sable-t0q (CWE-367): betterleaks.ts built a temp report path from a
  predictable Date.now() name in the shared tmpdir. Replaced with
  fs.mkdtempSync (private 0700 dir, atomic), report.json inside it, best-effort
  rmSync cleanup in finally (also fixes prior temp-file leaks on throw paths).
  Brings Node to parity with Python's existing TemporaryDirectory. rafter-reviewed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…(sable-qli/bnl/59s/29w)

Adds a runtime off-switch for the PreToolUse hook, honored ONLY from trusted,
machine-owner-owned sources — the RAFTER_DISABLE_HOOKS / RAFTER_DISABLE_SECRET_SCAN
/ RAFTER_DISABLE_COMMAND_POLICY env vars and the global ~/.rafter/config.json
`agent.hooks.{enabled,secretScan,commandPolicy}` keys. NEVER from project-local
.rafter.yml: a rafter-secure-design trust-boundary pass established that honoring a
disable flag from a repo-shipped file would let a hostile clone silently disable a
victim's secret scanning + command interception. Enforced structurally — the
resolver reads ConfigManager.load() (global only), not loadWithPolicy(), and `hooks`
is absent from the PolicyFile schema.

- New shared resolver: node/src/core/hook-control.ts + python/.../hook_control.py.
  Env overrides global (D5); default enabled; corrupt config / unrecognized value
  fails safe to enabled (D2). Granular: whole-hook, secret-scan-only, command-
  policy-only. The git-commit staged-secret scan (inside evaluateBash) stays gated
  by secretScan, command interception by commandPolicy.
- `rafter agent status` (+ --json `hook_control`) reports effective state + source
  (default | global-config | env), so "why didn't the hook fire?" is answerable (D4).
- Node + Python parity (D6), with cross-runtime tests incl. the security negative
  (a project-local .rafter.yml/.rafter/config.yml disable attempt is ignored).
- shared-docs/CONFIG.md: consolidated, code-verified config reference (global vs
  project layers, trust boundary, toggle matrix mapping each switch to the code
  that enforces it). CLI_SPEC + CHANGELOG updated.

Audit (sable-59s) also surfaced that agent.outputFiltering.redactSecrets/blockPatterns
are validated but never enforced (PostToolUse always redacts) — filed sable-y2z,
documented as a known gap in CONFIG.md.

rafter-secure-design gated; rafter-code-review CLEAN (trust boundary, fail-safe,
parity, granularity all verified). 39 new tests green both runtimes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Hook off-switch (sable-bnl) + betterleaks TOCTOU fix (sable-t0q) + config audit
& reference (sable-59s/29w). Versions bumped in node/package.json,
python/pyproject.toml, and both rafter-security-skill.md frontmatter; CHANGELOG
[0.8.6] dated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ssion)

The off-switch change gave _evaluate_bash a required `control` param but only
updated one of three test files that call it directly — test_hook.py and
test_hook_integration.py (~20 call sites) broke with a TypeError, caught by the
full Python CI suite. Default `control=None` to a fully-enabled HookControl: the
production dispatch always passes a resolved control explicitly, so the default
only affects direct test callers and is fail-safe (enabled). 101 hook tests green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Raftersecurity
Raftersecurity merged commit e9897b5 into prod Jun 13, 2026
19 checks 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