T07 · Tool Hijacking and Spoofing
- Location
scripts/claude_hook.py:263- Finding
Claude Code Hook Silently Rewrites Git Commit and Pull Request Commands
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The main rewriter is coherent, but the package also includes an under-disclosed Claude Code hook that can alter git commit and PR messages if registered.
Review before installing. The normal CLI rewrite path is explicit and reasonably scoped, but do not register or enable scripts/claude_hook.py unless you intentionally want automatic Claude Code hook behavior that may scan edited prose and change commit or PR message text.
scripts/claude_hook.py:263Claude Code Hook Silently Rewrites Git Commit and Pull Request Commands
Skill reads from agent configuration directories (.claude/, .codex/, .gemini/). These directories may contain API keys, personal settings, and other credentials that the skill has no legitimate need to access.
- It writes four paths and no others: two markdown files under
`~/.claude/output-styles/`, the `hooks` and `outputStyle` keys inside
`~/.claude/settings.json`, and a record of those at
`~/.claude/rabbit-writes-host.json`.
- `--dry-run` prints every one of them and writes nothing, and the skill's
own instructions require showing that output to the user before running the
The declared description is about using a small local language model over an OpenAI-compatible endpoint to rewrite prose offline and compare rewriting models. The supplied code does not call any OpenAI-compatible endpoint, local model server, Ollama, llama.cpp, LM Studio, vLLM, or OpenRouter. Instead, it is a host hook script for Claude Code that integrates with editor/tool events, invokes a local scanner script, announces active writing voice, reports scan findings after file edits, and rewrites git commit/PR message bodies by removing Claude attribution and applying safe mechanical fixes. These are materially different triggers, capabilities, and primary purpose from the declared rewriting/benchmarking skill.
The declared description is about local-LLM-based prose rewriting and benchmarking rewrite quality. The supplied code does not perform any model invocation, endpoint interaction, text rewriting, benchmarking, or planning of rewrite prompts. Instead, it defines tables and helper functions for text artifact/security scanning and URL normalization. Its primary purpose is invisible-character detection and concealment-channel handling, which is materially different from the declared rewriting workflow. This is a clear description-behavior mismatch.
The declared description is about using local LLMs to rewrite prose and evaluate rewrite quality. The supplied code does none of that. It only defines helper functions to format command-line parsing and file path errors and a custom argparse parser that emits structured error output. This is a materially different primary purpose and an unrelated capability set, so the description does not accurately represent the code.
The declared description centers on rewriting flagged prose with a local LLM through an OpenAI-compatible endpoint. The supplied code does nothing related to model calls, prompt construction, text rewriting, endpoint configuration, or benchmarking rewrite pass rates. Instead, it manages a committed README-analysis corpus: locating README files, loading JSON summaries, deriving a reduced statistics payload, and checking for drift between shipped and generated corpus summaries. This is a materially different primary purpose and capability set, so the description does not accurately represent the code.
The declared description is about offline/local-model prose rewriting and related endpoint/benchmark workflows. The supplied code does none of that: it contains stdlib-only document parsing and security-oriented detection logic for concealed text in Word documents. Its primary purpose is identifying hidden runs and possible injection directives in .docx parts and returning extracted visible text plus findings. This is a materially different behavior and an undeclared capability set, so the description does not accurately represent the code.
The declared description centers on using a small local model to rewrite prose through an OpenAI-compatible API and related workflow tasks. The supplied code does something materially different: it is a stdlib-only text analysis/helper library for extracting and normalizing facts from prose so a separate verifier can detect whether a rewrite changed numbers, dates, quotes, or entities. This is not merely a supporting implementation detail for the declared behavior, because the code chunk contains no model invocation, no endpoint configuration, no rewrite generation, and no application of edits. Its primary purpose is verification of factual preservation, not performing rewrites with local models. Therefore the description does not accurately represent the actual code behavior.
The declared description centers on local-LLM-based prose rewriting through an OpenAI-compatible endpoint. The supplied code does something entirely different: it is a schema/helper module for representing, sorting, counting, and validating analysis findings in a writing checker. It does not access local or remote model endpoints, does not rewrite text, and does not implement any of the described workflow around gated rewrites or model evaluation. This is a clear description-behavior mismatch with a materially different primary purpose.
The declared description centers on using a small local language model for rewriting prose offline through an OpenAI-compatible API, with tasks like setup, gated rewrites, and benchmarking models. The supplied code does something materially different: it is a stdlib-only fixer library that computes and applies tightly constrained mechanical text edits based on regexes and repository-defined rules. It explicitly avoids judgment-based rewriting, protects code/quotes/URLs and similar spans, and never calls any model, network endpoint, or benchmarking logic. This is not a minor implementation detail difference; the primary purpose and capabilities differ substantially. Therefore the description does not accurately represent the code chunk.
The declared description is about using small local LLMs to rewrite text through OpenAI-compatible endpoints and to evaluate rewrite performance. The supplied code does none of that. It is a standalone inflection helper that generates regular English variants of words/phrases (plural, past, gerund), expands ban-list entries, and maps plural nouns back to singular forms. There are no model invocations, no endpoint configuration, no prompt construction, no text rewriting pipeline, no benchmarking logic, and no relevant permissions or external resource access. This is a clear description/behavior mismatch with a different primary purpose.
The declared description says this skill rewrites prose with a small local model via an OpenAI-compatible endpoint and supports setup, applying rewrites, and benchmarking rewrite performance. The supplied code does none of that. Instead, it is a defensive analysis module focused on detecting prompt injection and hidden instructions in text. It uses regex-based scanning, HTML entity decoding, and Unicode tag analysis to emit safety findings such as hidden directives, hidden text, tag smuggling, and visible directives. The module explicitly states it 'never fixes' and halts automated rewriting when high-severity findings are present. That is a materially different primary purpose from local-model rewriting, so this is a clear description/behavior mismatch.
The declared purpose centers on using small local LLMs through compatible endpoints to rewrite prose and compare rewrite quality. The supplied code does none of that. It contains only a heuristic analyzer that strips non-prose Markdown regions, counts alphabetic vs. ASCII letters, and returns a warning when the text may be non-English. There is no model invocation, endpoint configuration, rewrite planning, patch application, or pass-rate measurement. This is a materially different primary purpose, so the description does not accurately represent the code chunk.
The declared description is about using local LLM endpoints to rewrite text drafts. The supplied code does not interact with any model, endpoint, or rewriting pipeline. Its primary purpose is maintaining shared detection metadata and regex compilation for a lexicon-driven scanning system, including synthetic finding priorities and pattern validation. That is a materially different function from offline rewrite/humanization tooling, so this is a clear description-behavior mismatch.
The declared description centers on local-model-based prose rewriting and rewrite workflow tasks. The supplied code does not perform model invocation, endpoint setup, rewrite planning, gated editing, or benchmarking. Instead, it provides static text-analysis patterns for identifying vague link text and claim/caveat wording in documents. That is a materially different purpose from the declared rewriting skill, so this is a clear mismatch.
The declared description is about an LLM-powered prose-rewriting skill that works with local inference endpoints and supports rewrite workflows and benchmarking. The supplied code does none of that. It is a standalone markdown-processing module using only Python stdlib (re, html) to define regex patterns and helper functions for blanking markup while preserving offsets, stripping images/entities/URLs, identifying prose blocks, and computing simple text statistics. There is no network access, no OpenAI-compatible client, no local model invocation, no rewrite generation, and no benchmarking logic. This is a clear description-behavior mismatch with a materially different primary purpose.
The declared description is about an offline/local-LLM rewriting skill: sending flagged prose to a local model endpoint, applying rewrites, and measuring model performance. The supplied code does something materially different. It is a formatter/renderer for 'voice profiles' into a Claude Code output style, modifying prompt/style content rather than rewriting user prose. The module builds markdown with YAML frontmatter, extracts sections from profile markdown, renders stylistic rules and bans, and returns the assembled string. It explicitly states there is no CLI and no filesystem access, and the code contains no networking, no model invocation, no OpenAI-compatible API usage, no rewrite logic, and no benchmarking. This is a clear description-behavior mismatch with a different primary purpose.
The declared description is about offline/local-LLM-assisted prose rewriting. The supplied code does not interact with any LLM endpoint, does not rewrite text, and does not implement rewrite gating or benchmarking. Its primary purpose is entirely different: it manages a tolerance matrix from registers.json, validates consistency rules, detects document registers from structural patterns, and renders/checks a markdown table in references/context.md. This is a clear description-behavior mismatch.
The declared description is about offline/local-LLM-assisted prose rewriting and related workflow tasks. The supplied code does none of that: it contains no model invocation, no endpoint configuration, no rewrite planning or application, and no benchmarking logic. Its sole purpose is to serialize precomputed findings into SARIF so they appear inline in GitHub or CI tooling. This is a materially different primary purpose, not a mere supporting utility for the declared rewriting function.
The declared description is about using a local language model to rewrite prose cheaply/offline. The supplied code does something entirely different: it defines keyword tables and regex-based helpers for classifying document headings and detecting whether a document resembles a research paper by IMRaD structure. There is no evidence of model inference, API calls, rewriting, file editing, benchmarking, or any workflow related to de-slopping or humanizing text. This is a clear primary-purpose mismatch, not merely an implementation detail difference.
The declared description is about a skill whose core function is rewriting prose with a local LLM over an OpenAI-compatible endpoint and related workflow tasks. The supplied code chunk instead provides low-level text analysis helpers: sentence segmentation, tokenization, and syllable estimation for English text. It uses only Python stdlib regex logic and has no networking, no model invocation, no rewrite generation, no endpoint setup, and no benchmarking logic. This is a materially different primary purpose, so the description does not accurately represent the code.
The declared description says this skill rewrites prose with a small local model over an OpenAI-compatible API and supports setup, sending plans, applying rewrites, and benchmarking rewrite quality. The supplied code does something materially different: it is a standard-library Python lint/check module for ASD-STE100 rules. It analyzes text and emits findings; the docstring explicitly states it is 'REPORT-ONLY' and that rewrite is a separate language-model task not handled here. There are no network calls, no endpoint configuration, no model inference, no token/cost logic, no rewrite application, and no benchmarking features. This is a clear description-behavior mismatch with a different primary purpose.
The declared description is about using a local LLM endpoint to rewrite prose cheaply/offline. The supplied code does not perform rewriting at all and does not interact with any model endpoint, API, local inference server, or benchmarking harness. Its primary purpose is measuring writing style similarity via stylometric features and stored fingerprints: Burrows' Delta, marker rates, distributions, sentence-shape summaries, caricature detection, exemplar selection, and fingerprint file I/O/path resolution. This is a materially different capability and purpose from the declared rewriting tool, so the description does not accurately represent the code.
The declared description is about using local LLM endpoints to rewrite prose cheaply/offline and evaluate rewriting quality. The supplied code does something entirely different: it processes rabbit-allow suppression comments, marks findings as suppressed, prevents suppression of safety findings, and emits audit findings for invalid or stale suppressions. There is no networking, no model invocation, no rewrite planning, no endpoint configuration, and no benchmarking. This is a clear primary-purpose mismatch.
The declared description is about using a small local language model to rewrite prose offline through an OpenAI-compatible API. The supplied code does nothing of that kind. It imports stdlib plus local validation modules, reads JSON/markdown/fingerprint files from disk, compiles and checks regexes, validates configuration structure and references, and emits fail/note findings for voice profile assets. Its primary purpose is configuration/profile validation for a writing/voice engine, not rewriting text. This is a clear description-behavior mismatch with materially different functionality and resource usage.
The declared description centers on using local LLMs to rewrite prose through OpenAI-compatible APIs, including setup, sending rewrite requests, gated application of edits, and benchmarking model performance. The supplied code does none of that. Instead, it manages voice/style rule configuration files: merges inherited JSON profiles, blends rule sets, validates mechanic values, finds active or pinned voice profiles from the filesystem, and offers a CLI to output/write blended rules JSON. Its primary purpose is configuration/rules management for voice enforcement, not LLM-based rewriting. This is a clear material mismatch in primary function and capabilities.
Detected: suspicious.dynamic_code_execution, suspicious.exposed_secret_literal