Skip to content

Release v0.8.10 → prod (publish npm + PyPI) - #186

Merged
Raftersecurity merged 8 commits into
prodfrom
main
Jun 28, 2026
Merged

Release v0.8.10 → prod (publish npm + PyPI)#186
Raftersecurity merged 8 commits into
prodfrom
main

Conversation

@Rome-1

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

Copy link
Copy Markdown
Collaborator

Promote mainprod to publish v0.8.10 to npm (@rafter-security/cli) and PyPI (rafter-cli).

Shipping (since 0.8.9)

Pre-flight

Merging this triggers publish.yaml (tests gate → OIDC publish → post-publish smoke tests). Refs sable-ehb1.

🤖 Generated with Claude Code

Rome-1 and others added 8 commits June 20, 2026 21:48
…ands (sable-nf2i)

CommandInterceptor.evaluate() returned {allowed:true, requiresApproval:false}
for critical destructive commands (rm -rf /, fork bombs, dd to disk, mkfs, …)
whenever no commandPolicy was configured — which is the real-world default
(the user's ~/.rafter/config.json often omits agent.commandPolicy). The pretool
hook only denies on (!allowed && !requiresApproval) || requiresApproval, so
allowed=true+approval=false sailed straight through: a security CLI that did not
block `rm -rf /` by default.

Fix: add an UNCONDITIONAL critical-destructive hard-block at the very top of
evaluate(), before any policy is loaded, in both implementations. Critical
commands now always return allowed=false, requiresApproval=false — independent
of whether a policy exists or which mode is set (allow-all and custom deny-lists
can no longer opt out of catastrophic commands). With no policy configured,
high-risk commands now fall back to requiring approval instead of allow-all.

- node/src/core/risk-rules.ts: add matchedCriticalPattern() helper
- python/rafter_cli/core/risk_rules.py: add match_critical_pattern() helper
- both interceptors: hard-block keyed on assessCommandRisk()=="critical",
  surfacing the matched built-in pattern; exact node/python parity verified
  (16/16 commands identical under the same config)

Updated the policy-mode tests that encoded the old (insecure) contract
(allow-all / custom deny-list / approve-dangerous permitting critical commands)
to assert the hard-block. Repairs the 13 red command-interceptor.test.ts cases,
the hook-integration "blocks rm -rf / even in a git repo" case, and the two
error-handling-gauntlet interceptor cases.

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

fix(security): unconditional hard-block for critical destructive commands (sable-nf2i)
…son)

Claude Code appends `--hook-json <data>` to the hook command at invocation; both
CLIs rejected it as an unknown option and exited non-zero, breaking the hook.
Hook input comes from stdin, so the extra flag (and its value) is unused and
safe to discard.

- Node: `.allowUnknownOption()` + `.allowExcessArguments()` on BOTH the pretool
  and posttool Commander subcommands (the `<data>` value lands as an excess arg,
  so allowUnknownOption alone isn't enough).
- Python: `context_settings={allow_extra_args, ignore_unknown_options}` on the
  pretool/posttool `@hook_app.command(...)` decorators. (Setting it on the
  hook_app *group* — the prior approach — does NOT reach subcommand parsing, so
  `--hook-json` was still rejected; verified the group-only fix fails.)

Declared options like `--format` are still parsed normally. Adds Node + Python
regression tests covering: --hook-json tolerated on pretool & posttool, --format
still honored (not swallowed), and unchanged no-flag behavior. CLI_SPEC.md
documents the tolerance.

Supersedes the original #180 branch (which had no merge-base with main and
bundled an unrelated docs/vitest-upgrade history); re-applied cleanly on main.

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

fix(hook): tolerate --hook-json flag from Claude Code harness
…te|Edit|MultiEdit

rafter agent init --with-claude-code (and agent enable claude-code.hooks)
registered the `rafter hook posttool` redaction hook with a catch-all `.*`
matcher, so it fired after EVERY Claude Code tool call — including Read and
MCP tools, which never produce secrets to redact — adding latency to every
operation. Narrow the matcher to the tools whose output is worth scanning:
shell output (Bash) and file writes (Write/Edit/MultiEdit).

Changed in both install paths per language (init/legacy + component spec),
keeping Node and Python identical. PreToolUse matchers are unchanged.

Scope is Claude Code only. Codex (.* PostToolUse) and Gemini (.* AfterTool)
have the same broad-matcher latency issue and are tracked separately in
sable-4alt for platform-correct narrow matchers.

Docs (SKILL.md, PLATFORM_PARITY_AUDIT.md, CHANGELOG) and test expectations
updated; a PostToolUse-matcher assertion added to the Python install test
to mirror the Node coverage.

Closes sable-h0ah

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

fix(claude-code): narrow PostToolUse hook matcher from .* to Bash|Write|Edit|MultiEdit (sable-h0ah)
…ening) (#184)

Triage + remediation of the Rafter scan on main (bead sable-qsig). The large
majority of the 780 findings are context-blind SAST false positives for a local
CLI (fs/path ops on the user's own filesystem, an XXE rule firing on code that
parses no XML, status-string compares flagged as timing attacks, git-diff
parsing flagged as URL validation) and intentional demo/fixture secrets. Those
are documented and suppressed in a new repo-root .rafter.yml — each entry traced
input->sink first, honored by both the local engines and remote `rafter run`.

Real fixes applied:
- Node dependency CVE bumps via pnpm workspace overrides + direct deps, re-locked:
  axios 1.13.6->1.18.1, hono 4.12.8->4.12.27, tar ->7.5.17, js-yaml ->4.3.0,
  fast-uri, path-to-regexp, form-data, follow-redirects, ip-address, qs,
  brace-expansion all bumped past their fixed versions (~50 CVEs). tsc build
  clean; affected suites pass.
- Python direct-dep floors bumped in pyproject (requests ^2.33.0, urllib3
  >=2.7.0, python-dotenv ^1.2.2). Transitive CVEs (via mcp) need `poetry lock`
  on a box with poetry -> tracked in sable-i7ll.
- skill_remote.extract_npm_tarball: skip non-file/dir members (symlink/hardlink/
  device) as defense-in-depth on top of the existing zip-slip guard.

Local secrets rescan after: 0 active, 488 suppressed (all triaged fixtures).

Refs sable-qsig. Follow-ups: sable-i7ll (python poetry lock), sable-ufd9
(backend FP rules behind GH #178/#182).

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Patch release bundling the unreleased changes on main since 0.8.9:
- Claude Code PostToolUse matcher narrowed .* -> Bash|Write|Edit|MultiEdit (#183)
- Hooks tolerate harness-appended flags, e.g. --hook-json (#180)
- Dependency CVE re-lock (axios, hono, tar, js-yaml, +transitives) and
  remote-skill tarball extraction hardening (#184)

Bumps node/package.json + python/pyproject.toml to 0.8.10 (parity), the
rafter-security skill resource version (node + python), and finalizes the
CHANGELOG 0.8.10 section.

Refs sable-ehb1

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
@Raftersecurity
Raftersecurity merged commit 348e123 into prod Jun 28, 2026
10 of 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