fix(plugin): full-plugin audit fixes + cross-platform hardening + README refresh — 0.24.4#17
Merged
Merged
Conversation
… script hardening) Full-plugin functional/contract audit (10 parallel auditors) found 0 blocking issues; these are the warn/advisory fixes: allowed-tools gaps (v0.21.1 missing-mktemp class -> permission prompts mid-run): - dream: + mktemp/mv/mkdir/rm (atomic status.json write + FORGET archive loop) - setup: + grep/sed/awk/head/cat/wc (persona-card pipeline) - review: + basename/dirname/tr/head - import-host: + tr - status: + knowledge_validate MCP tool; numeric-guard SPEND (%.4f on non-numeric) - upgrade: + node/cd/bash (vector-deps health smoke-check) script/agent hardening: - symlink-guard.sh: deny-guard now fails CLOSED if realpath is absent (lexical fallback still denies a literal credential write) instead of fail-open exit 0 - wiki-recall-check.sh: awk gate uses -v + numeric coercion (no shell-interp into awk source -- the 0.21.4/0.22.3 mawk bug class), fix at source - stop-extract.sh: SB_EXTRACT_TIMEOUT comment 40 -> 25 (matches code) - knowledge-maintainer Phase 4b: drop unbound $KD (script defaults to $HOME/knowledge) - doubt: example layer id stop-predicate -> stop-extract (real taxonomy id) New guards: test-skill-allowed-tools.sh (per-skill verb requirements), test-symlink-guard.sh Test 17 (realpath-absent fail-closed). Full suite green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ADME refresh + release 0.24.4 Cross-platform (the plugin is bash-heavy; this makes it runnable on macOS BSD coreutils + /bin/bash 3.2 and under Git Bash on Windows, not just Linux/GNU): - wiki-forget-candidates.sh: mapfile (bash 4+) -> portable read loop - wiki-forget-score.sh + dream-autostage.sh: pair stat -c with stat -f (BSD/macOS) - tool-return-scanner.sh: PCRE grep -P -> portable grep -F byte-prefix (the Unicode-tag-block scanner now WORKS on BSD/macOS instead of silently no-op'ing) - symlink-guard.sh: portable realpath -m -> cd && pwd -P parent-resolver fallback (resolves symlink escapes on macOS where realpath lacks -m; still fail-closed) - lib.sh: timeout -> 'command -v timeout || command -v gtimeout' (macOS coreutils) - New test-script-portability.sh guards the construct classes (bash-4 builtins, unpaired stat -c/date -d, grep -P) against regression. README: refreshed to high-level, accessible framing and corrected the stale-wrong contradictions -- search is BM25 + optional on-device vectors (not 'token-overlap, no embeddings'); the plugin DOES auto-extract to wiki/graph at capture (not 'no autonomous writes'); added the graph + ai-block + forgetting features; completed the skills (audit/track/using-second-brain) + MCP-tool (relate/neighbors) tables; fixed 'v2.x' -> the plugin; test counts 24/59 -> 72/357; accurate cross-platform section enforced by the new portability test. Release 0.24.4 (plugin + marketplace lockstep) + upgrade migration row. Full suite green (72 shell + 357 vitest). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… HIGH) The release-gate review found that the new BSD/macOS realpath fallback resolved the parent dir's symlinks but appended the basename literally -- so a benign-named file that is ITSELF a symlink into a credential dir (e.g. innocent.txt -> ~/.ssh/ authorized_keys) slipped through on stock macOS (where the fallback is the active path). GNU realpath -m follows the leaf; the fallback now does too: try greadlink -f (macOS Homebrew coreutils), then cd && pwd -P on the parent + a leaf readlink deref. Fail-closed preserved. test-symlink-guard.sh Test 19 locks it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR rolls up advisory findings from a full functional/contract audit and a cross-platform hardening pass, plus a README refresh and version bump to 0.24.4. The changes primarily tighten safety/portability guards (especially around shell tooling differences on macOS/BSD and Git Bash) and ensure skills declare all required allowed-tools to avoid runtime permission prompts.
Changes:
- Hardened shell scripts for macOS/BSD + Git Bash portability (e.g.,
timeout→gtimeout,stat -c→stat -ffallbacks, removemapfile, replacegrep -P). - Expanded multiple skills’
allowed-toolsdeclarations and added tests to prevent regressions. - Updated safety guard behavior (symlink guard fail-closed when
realpathis absent) and refreshed README/product documentation; bumped plugin/marketplace version to 0.24.4.
Reviewed changes
Copilot reviewed 22 out of 22 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
tests/test-symlink-guard.sh |
Adds regression tests for symlink-guard fail-closed + macOS/BSD fallback scenarios. |
tests/test-skill-allowed-tools.sh |
New guard test ensuring skills declare required allowed-tools. |
tests/test-script-portability.sh |
New static portability linter for scripts/ (bash-3.2/BSD incompatibilities). |
skills/upgrade/SKILL.md |
Adds allowed-tools for new dependencies and documents 0.24.4 migration row. |
skills/status/SKILL.md |
Adds knowledge_validate tool grant and hardens persona spend parsing. |
skills/setup/SKILL.md |
Adds missing allowed-tools for binaries used by the skill. |
skills/review/SKILL.md |
Adds missing allowed-tools for binaries used by the skill. |
skills/import-host/SKILL.md |
Adds missing allowed-tools (tr). |
skills/dream/SKILL.md |
Adds missing allowed-tools (mktemp/mv/mkdir/rm). |
skills/doubt/SKILL.md |
Fixes example layer id (stop-predicate → stop-extract). |
scripts/wiki-recall-check.sh |
Makes awk gating numeric-safe via -v and coercion. |
scripts/wiki-forget-score.sh |
Adds BSD/macOS stat -f fallback for mtime extraction. |
scripts/wiki-forget-candidates.sh |
Replaces mapfile with a bash-3.2-compatible read loop. |
scripts/tool-return-scanner.sh |
Replaces grep -P with a portable fixed-string byte-prefix check. |
scripts/symlink-guard.sh |
Changes resolver behavior to fail-closed when realpath is unavailable; adds macOS/BSD fallback. |
scripts/stop-extract.sh |
Updates extractor timeout comment default (40 → 25). |
scripts/lib.sh |
Adds gtimeout fallback for timeout-based extractor invocation. |
scripts/dream-autostage.sh |
Adds BSD/macOS stat -f fallback for watermark mtime. |
README.md |
Updates high-level product description, feature framing, and testing counts. |
agents/knowledge-maintainer.md |
Removes unbound $KD from example invocation. |
.claude-plugin/plugin.json |
Version bump to 0.24.4. |
.claude-plugin/marketplace.json |
Version bump to 0.24.4. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+63
to
+74
| _pd=$(dirname -- "$FILE_PATH"); _pb=$(basename -- "$FILE_PATH") | ||
| _rpd=$(cd "$_pd" 2>/dev/null && pwd -P) | ||
| if [ -n "$_rpd" ]; then | ||
| if [ -L "$_rpd/$_pb" ]; then | ||
| _tgt=$(readlink -- "$_rpd/$_pb" 2>/dev/null) | ||
| case "$_tgt" in /*) RESOLVED="$_tgt" ;; *) RESOLVED="$_rpd/$_tgt" ;; esac | ||
| else | ||
| RESOLVED="$_rpd/$_pb" | ||
| fi | ||
| else | ||
| RESOLVED="${FILE_PATH/#\~/$HOME}" | ||
| fi |
Comment on lines
+134
to
+136
| STUB="$TMP/stub"; mkdir -p "$STUB" | ||
| printf '#!/bin/sh\nexit 127\n' > "$STUB/realpath"; chmod +x "$STUB/realpath" | ||
| gen(){ jq -nc --arg t "$1" --arg p "$2" '{session_id:"t",hook_event_name:"PreToolUse",tool_name:$t,tool_input:{file_path:$p}}'; } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Two workstreams from a full-plugin functional/contract audit (10 parallel auditors over every MCP tool, all 8 hook events, 21 skills, 7 agents, 47 scripts) + a cross-platform portability pass. The audit found 0 blocking issues — everything works; these are the surfaced warn/advisory fixes.
Audit fixes
allowed-toolsgaps (the v0.21.1 missing-mktempclass → permission prompts mid-run):dream+mktemp/mv/mkdir/rm ·setup+grep/sed/awk/head/cat/wc ·review+basename/dirname/tr/head ·import-host+tr ·status+knowledge_validate(+numeric-guard the persona-spend printf) ·upgrade+node/cd/bash.symlink-guard.shnow fails closed ifrealpathis absent (was fail-openexit 0).wiki-recall-check.shawk gate →-v+ numeric coercion (the mawk shell-interp bug class, fixed at source).stop-extracttimeout comment, maintainer unbound$KD,doubtexample layer id.Cross-platform (Linux / macOS BSD+bash-3.2 / Windows Git Bash)
mapfile(bash 4+) → portable read loop · unpairedstat -c→stat -c || stat -f· PCREgrep -P→ portablegrep -Fbyte-prefix (the Unicode-tag-block scanner now works on BSD/macOS instead of silently no-op'ing) ·timeout→timeout || gtimeout· portablerealpathresolver.test-script-portability.shguards the construct classes against regression.README
Refreshed to a high-level, accessible framing and corrected the stale-wrong contradictions: search is BM25 + optional on-device vectors (not "token-overlap, no embeddings"); the plugin does auto-extract to wiki/graph at capture (not "no autonomous writes"); added the graph + AI-block + forgetting features; completed the skills + MCP-tool tables;
v2.x→ "the plugin"; test counts24/59→72/357.Release gate — review found 1 HIGH (fixed), history found 0 regressions
The unit reviewer caught a real security gap I'd introduced: the new macOS
realpathfallback resolved the parent's symlinks but appended the basename literally, so a benign-named file that is itself a symlink into~/.sshslipped through on stock macOS. Fixed — the fallback now follows the leaf symlink too (greadlink -f, thencd && pwd -P+readlinkderef).test-symlink-guard.shTest 19 locks it.Verification
Full suite green (72 shell + 357 vitest, 0 fail); version lockstep 0.24.4; upgrade migration row added; new guards:
test-skill-allowed-tools.sh,test-script-portability.sh, symlink-guard fail-closed + macOS-resolver + leaf-symlink cases. No state migration (prompt/script/doc/test only).🤖 Generated with Claude Code