hooks.json wired pre-write-executor.mjs to the Write tool only, so Edit and NotebookEdit reached .git/hooks/, .env, shell configs and the other protected paths unguarded. The matcher is now Write|Edit|NotebookEdit. The guard reads the target path per tool: file_path for Write and Edit (hooks reference, PreToolUse tool_input tables), notebook_path for NotebookEdit (the tool's input schema). When it cannot read a path (unparseable input, unknown tool, missing field) it now blocks instead of allowing. New tests resolve hooks.json with Claude Code's matcher semantics and run the hooks that would fire per tool: 9 failed on the old code, all pass now. The two fail-open pins in path-guard.test.mjs are flipped to fail closed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3.7 KiB
Security Policy — trekplan
Reporting a vulnerability
Report privately to security@fromaitochitta.com — do not open a public issue. There is no SLA — this is a solo-maintained plugin — but acknowledged reports are usually triaged within 7 days.
If you already have an account on the Forgejo instance, you may instead
open a private issue on the repo, tagged security:
Supported versions
Only the current minor version receives security fixes. When v3.2.0 ships, v3.1.x stops receiving patches. Pin to the latest minor and update on the next bump.
| Version | Supported |
|---|---|
| 3.1.x | Yes |
| 3.0.x | No (upgrade to 3.1.x) |
| < 3.0 | No |
Scope
The plugin's security posture covers:
Plugin-owned hooks (hooks/scripts/)
| Hook | Trigger | Purpose |
|---|---|---|
pre-bash-executor.mjs |
PreToolUse for Bash |
BLOCKs known-dangerous shell patterns; WARNs on suspicious ones; fails open on parse errors |
pre-write-executor.mjs |
PreToolUse for Write, Edit, NotebookEdit |
BLOCKs writes to .git/hooks/, ~/.ssh/, .env, and other sensitive paths; fails closed when it cannot read the target path |
pre-compact-flush.mjs |
PreCompact |
Flushes progress.json from git history before compaction (P0 drift fix); read-only beyond progress.json |
session-title.mjs (planned, F9) |
UserPromptSubmit |
Sets session title voyage:<command>:<slug> for telling parallel sessions apart |
All hooks are zero-dependency Node.js (.mjs) scripts and are designed
to fail open — a hook crash never blocks the user's work. Hooks log
to stderr only; they never write to user files outside their declared
scope.
Prompt-level denylist (commands/trekexecute.md)
The execute command embeds a denylist that takes effect even in a session where a hook does not fire. This is layer 2 of the three-layer defense-in-depth model (README, Security hardening) and protects against plan-injected destructive commands.
Validators (lib/validators/*.mjs)
Read-only. Never write to user files. Used both by hooks and by command phases to detect malformed artifacts before they propagate.
Out of scope
- Opt-in upstream architect step. Any external producer of
architecture/overview.mdships its own security posture. The architecture-discovery validator in this plugin treatsarchitecture/overview.mdas an external contract (drift-WARN, never drift-FAIL). - LLM output content. The plugin validates artifact shape, not
artifact truthfulness. A plan that passes
plan-validator --strictmay still contain hallucinated file paths or unsafe commands; that is whypre-bash-executorexists. - The Claude Code CLI itself. Report Claude Code vulnerabilities to Anthropic via https://github.com/anthropics/claude-code/issues.
Hardening recommendations
For fork-ers handling untrusted task briefs or plans:
- Set
disableSkillShellExecution: truein~/.claude/settings.json(CC v2.1.91+) to prevent Skills from invoking arbitrary shell. - Run plan validation in
--strictmode before any execute:node ${CLAUDE_PLUGIN_ROOT}/lib/validators/plan-validator.mjs --strict plan.md - Review the plan-critic adversarial output before approving plans from external sources — semantic rubric (rule #7) catches deferred decisions that an attacker could exploit.
- Pin a CC version floor. v3.1.0 of this plugin assumes CC ≥
2.1.85 for the
if-field on hooks; older CC silently ignores the field, weakening the scoping.
Past advisories
None as of v3.1.0. This section will list CVE-style entries if any are discovered.