| Version | Supported |
|---|---|
| 2.x (Go) | Yes |
| 1.x (TypeScript, deprecated) | No |
| 0.1.x (Python) | No |
If you discover a security vulnerability, please report it responsibly:
- For sensitive vulnerabilities, email vishnu@hookwise.dev with a description, reproduction steps, and impact assessment. Do not open a public issue for exploitable or unpatched vulnerabilities.
- For low-severity or already-patched issues, you may use the Security Vulnerability issue template.
- You will receive an acknowledgment within 48 hours
- We aim to release a fix within 7 days for confirmed vulnerabilities
hookwise undergoes a structured security review pipeline on every release:
- Automated analysis -- 4 parallel review agents scan the full codebase (~80 source files) across isolated domains: core engine, CLI layer, feed producers, and Python TUI
- False-positive filtering -- Every candidate finding is independently validated against a strict exclusion list and concrete exploitability criteria (confidence >= 8/10 required)
- PR-level review -- Every pull request is diffed against
origin/HEADand reviewed for security regressions before merge
The most recent full-package review (v1.3.0) covered all source files and returned zero confirmed vulnerabilities.
hookwise operates under the following trust boundaries:
| Input | Trust Level | Rationale |
|---|---|---|
hookwise.yaml |
Trusted | User-authored local config, equivalent to a Makefile or package.json scripts. Note: feeds.custom entries are executed via sh -c with the user's privileges (see Process Execution below) |
| CLI arguments | Trusted | Provided by the local user |
| Environment variables | Trusted | Set by the local user or system |
| Claude Code hook payloads | Semi-trusted | JSON from Claude Code's hook system; parsed with Go's encoding/json (no code execution) |
| External APIs (Open-Meteo, HN, RSS) | Untrusted | Consumed defensively with fail-open error handling and type checking |
The codebase enforces the following security practices by design:
- Parameterized SQL everywhere -- All SQLite queries use
?or@paramplaceholders. No string concatenation in query construction. - Safe YAML parsing -- Go uses
gopkg.in/yaml.v3(safe by default, no code execution tags); Python TUI usesyaml.safe_load(). - JSON-only deserialization -- All external data is parsed with Go's
encoding/json, which cannot execute code.
- No code execution from untrusted or semi-trusted input -- External API responses and Claude Code hook payloads are parsed as data only (
encoding/json) and are never evaluated as code. - Handler dispatch uses no shell -- The dispatcher runs handler executables via
exec.Commandwith arguments passed as array elements (not a shell string), so a hook payload cannot inject shell commands. - Custom feeds run a shell by design, scoped to trusted config -- The optional
feeds.custommechanism executes its configuredcommandviash -c(internal/feeds/custom.go). This is intentional and is scoped to the Trustedhookwise.yaml-- the same trust level as a Makefile target or an npmscriptsentry. A custom feed command runs with your privileges, so only configure commands you would run yourself; treat a project'shookwise.yamlthe way you would treat its build scripts before enabling custom feeds. hookwise never derives a shell command from any semi-trusted or untrusted input.
- Restrictive permissions -- Database files use
0o600; directories use0o700(owner-only). - Atomic writes -- Config, cache, and state files use temp-file-plus-rename to prevent corruption.
- PID files with
O_EXCL-- Prevents TOCTOU race conditions in daemon startup.
- Fail-open design -- Internal errors in hookwise never block Claude Code tool calls. The
safeDispatchwrapper ensures graceful degradation. - Read-only access to Claude Code data -- The insights producer reads
~/.claude/usage-data/but never writes to it. - No network listeners -- hookwise does not open any ports or accept inbound connections. The daemon communicates via the filesystem (cache bus).
hookwise maintains a minimal dependency footprint:
- Runtime (Go):
modernc.org/sqlite,cobra,yaml.v3— compiled into a single static binary (CGO-free, ~19 MB stripped release) - Test-only (Go):
testify— not compiled into the shipped binary - Runtime (Python TUI):
textual,pyyaml,rich,anthropic - No native HTTP server dependencies -- External data is fetched via Go's
net/httpor Pythonurllib - Binary releases -- Go binaries are published via GitHub Releases with Dagger-based CI builds