@bookedsolid/reagent 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/commands/init/github.d.ts +13 -0
- package/dist/cli/commands/init/github.d.ts.map +1 -0
- package/dist/cli/commands/init/github.js +81 -0
- package/dist/cli/commands/init/github.js.map +1 -0
- package/dist/cli/commands/init/index.d.ts.map +1 -1
- package/dist/cli/commands/init/index.js +11 -0
- package/dist/cli/commands/init/index.js.map +1 -1
- package/dist/gateway/native-tools.d.ts.map +1 -1
- package/dist/gateway/native-tools.js +38 -0
- package/dist/gateway/native-tools.js.map +1 -1
- package/dist/pm/github-bridge.d.ts +35 -0
- package/dist/pm/github-bridge.d.ts.map +1 -1
- package/dist/pm/github-bridge.js +185 -0
- package/dist/pm/github-bridge.js.map +1 -1
- package/dist/pm/types.d.ts +7 -7
- package/hooks/ci-config-protection.sh +84 -0
- package/hooks/file-size-guard.sh +64 -0
- package/hooks/git-config-guard.sh +81 -0
- package/hooks/import-guard.sh +99 -0
- package/hooks/network-exfil-guard.sh +118 -0
- package/hooks/output-validation.sh +101 -0
- package/hooks/rate-limit-guard.sh +75 -0
- package/hooks/symlink-guard.sh +96 -0
- package/package.json +1 -1
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# PreToolUse hook: symlink-guard.sh
|
|
3
|
+
# Fires BEFORE every Write tool call.
|
|
4
|
+
# Resolves the target file path and blocks if it escapes the project root.
|
|
5
|
+
# Guards against symlink traversal attacks where a path resolves outside the repo.
|
|
6
|
+
#
|
|
7
|
+
# Content extraction:
|
|
8
|
+
# Write tool → tool_input.file_path
|
|
9
|
+
#
|
|
10
|
+
# Exit codes:
|
|
11
|
+
# 0 = path is within project root — allow
|
|
12
|
+
# 2 = path escapes project root — block
|
|
13
|
+
|
|
14
|
+
set -uo pipefail
|
|
15
|
+
|
|
16
|
+
INPUT=$(cat)
|
|
17
|
+
|
|
18
|
+
# ── Dependency check ──────────────────────────────────────────────────────────
|
|
19
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
20
|
+
printf 'REAGENT ERROR: jq is required but not installed.\n' >&2
|
|
21
|
+
printf 'Install: brew install jq OR apt-get install -y jq\n' >&2
|
|
22
|
+
exit 2
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
# ── HALT check ────────────────────────────────────────────────────────────────
|
|
26
|
+
REAGENT_ROOT="${CLAUDE_PROJECT_DIR:-$(pwd)}"
|
|
27
|
+
HALT_FILE="${REAGENT_ROOT}/.reagent/HALT"
|
|
28
|
+
if [ -f "$HALT_FILE" ]; then
|
|
29
|
+
printf 'REAGENT HALT: %s\nAll agent operations suspended. Run: reagent unfreeze\n' \
|
|
30
|
+
"$(head -c 1024 "$HALT_FILE" 2>/dev/null || echo 'Reason unknown')" >&2
|
|
31
|
+
exit 2
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
TOOL_NAME=$(printf '%s' "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
|
|
35
|
+
|
|
36
|
+
# Only applies to Write tool
|
|
37
|
+
if [[ "$TOOL_NAME" != "Write" ]]; then
|
|
38
|
+
exit 0
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
FILE_PATH=$(printf '%s' "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
|
|
42
|
+
|
|
43
|
+
if [[ -z "$FILE_PATH" ]]; then
|
|
44
|
+
exit 0
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
# ── Determine project root ────────────────────────────────────────────────────
|
|
48
|
+
# Walk up from CLAUDE_PROJECT_DIR looking for .claude/ directory
|
|
49
|
+
PROJECT_ROOT=""
|
|
50
|
+
SEARCH_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
|
|
51
|
+
while [[ "$SEARCH_DIR" != "/" ]]; do
|
|
52
|
+
if [[ -d "$SEARCH_DIR/.claude" ]] || [[ -d "$SEARCH_DIR/.reagent" ]]; then
|
|
53
|
+
PROJECT_ROOT="$SEARCH_DIR"
|
|
54
|
+
break
|
|
55
|
+
fi
|
|
56
|
+
SEARCH_DIR=$(dirname "$SEARCH_DIR")
|
|
57
|
+
done
|
|
58
|
+
|
|
59
|
+
if [[ -z "$PROJECT_ROOT" ]]; then
|
|
60
|
+
PROJECT_ROOT="${CLAUDE_PROJECT_DIR:-$(pwd)}"
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
# ── Resolve the file path (no-symlinks) ───────────────────────────────────────
|
|
64
|
+
# Use python3 for portable path resolution since realpath --no-symlinks
|
|
65
|
+
# is not universally available (macOS ships an older realpath)
|
|
66
|
+
if command -v python3 >/dev/null 2>&1; then
|
|
67
|
+
RESOLVED=$(python3 -c "
|
|
68
|
+
import os, sys
|
|
69
|
+
p = sys.argv[1]
|
|
70
|
+
# os.path.realpath resolves symlinks; we use normpath for lexical-only resolution
|
|
71
|
+
# to detect path traversal without requiring the path to exist
|
|
72
|
+
print(os.path.normpath(os.path.abspath(p)))
|
|
73
|
+
" "$FILE_PATH" 2>/dev/null)
|
|
74
|
+
elif command -v realpath >/dev/null 2>&1; then
|
|
75
|
+
# Fallback: realpath without --canonicalize-missing may still work on some systems
|
|
76
|
+
RESOLVED=$(realpath -m "$FILE_PATH" 2>/dev/null || realpath "$FILE_PATH" 2>/dev/null || printf '%s' "$FILE_PATH")
|
|
77
|
+
else
|
|
78
|
+
# Last resort: use pwd-relative normalization
|
|
79
|
+
RESOLVED=$(cd "$(dirname "$FILE_PATH")" 2>/dev/null && pwd)/$(basename "$FILE_PATH") || printf '%s' "$FILE_PATH"
|
|
80
|
+
fi
|
|
81
|
+
|
|
82
|
+
# ── Check if resolved path is within project root ─────────────────────────────
|
|
83
|
+
RESOLVED_PROJECT=$(python3 -c "import os; print(os.path.normpath(os.path.abspath('$PROJECT_ROOT')))" 2>/dev/null || printf '%s' "$PROJECT_ROOT")
|
|
84
|
+
|
|
85
|
+
# Path must start with project root followed by / or be exactly the root
|
|
86
|
+
if [[ "$RESOLVED" != "$RESOLVED_PROJECT"/* ]] && [[ "$RESOLVED" != "$RESOLVED_PROJECT" ]]; then
|
|
87
|
+
printf 'SYMLINK-GUARD: Path escapes project root — blocked\n' >&2
|
|
88
|
+
printf ' Requested path: %s\n' "$FILE_PATH" >&2
|
|
89
|
+
printf ' Resolved path: %s\n' "$RESOLVED" >&2
|
|
90
|
+
printf ' Project root: %s\n' "$RESOLVED_PROJECT" >&2
|
|
91
|
+
printf 'Block reason: The resolved path is outside the project directory.\n' >&2
|
|
92
|
+
printf 'This may indicate a symlink traversal attempt or an incorrect absolute path.\n' >&2
|
|
93
|
+
exit 2
|
|
94
|
+
fi
|
|
95
|
+
|
|
96
|
+
exit 0
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bookedsolid/reagent",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Zero-trust MCP gateway — policy enforcement, secret redaction, and audit logging for AI-assisted projects",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Booked Solid Technology <oss@bookedsolid.tech> (https://bookedsolid.tech)",
|