claude-code-pilot 3.1.1 → 3.3.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/CHANGELOG.md +57 -0
- package/README.md +16 -11
- package/bin/install.js +127 -11
- package/manifest.json +20 -1
- package/package.json +4 -3
- package/src/agents/a11y-architect.md +141 -0
- package/src/agents/code-architect.md +71 -0
- package/src/agents/code-explorer.md +69 -0
- package/src/agents/code-simplifier.md +47 -0
- package/src/agents/comment-analyzer.md +45 -0
- package/src/agents/csharp-reviewer.md +101 -0
- package/src/agents/dart-build-resolver.md +201 -0
- package/src/agents/django-build-resolver.md +252 -0
- package/src/agents/django-reviewer.md +169 -0
- package/src/agents/fastapi-reviewer.md +79 -0
- package/src/agents/fsharp-reviewer.md +109 -0
- package/src/agents/pr-test-analyzer.md +45 -0
- package/src/agents/silent-failure-hunter.md +50 -0
- package/src/agents/swift-build-resolver.md +170 -0
- package/src/agents/swift-reviewer.md +116 -0
- package/src/agents/type-design-analyzer.md +41 -0
- package/src/available-rules/README.md +3 -1
- package/src/available-rules/dart/coding-style.md +159 -0
- package/src/available-rules/dart/hooks.md +66 -0
- package/src/available-rules/dart/patterns.md +261 -0
- package/src/available-rules/dart/security.md +135 -0
- package/src/available-rules/dart/testing.md +215 -0
- package/src/available-rules/web/coding-style.md +105 -0
- package/src/available-rules/web/design-quality.md +72 -0
- package/src/available-rules/web/hooks.md +129 -0
- package/src/available-rules/web/patterns.md +88 -0
- package/src/available-rules/web/performance.md +73 -0
- package/src/available-rules/web/security.md +66 -0
- package/src/available-rules/web/testing.md +64 -0
- package/src/commands/ccp/ai-integration-phase.md +36 -0
- package/src/commands/ccp/audit-fix.md +33 -0
- package/src/commands/ccp/code-review-fix.md +52 -0
- package/src/commands/ccp/cost-report.md +107 -0
- package/src/commands/ccp/eval-review.md +32 -0
- package/src/commands/ccp/extract_learnings.md +22 -0
- package/src/commands/ccp/import.md +37 -0
- package/src/commands/ccp/ingest-docs.md +42 -0
- package/src/commands/ccp/intel.md +179 -0
- package/src/commands/ccp/mvp-phase.md +45 -0
- package/src/commands/ccp/plan-prd.md +160 -0
- package/src/commands/ccp/plan-review-convergence.md +58 -0
- package/src/commands/ccp/pr-ecc.md +184 -0
- package/src/commands/ccp/scan.md +26 -0
- package/src/commands/ccp/security-scan.md +74 -0
- package/src/commands/ccp/sketch-wrap-up.md +31 -0
- package/src/commands/ccp/sketch.md +54 -0
- package/src/commands/ccp/spec-phase.md +62 -0
- package/src/commands/ccp/spike-wrap-up.md +31 -0
- package/src/commands/ccp/spike.md +51 -0
- package/src/commands/ccp/ultraplan-phase.md +33 -0
- package/src/hooks/ccp-bash-hook-dispatcher.js +96 -0
- package/src/hooks/ccp-context-monitor.js +23 -0
- package/src/hooks/ccp-doc-file-warning.js +93 -0
- package/src/hooks/ccp-pre-bash-dispatcher.js +24 -0
- package/src/hooks/ccp-read-injection-scanner.js +152 -0
- package/src/hooks/ccp-write-gateguard.js +868 -0
- package/src/hooks/kit-check-update.js +59 -7
- package/src/hooks/run-with-flags-shell.sh +1 -0
- package/src/hooks/run-with-flags.js +48 -1
- package/src/hooks/session-end.js +88 -1
- package/src/lib/hook-flags.js +14 -0
- package/src/lib/project-detect.js +0 -2
- package/src/lib/shell-substitution.js +499 -0
- package/src/pilot/references/agent-contracts.md +79 -0
- package/src/pilot/references/ai-evals.md +156 -0
- package/src/pilot/references/ai-frameworks.md +186 -0
- package/src/pilot/references/doc-conflict-engine.md +91 -0
- package/src/pilot/references/execute-mvp-tdd.md +81 -0
- package/src/pilot/references/gate-prompts.md +100 -0
- package/src/pilot/references/gates.md +70 -0
- package/src/pilot/references/mandatory-initial-read.md +2 -0
- package/src/pilot/references/mvp-concepts.md +49 -0
- package/src/pilot/references/planner-graphify-auto-update.md +67 -0
- package/src/pilot/references/planner-human-verify-mode.md +57 -0
- package/src/pilot/references/planner-mvp-mode.md +53 -0
- package/src/pilot/references/project-skills-discovery.md +19 -0
- package/src/pilot/references/revision-loop.md +97 -0
- package/src/pilot/references/skeleton-template.md +48 -0
- package/src/pilot/references/sketch-interactivity.md +41 -0
- package/src/pilot/references/sketch-theme-system.md +94 -0
- package/src/pilot/references/sketch-tooling.md +45 -0
- package/src/pilot/references/sketch-variant-patterns.md +81 -0
- package/src/pilot/references/spidr-splitting.md +69 -0
- package/src/pilot/references/thinking-models-debug.md +44 -0
- package/src/pilot/references/thinking-models-execution.md +50 -0
- package/src/pilot/references/thinking-models-planning.md +62 -0
- package/src/pilot/references/thinking-models-research.md +50 -0
- package/src/pilot/references/thinking-models-verification.md +55 -0
- package/src/pilot/references/user-story-template.md +58 -0
- package/src/pilot/references/verify-mvp-mode.md +85 -0
- package/src/pilot/references/worktree-path-safety.md +89 -0
- package/src/pilot/templates/AI-SPEC.md +246 -0
- package/src/pilot/templates/spec.md +307 -0
- package/src/pilot/workflows/ai-integration-phase.md +284 -0
- package/src/pilot/workflows/audit-fix.md +175 -0
- package/src/pilot/workflows/code-review-fix.md +497 -0
- package/src/pilot/workflows/eval-review.md +155 -0
- package/src/pilot/workflows/extract_learnings.md +242 -0
- package/src/pilot/workflows/help.md +5 -0
- package/src/pilot/workflows/import.md +246 -0
- package/src/pilot/workflows/ingest-docs.md +328 -0
- package/src/pilot/workflows/mvp-phase.md +199 -0
- package/src/pilot/workflows/plan-review-convergence.md +329 -0
- package/src/pilot/workflows/scan.md +102 -0
- package/src/pilot/workflows/sketch-wrap-up.md +285 -0
- package/src/pilot/workflows/sketch.md +360 -0
- package/src/pilot/workflows/spec-phase.md +262 -0
- package/src/pilot/workflows/spike-wrap-up.md +306 -0
- package/src/pilot/workflows/spike.md +452 -0
- package/src/pilot/workflows/ultraplan-phase.md +189 -0
- package/src/skills/accessibility/SKILL.md +146 -0
- package/src/skills/agent-architecture-audit/SKILL.md +256 -0
- package/src/skills/agent-eval/SKILL.md +145 -0
- package/src/skills/agent-harness-design/SKILL.md +73 -0
- package/src/skills/agent-introspection-debugging/SKILL.md +153 -0
- package/src/skills/android-clean-architecture/SKILL.md +339 -0
- package/src/skills/angular-developer/SKILL.md +154 -0
- package/src/skills/angular-developer/references/angular-animations.md +160 -0
- package/src/skills/angular-developer/references/angular-aria.md +410 -0
- package/src/skills/angular-developer/references/cli.md +86 -0
- package/src/skills/angular-developer/references/component-harnesses.md +59 -0
- package/src/skills/angular-developer/references/component-styling.md +91 -0
- package/src/skills/angular-developer/references/components.md +117 -0
- package/src/skills/angular-developer/references/creating-services.md +97 -0
- package/src/skills/angular-developer/references/data-resolvers.md +69 -0
- package/src/skills/angular-developer/references/define-routes.md +67 -0
- package/src/skills/angular-developer/references/defining-providers.md +72 -0
- package/src/skills/angular-developer/references/di-fundamentals.md +120 -0
- package/src/skills/angular-developer/references/e2e-testing.md +56 -0
- package/src/skills/angular-developer/references/effects.md +83 -0
- package/src/skills/angular-developer/references/hierarchical-injectors.md +43 -0
- package/src/skills/angular-developer/references/host-elements.md +80 -0
- package/src/skills/angular-developer/references/injection-context.md +63 -0
- package/src/skills/angular-developer/references/inputs.md +101 -0
- package/src/skills/angular-developer/references/linked-signal.md +59 -0
- package/src/skills/angular-developer/references/loading-strategies.md +61 -0
- package/src/skills/angular-developer/references/mcp.md +108 -0
- package/src/skills/angular-developer/references/navigate-to-routes.md +69 -0
- package/src/skills/angular-developer/references/outputs.md +86 -0
- package/src/skills/angular-developer/references/reactive-forms.md +122 -0
- package/src/skills/angular-developer/references/rendering-strategies.md +44 -0
- package/src/skills/angular-developer/references/resource.md +77 -0
- package/src/skills/angular-developer/references/route-animations.md +56 -0
- package/src/skills/angular-developer/references/route-guards.md +52 -0
- package/src/skills/angular-developer/references/router-lifecycle.md +45 -0
- package/src/skills/angular-developer/references/router-testing.md +87 -0
- package/src/skills/angular-developer/references/show-routes-with-outlets.md +68 -0
- package/src/skills/angular-developer/references/signal-forms.md +795 -0
- package/src/skills/angular-developer/references/signals-overview.md +94 -0
- package/src/skills/angular-developer/references/tailwind-css.md +69 -0
- package/src/skills/angular-developer/references/template-driven-forms.md +114 -0
- package/src/skills/angular-developer/references/testing-fundamentals.md +65 -0
- package/src/skills/api-connector-builder/SKILL.md +120 -0
- package/src/skills/code-tour/SKILL.md +236 -0
- package/src/skills/compose-multiplatform-patterns/SKILL.md +299 -0
- package/src/skills/csharp-testing/SKILL.md +321 -0
- package/src/skills/dart-flutter-patterns/SKILL.md +563 -0
- package/src/skills/dashboard-builder/SKILL.md +108 -0
- package/src/skills/dotnet-patterns/SKILL.md +321 -0
- package/src/skills/error-handling/SKILL.md +376 -0
- package/src/skills/fastapi-patterns/SKILL.md +327 -0
- package/src/skills/flox-environments/SKILL.md +496 -0
- package/src/skills/frontend-design/SKILL.md +145 -0
- package/src/skills/frontend-slides/SKILL.md +184 -0
- package/src/skills/frontend-slides/STYLE_PRESETS.md +330 -0
- package/src/skills/fsharp-testing/SKILL.md +280 -0
- package/src/skills/gateguard/SKILL.md +121 -0
- package/src/skills/github-ops/SKILL.md +144 -0
- package/src/skills/hookify-rules/SKILL.md +128 -0
- package/src/skills/ios-icon-gen/SKILL.md +157 -0
- package/src/skills/ios-icon-gen/scripts/generate_icons.swift +258 -0
- package/src/skills/ios-icon-gen/scripts/iconify_gen.sh +235 -0
- package/src/skills/knowledge-ops/SKILL.md +154 -0
- package/src/skills/liquid-glass-design/SKILL.md +279 -0
- package/src/skills/make-interfaces-feel-better/SKILL.md +151 -0
- package/src/skills/mysql-patterns/SKILL.md +412 -0
- package/src/skills/nestjs-patterns/SKILL.md +230 -0
- package/src/skills/plan-orchestrate/SKILL.md +220 -0
- package/src/skills/prisma-patterns/SKILL.md +371 -0
- package/src/skills/production-audit/SKILL.md +206 -0
- package/src/skills/security-bounty-hunter/SKILL.md +99 -0
- package/src/skills/security-scan/references/agentshield-policy-exception/candidate-playbook.md +49 -0
- package/src/skills/security-scan/references/agentshield-policy-exception/report.json +35 -0
- package/src/skills/security-scan/references/agentshield-policy-exception/scenario.json +62 -0
- package/src/skills/security-scan/references/agentshield-policy-exception/trace.json +45 -0
- package/src/skills/security-scan/references/agentshield-policy-exception/verifier-result.json +35 -0
- package/src/skills/swift-actor-persistence/SKILL.md +143 -0
- package/src/skills/swift-protocol-di-testing/SKILL.md +190 -0
- package/src/skills/swiftui-patterns/SKILL.md +259 -0
- package/src/skills/terminal-ops/SKILL.md +109 -0
- package/src/skills/ui-demo/SKILL.md +465 -0
- package/src/skills/vite-patterns/SKILL.md +449 -0
- package/src/skills/windows-desktop-e2e/SKILL.md +887 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Doc File Warning - PreToolUse (Write) hook
|
|
3
|
+
// Warns-only advisory: never blocks the Write, ALWAYS exits 0.
|
|
4
|
+
//
|
|
5
|
+
// Uses a denylist approach: only warn on known ad-hoc documentation
|
|
6
|
+
// filenames (NOTES, TODO, SCRATCH, etc.) written outside structured
|
|
7
|
+
// directories. This avoids false positives for legitimate
|
|
8
|
+
// markdown-heavy workflows (specs, ADRs, command definitions, skill
|
|
9
|
+
// files, etc.).
|
|
10
|
+
//
|
|
11
|
+
// How it works:
|
|
12
|
+
// 1. Reads the PreToolUse JSON payload from stdin (tool_input.file_path).
|
|
13
|
+
// 2. If the basename matches a known ad-hoc doc filename AND the path is
|
|
14
|
+
// NOT inside a structured directory, emits an advisory to stderr.
|
|
15
|
+
// 3. Exits 0 unconditionally (advisory only, never blocks the write).
|
|
16
|
+
//
|
|
17
|
+
// On empty or unparseable stdin it exits 0 silently. Stdlib-only (path).
|
|
18
|
+
|
|
19
|
+
'use strict';
|
|
20
|
+
|
|
21
|
+
const path = require('path');
|
|
22
|
+
|
|
23
|
+
const MAX_STDIN = 1024 * 1024;
|
|
24
|
+
|
|
25
|
+
// Known ad-hoc filenames that signal impulse/scratch docs (case-sensitive, uppercase).
|
|
26
|
+
const ADHOC_FILENAMES = /^(NOTES|TODO|SCRATCH|TEMP|DRAFT|BRAINSTORM|SPIKE|DEBUG|WIP)\.(md|txt)$/;
|
|
27
|
+
|
|
28
|
+
// Structured directories where even ad-hoc names are intentional.
|
|
29
|
+
const STRUCTURED_DIRS = /(^|\/)(docs|\.claude|\.github|commands|skills|benchmarks|templates|\.history|memory)\//;
|
|
30
|
+
|
|
31
|
+
function isSuspiciousDocPath(filePath) {
|
|
32
|
+
const normalized = String(filePath).replace(/\\/g, '/');
|
|
33
|
+
const basename = path.basename(normalized);
|
|
34
|
+
|
|
35
|
+
// Only inspect .md and .txt files (case-sensitive, consistent with ADHOC_FILENAMES).
|
|
36
|
+
if (!/\.(md|txt)$/.test(basename)) return false;
|
|
37
|
+
|
|
38
|
+
// Only flag known ad-hoc filenames.
|
|
39
|
+
if (!ADHOC_FILENAMES.test(basename)) return false;
|
|
40
|
+
|
|
41
|
+
// Allow ad-hoc names inside structured directories (intentional usage).
|
|
42
|
+
if (STRUCTURED_DIRS.test(normalized)) return false;
|
|
43
|
+
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Pure decision function. Returns an advisory string (for stderr) or null.
|
|
48
|
+
// Exported for testing; the CLI below drives it from stdin.
|
|
49
|
+
function matchesDenylist(rawInput) {
|
|
50
|
+
let input;
|
|
51
|
+
try {
|
|
52
|
+
input = typeof rawInput === 'string'
|
|
53
|
+
? (rawInput.trim() ? JSON.parse(rawInput) : {})
|
|
54
|
+
: (rawInput || {});
|
|
55
|
+
} catch (_e) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const filePath = String((input && input.tool_input && input.tool_input.file_path) || '');
|
|
60
|
+
if (!filePath || !isSuspiciousDocPath(filePath)) return null;
|
|
61
|
+
|
|
62
|
+
return (
|
|
63
|
+
'[Hook] WARNING: Ad-hoc documentation filename detected\n' +
|
|
64
|
+
'[Hook] File: ' + filePath + '\n' +
|
|
65
|
+
'[Hook] Consider a structured path (e.g. docs/, .claude/, skills/, .github/, benchmarks/, templates/)'
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
module.exports = { matchesDenylist, isSuspiciousDocPath };
|
|
70
|
+
|
|
71
|
+
if (require.main === module) {
|
|
72
|
+
let data = '';
|
|
73
|
+
|
|
74
|
+
process.stdin.setEncoding('utf8');
|
|
75
|
+
process.stdin.on('data', chunk => {
|
|
76
|
+
if (data.length < MAX_STDIN) {
|
|
77
|
+
data += chunk.substring(0, MAX_STDIN - data.length);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
process.stdin.on('end', () => {
|
|
82
|
+
const advisory = matchesDenylist(data);
|
|
83
|
+
if (advisory) {
|
|
84
|
+
process.stderr.write(advisory + '\n');
|
|
85
|
+
}
|
|
86
|
+
// Pass the payload through unchanged; warns-only, never blocks.
|
|
87
|
+
process.stdout.write(data);
|
|
88
|
+
process.exit(0);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// Empty/closed stdin: exit 0 silently.
|
|
92
|
+
process.stdin.on('error', () => process.exit(0));
|
|
93
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const { runPreBash } = require('./ccp-bash-hook-dispatcher');
|
|
5
|
+
|
|
6
|
+
let raw = '';
|
|
7
|
+
const MAX_STDIN = 1024 * 1024;
|
|
8
|
+
|
|
9
|
+
process.stdin.setEncoding('utf8');
|
|
10
|
+
process.stdin.on('data', chunk => {
|
|
11
|
+
if (raw.length < MAX_STDIN) {
|
|
12
|
+
const remaining = MAX_STDIN - raw.length;
|
|
13
|
+
raw += chunk.substring(0, remaining);
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
process.stdin.on('end', () => {
|
|
18
|
+
const result = runPreBash(raw);
|
|
19
|
+
if (result.stderr) {
|
|
20
|
+
process.stderr.write(result.stderr);
|
|
21
|
+
}
|
|
22
|
+
process.stdout.write(result.output);
|
|
23
|
+
process.exitCode = result.exitCode;
|
|
24
|
+
});
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// ccp-hook-version: {{CCP_VERSION}}
|
|
3
|
+
// CCP Read Injection Scanner — PostToolUse hook (ported from GSD #2201)
|
|
4
|
+
// Scans file content returned by the Read tool for prompt injection patterns.
|
|
5
|
+
// Catches poisoned content at ingestion before it enters conversation context.
|
|
6
|
+
//
|
|
7
|
+
// Defense-in-depth: long sessions hit context compression, and the
|
|
8
|
+
// summariser does not distinguish user instructions from content read from
|
|
9
|
+
// external files. Poisoned instructions that survive compression become
|
|
10
|
+
// indistinguishable from trusted context. This hook warns at ingestion time.
|
|
11
|
+
//
|
|
12
|
+
// Triggers on: Read tool PostToolUse events
|
|
13
|
+
// Action: Advisory warning (does not block) — logs detection for awareness
|
|
14
|
+
// Severity: LOW (1–2 patterns), HIGH (3+ patterns)
|
|
15
|
+
//
|
|
16
|
+
// False-positive exclusion: .planning/, REVIEW.md, CHECKPOINT, security docs,
|
|
17
|
+
// hook source files — these legitimately contain injection-like strings.
|
|
18
|
+
|
|
19
|
+
const path = require('path');
|
|
20
|
+
|
|
21
|
+
// Summarisation-specific patterns (novel — not in ccp-prompt-guard.js).
|
|
22
|
+
// These target instructions specifically designed to survive context compression.
|
|
23
|
+
const SUMMARISATION_PATTERNS = [
|
|
24
|
+
/when\s+(?:summari[sz]ing|compressing|compacting),?\s+(?:retain|preserve|keep)\s+(?:this|these)/i,
|
|
25
|
+
/this\s+(?:instruction|directive|rule)\s+is\s+(?:permanent|persistent|immutable)/i,
|
|
26
|
+
/preserve\s+(?:these|this)\s+(?:rules?|instructions?|directives?)\s+(?:in|through|after|during)/i,
|
|
27
|
+
/(?:retain|keep)\s+(?:this|these)\s+(?:in|through|after)\s+(?:summar|compress|compact)/i,
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
// Standard injection patterns — mirrors ccp-prompt-guard.js, inlined for hook independence.
|
|
31
|
+
const INJECTION_PATTERNS = [
|
|
32
|
+
/ignore\s+(all\s+)?previous\s+instructions/i,
|
|
33
|
+
/ignore\s+(all\s+)?above\s+instructions/i,
|
|
34
|
+
/disregard\s+(all\s+)?previous/i,
|
|
35
|
+
/forget\s+(all\s+)?(your\s+)?instructions/i,
|
|
36
|
+
/override\s+(system|previous)\s+(prompt|instructions)/i,
|
|
37
|
+
/you\s+are\s+now\s+(?:a|an|the)\s+/i,
|
|
38
|
+
/act\s+as\s+(?:a|an|the)\s+(?!plan|phase|wave)/i,
|
|
39
|
+
/pretend\s+(?:you(?:'re| are)\s+|to\s+be\s+)/i,
|
|
40
|
+
/from\s+now\s+on,?\s+you\s+(?:are|will|should|must)/i,
|
|
41
|
+
/(?:print|output|reveal|show|display|repeat)\s+(?:your\s+)?(?:system\s+)?(?:prompt|instructions)/i,
|
|
42
|
+
/<\/?(?:system|assistant|human)>/i,
|
|
43
|
+
/\[SYSTEM\]/i,
|
|
44
|
+
/\[INST\]/i,
|
|
45
|
+
/<<\s*SYS\s*>>/i,
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
const ALL_PATTERNS = [...INJECTION_PATTERNS, ...SUMMARISATION_PATTERNS];
|
|
49
|
+
|
|
50
|
+
function isExcludedPath(filePath) {
|
|
51
|
+
const p = filePath.replace(/\\/g, '/');
|
|
52
|
+
return (
|
|
53
|
+
p.includes('/.planning/') ||
|
|
54
|
+
p.includes('.planning/') ||
|
|
55
|
+
/(?:^|\/)REVIEW\.md$/i.test(p) ||
|
|
56
|
+
/CHECKPOINT/i.test(path.basename(p)) ||
|
|
57
|
+
/[/\\](?:security|techsec|injection)[/\\.]/i.test(p) ||
|
|
58
|
+
/security\.cjs$/.test(p) ||
|
|
59
|
+
p.includes('/.claude/hooks/')
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
let inputBuf = '';
|
|
64
|
+
const stdinTimeout = setTimeout(() => process.exit(0), 5000);
|
|
65
|
+
process.stdin.setEncoding('utf8');
|
|
66
|
+
process.stdin.on('data', chunk => { inputBuf += chunk; });
|
|
67
|
+
process.stdin.on('end', () => {
|
|
68
|
+
clearTimeout(stdinTimeout);
|
|
69
|
+
try {
|
|
70
|
+
const data = JSON.parse(inputBuf);
|
|
71
|
+
|
|
72
|
+
if (data.tool_name !== 'Read') {
|
|
73
|
+
process.exit(0);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const filePath = data.tool_input?.file_path || '';
|
|
77
|
+
if (!filePath) {
|
|
78
|
+
process.exit(0);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (isExcludedPath(filePath)) {
|
|
82
|
+
process.exit(0);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Extract content from tool_response — string (cat -n output) or object form
|
|
86
|
+
let content = '';
|
|
87
|
+
const resp = data.tool_response;
|
|
88
|
+
if (typeof resp === 'string') {
|
|
89
|
+
content = resp;
|
|
90
|
+
} else if (resp && typeof resp === 'object') {
|
|
91
|
+
const c = resp.content;
|
|
92
|
+
if (Array.isArray(c)) {
|
|
93
|
+
content = c.map(b => (typeof b === 'string' ? b : b.text || '')).join('\n');
|
|
94
|
+
} else if (c != null) {
|
|
95
|
+
content = String(c);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (!content || content.length < 20) {
|
|
100
|
+
process.exit(0);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const findings = [];
|
|
104
|
+
|
|
105
|
+
for (const pattern of ALL_PATTERNS) {
|
|
106
|
+
if (pattern.test(content)) {
|
|
107
|
+
// Trim pattern source for readable output
|
|
108
|
+
findings.push(pattern.source.replace(/\\s\+/g, '-').replace(/[()\\]/g, '').substring(0, 50));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Invisible Unicode (zero-width, RTL override, soft hyphen, BOM)
|
|
113
|
+
if (/[\u200B-\u200F\u2028-\u202F\uFEFF\u00AD\u2060-\u2069]/.test(content)) {
|
|
114
|
+
findings.push('invisible-unicode');
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Unicode tag block U+E0000–E007F (invisible instruction injection vector)
|
|
118
|
+
try {
|
|
119
|
+
if (/[\u{E0000}-\u{E007F}]/u.test(content)) {
|
|
120
|
+
findings.push('unicode-tag-block');
|
|
121
|
+
}
|
|
122
|
+
} catch {
|
|
123
|
+
// Engine does not support Unicode property escapes — skip this check
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (findings.length === 0) {
|
|
127
|
+
process.exit(0);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const severity = findings.length >= 3 ? 'HIGH' : 'LOW';
|
|
131
|
+
const fileName = path.basename(filePath);
|
|
132
|
+
const detail = severity === 'HIGH'
|
|
133
|
+
? 'Multiple patterns — strong injection signal. Review the file for embedded instructions before proceeding.'
|
|
134
|
+
: 'Single pattern match may be a false positive (e.g., documentation). Proceed with awareness.';
|
|
135
|
+
|
|
136
|
+
const output = {
|
|
137
|
+
hookSpecificOutput: {
|
|
138
|
+
hookEventName: 'PostToolUse',
|
|
139
|
+
additionalContext:
|
|
140
|
+
`\u26a0\ufe0f READ INJECTION SCAN [${severity}]: File "${fileName}" triggered ` +
|
|
141
|
+
`${findings.length} pattern(s): ${findings.join(', ')}. ` +
|
|
142
|
+
`This content is now in your conversation context. ${detail} ` +
|
|
143
|
+
`Source: ${filePath}`,
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
process.stdout.write(JSON.stringify(output));
|
|
148
|
+
} catch {
|
|
149
|
+
// Silent fail — never block tool execution
|
|
150
|
+
process.exit(0);
|
|
151
|
+
}
|
|
152
|
+
});
|