@cybedefend/vibedefend 1.5.0 → 1.7.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/README.md +71 -2
- package/dist/api/gateway-request.js +49 -0
- package/dist/api/gateway-request.js.map +1 -0
- package/dist/api/projects.js +67 -0
- package/dist/api/projects.js.map +1 -1
- package/dist/api/repository-link.js +157 -0
- package/dist/api/repository-link.js.map +1 -0
- package/dist/auth/auth-store.js +107 -25
- package/dist/auth/auth-store.js.map +1 -1
- package/dist/auth/auth.js +21 -0
- package/dist/auth/auth.js.map +1 -1
- package/dist/clients/cursor.js +5 -1
- package/dist/clients/cursor.js.map +1 -1
- package/dist/clients/vscode.js +38 -29
- package/dist/clients/vscode.js.map +1 -1
- package/dist/commands/mcp/allow.js +219 -0
- package/dist/commands/mcp/allow.js.map +1 -0
- package/dist/commands/mcp/connect.js +337 -0
- package/dist/commands/mcp/connect.js.map +1 -0
- package/dist/commands/mcp/index.js +170 -0
- package/dist/commands/mcp/index.js.map +1 -0
- package/dist/commands/mcp/proxy.js +320 -0
- package/dist/commands/mcp/proxy.js.map +1 -0
- package/dist/commands/mcp/scan.js +349 -0
- package/dist/commands/mcp/scan.js.map +1 -0
- package/dist/commands/mcp/sync.js +215 -0
- package/dist/commands/mcp/sync.js.map +1 -0
- package/dist/config.js +6 -0
- package/dist/config.js.map +1 -1
- package/dist/diagnostics.js +78 -12
- package/dist/diagnostics.js.map +1 -1
- package/dist/doctor.js +19 -0
- package/dist/doctor.js.map +1 -1
- package/dist/guards-evaluator/analysis-types.js +27 -0
- package/dist/guards-evaluator/analysis-types.js.map +1 -0
- package/dist/guards-evaluator/command-analysis.js +572 -0
- package/dist/guards-evaluator/command-analysis.js.map +1 -0
- package/dist/guards-evaluator/command-view.js +586 -0
- package/dist/guards-evaluator/command-view.js.map +1 -0
- package/dist/guards-evaluator/env.js +11 -0
- package/dist/guards-evaluator/env.js.map +1 -0
- package/dist/guards-evaluator/evaluate.js +91 -41
- package/dist/guards-evaluator/evaluate.js.map +1 -1
- package/dist/guards-evaluator/index.js +2 -1
- package/dist/guards-evaluator/index.js.map +1 -1
- package/dist/guards-evaluator/inline-code.js +259 -0
- package/dist/guards-evaluator/inline-code.js.map +1 -0
- package/dist/guards-evaluator/normalize.js +716 -0
- package/dist/guards-evaluator/normalize.js.map +1 -0
- package/dist/guards-evaluator/preprocess.js +13 -5
- package/dist/guards-evaluator/preprocess.js.map +1 -1
- package/dist/guards-evaluator/redact.js +19 -0
- package/dist/guards-evaluator/redact.js.map +1 -1
- package/dist/guards-evaluator/regex.js +25 -3
- package/dist/guards-evaluator/regex.js.map +1 -1
- package/dist/guards-evaluator/safe-commands.js +155 -0
- package/dist/guards-evaluator/safe-commands.js.map +1 -0
- package/dist/guards-evaluator/triage.js +315 -0
- package/dist/guards-evaluator/triage.js.map +1 -0
- package/dist/hook-runner.js +24679 -5079
- package/dist/hooks/install.js +38 -0
- package/dist/hooks/install.js.map +1 -1
- package/dist/hooks/runtime/config.js +38 -0
- package/dist/hooks/runtime/config.js.map +1 -1
- package/dist/hooks/runtime/emit.js +94 -61
- package/dist/hooks/runtime/emit.js.map +1 -1
- package/dist/hooks/runtime/fetch-rules.js +22 -7
- package/dist/hooks/runtime/fetch-rules.js.map +1 -1
- package/dist/hooks/runtime/gateway-http-error.js +34 -0
- package/dist/hooks/runtime/gateway-http-error.js.map +1 -0
- package/dist/hooks/runtime/guard-rules-cache.js +139 -17
- package/dist/hooks/runtime/guard-rules-cache.js.map +1 -1
- package/dist/hooks/runtime/guard-violations-buffer.js +321 -48
- package/dist/hooks/runtime/guard-violations-buffer.js.map +1 -1
- package/dist/hooks/runtime/judge-cache.js +6 -0
- package/dist/hooks/runtime/judge-cache.js.map +1 -1
- package/dist/hooks/runtime/judge-triage.js +193 -0
- package/dist/hooks/runtime/judge-triage.js.map +1 -0
- package/dist/hooks/runtime/judge.js +7 -1
- package/dist/hooks/runtime/judge.js.map +1 -1
- package/dist/hooks/runtime/pre-compact.js +12 -6
- package/dist/hooks/runtime/pre-compact.js.map +1 -1
- package/dist/hooks/runtime/resolve.js +90 -8
- package/dist/hooks/runtime/resolve.js.map +1 -1
- package/dist/hooks/runtime/retry-policy.js +57 -0
- package/dist/hooks/runtime/retry-policy.js.map +1 -0
- package/dist/hooks/runtime/review-sessions.js +74 -0
- package/dist/hooks/runtime/review-sessions.js.map +1 -0
- package/dist/hooks/runtime/script-resolve.js +695 -0
- package/dist/hooks/runtime/script-resolve.js.map +1 -0
- package/dist/hooks/runtime/session-activation.js +5 -1
- package/dist/hooks/runtime/session-activation.js.map +1 -1
- package/dist/hooks/runtime/session-review.js +163 -45
- package/dist/hooks/runtime/session-review.js.map +1 -1
- package/dist/hooks/runtime/session-start.js +2 -1
- package/dist/hooks/runtime/session-start.js.map +1 -1
- package/dist/hooks/runtime/session-writes.js +232 -0
- package/dist/hooks/runtime/session-writes.js.map +1 -0
- package/dist/hooks/runtime/sniff.js +26 -7
- package/dist/hooks/runtime/sniff.js.map +1 -1
- package/dist/hooks/runtime/target-resolve.js +336 -0
- package/dist/hooks/runtime/target-resolve.js.map +1 -0
- package/dist/hooks/runtime/unmapped-tools.js +93 -0
- package/dist/hooks/runtime/unmapped-tools.js.map +1 -0
- package/dist/hooks/runtime/usage-block.js +4 -0
- package/dist/hooks/runtime/usage-block.js.map +1 -1
- package/dist/hooks/runtime/user-prompt-submit.js +2 -1
- package/dist/hooks/runtime/user-prompt-submit.js.map +1 -1
- package/dist/hooks/runtime/wire-text.js +41 -0
- package/dist/hooks/runtime/wire-text.js.map +1 -0
- package/dist/hooks/runtime/work-dir.js +84 -0
- package/dist/hooks/runtime/work-dir.js.map +1 -0
- package/dist/index.js +45 -12
- package/dist/index.js.map +1 -1
- package/dist/install.js +174 -11
- package/dist/install.js.map +1 -1
- package/dist/link.js +74 -48
- package/dist/link.js.map +1 -1
- package/dist/login.js +77 -11
- package/dist/login.js.map +1 -1
- package/dist/mcp/auth/agent-sign-ins.js +174 -0
- package/dist/mcp/auth/agent-sign-ins.js.map +1 -0
- package/dist/mcp/auth/callback.js +200 -0
- package/dist/mcp/auth/callback.js.map +1 -0
- package/dist/mcp/auth/connect.js +392 -0
- package/dist/mcp/auth/connect.js.map +1 -0
- package/dist/mcp/auth/discovery.js +399 -0
- package/dist/mcp/auth/discovery.js.map +1 -0
- package/dist/mcp/auth/oauth.js +326 -0
- package/dist/mcp/auth/oauth.js.map +1 -0
- package/dist/mcp/auth/probe.js +128 -0
- package/dist/mcp/auth/probe.js.map +1 -0
- package/dist/mcp/auth/secrets.js +446 -0
- package/dist/mcp/auth/secrets.js.map +1 -0
- package/dist/mcp/auth/store.js +260 -0
- package/dist/mcp/auth/store.js.map +1 -0
- package/dist/mcp/auth/tokenSource.js +55 -0
- package/dist/mcp/auth/tokenSource.js.map +1 -0
- package/dist/mcp/config/atomicWrite.js +98 -0
- package/dist/mcp/config/atomicWrite.js.map +1 -0
- package/dist/mcp/config/clients.js +171 -0
- package/dist/mcp/config/clients.js.map +1 -0
- package/dist/mcp/config/cybedefend-servers.js +48 -0
- package/dist/mcp/config/cybedefend-servers.js.map +1 -0
- package/dist/mcp/config/discover.js +114 -0
- package/dist/mcp/config/discover.js.map +1 -0
- package/dist/mcp/config/hook.js +123 -0
- package/dist/mcp/config/hook.js.map +1 -0
- package/dist/mcp/config/index.js +11 -0
- package/dist/mcp/config/index.js.map +1 -0
- package/dist/mcp/config/install.js +132 -0
- package/dist/mcp/config/install.js.map +1 -0
- package/dist/mcp/config/installed.js +37 -0
- package/dist/mcp/config/installed.js.map +1 -0
- package/dist/mcp/config/jsonEdit.js +119 -0
- package/dist/mcp/config/jsonEdit.js.map +1 -0
- package/dist/mcp/config/lock.js +102 -0
- package/dist/mcp/config/lock.js.map +1 -0
- package/dist/mcp/config/proxyBinary.js +211 -0
- package/dist/mcp/config/proxyBinary.js.map +1 -0
- package/dist/mcp/config/rewrite.js +388 -0
- package/dist/mcp/config/rewrite.js.map +1 -0
- package/dist/mcp/config/types.js +34 -0
- package/dist/mcp/config/types.js.map +1 -0
- package/dist/mcp/proxy/audit.js +83 -0
- package/dist/mcp/proxy/audit.js.map +1 -0
- package/dist/mcp/proxy/authInterceptor.js +119 -0
- package/dist/mcp/proxy/authInterceptor.js.map +1 -0
- package/dist/mcp/proxy/expand.js +93 -0
- package/dist/mcp/proxy/expand.js.map +1 -0
- package/dist/mcp/proxy/inject.js +412 -0
- package/dist/mcp/proxy/inject.js.map +1 -0
- package/dist/mcp/proxy/intercept.js +63 -0
- package/dist/mcp/proxy/intercept.js.map +1 -0
- package/dist/mcp/proxy/jsonrpc.js +153 -0
- package/dist/mcp/proxy/jsonrpc.js.map +1 -0
- package/dist/mcp/proxy/log.js +109 -0
- package/dist/mcp/proxy/log.js.map +1 -0
- package/dist/mcp/proxy/paths.js +57 -0
- package/dist/mcp/proxy/paths.js.map +1 -0
- package/dist/mcp/proxy/proxy.js +520 -0
- package/dist/mcp/proxy/proxy.js.map +1 -0
- package/dist/mcp/proxy/serverCheckTimer.js +75 -0
- package/dist/mcp/proxy/serverCheckTimer.js.map +1 -0
- package/dist/mcp/proxy/sessionLifecycle.js +29 -0
- package/dist/mcp/proxy/sessionLifecycle.js.map +1 -0
- package/dist/mcp/proxy/spec.js +203 -0
- package/dist/mcp/proxy/spec.js.map +1 -0
- package/dist/mcp/proxy/sse.js +77 -0
- package/dist/mcp/proxy/sse.js.map +1 -0
- package/dist/mcp/proxy/upstream.js +2 -0
- package/dist/mcp/proxy/upstream.js.map +1 -0
- package/dist/mcp/proxy/upstreamHttp.js +499 -0
- package/dist/mcp/proxy/upstreamHttp.js.map +1 -0
- package/dist/mcp/proxy/upstreamStdio.js +188 -0
- package/dist/mcp/proxy/upstreamStdio.js.map +1 -0
- package/dist/mcp/proxy/upstreams.js +143 -0
- package/dist/mcp/proxy/upstreams.js.map +1 -0
- package/dist/mcp/proxy/verifyInterceptor.js +718 -0
- package/dist/mcp/proxy/verifyInterceptor.js.map +1 -0
- package/dist/mcp/proxy/windowsCommand.js +99 -0
- package/dist/mcp/proxy/windowsCommand.js.map +1 -0
- package/dist/mcp/report/buffer.js +351 -0
- package/dist/mcp/report/buffer.js.map +1 -0
- package/dist/mcp/report/coalesce.js +165 -0
- package/dist/mcp/report/coalesce.js.map +1 -0
- package/dist/mcp/report/constants.js +51 -0
- package/dist/mcp/report/constants.js.map +1 -0
- package/dist/mcp/report/project.js +83 -0
- package/dist/mcp/report/project.js.map +1 -0
- package/dist/mcp/report/reporter.js +443 -0
- package/dist/mcp/report/reporter.js.map +1 -0
- package/dist/mcp/report/types.js +3 -0
- package/dist/mcp/report/types.js.map +1 -0
- package/dist/mcp/report/validate.js +179 -0
- package/dist/mcp/report/validate.js.map +1 -0
- package/dist/mcp/scan/args.js +228 -0
- package/dist/mcp/scan/args.js.map +1 -0
- package/dist/mcp/scan/results.js +253 -0
- package/dist/mcp/scan/results.js.map +1 -0
- package/dist/mcp/scan/types.js +40 -0
- package/dist/mcp/scan/types.js.map +1 -0
- package/dist/mcp/verify/api.js +514 -0
- package/dist/mcp/verify/api.js.map +1 -0
- package/dist/mcp/verify/backend.js +143 -0
- package/dist/mcp/verify/backend.js.map +1 -0
- package/dist/mcp/verify/cache.js +200 -0
- package/dist/mcp/verify/cache.js.map +1 -0
- package/dist/mcp/verify/contract-errors.js +198 -0
- package/dist/mcp/verify/contract-errors.js.map +1 -0
- package/dist/mcp/verify/digest.js +91 -0
- package/dist/mcp/verify/digest.js.map +1 -0
- package/dist/mcp/verify/factory.js +56 -0
- package/dist/mcp/verify/factory.js.map +1 -0
- package/dist/mcp/verify/identity.js +286 -0
- package/dist/mcp/verify/identity.js.map +1 -0
- package/dist/mcp/verify/policy-store.js +63 -0
- package/dist/mcp/verify/policy-store.js.map +1 -0
- package/dist/mcp/verify/policy.js +160 -0
- package/dist/mcp/verify/policy.js.map +1 -0
- package/dist/mcp/verify/pool.js +27 -0
- package/dist/mcp/verify/pool.js.map +1 -0
- package/dist/mcp/verify/token-refresh.js +44 -0
- package/dist/mcp/verify/token-refresh.js.map +1 -0
- package/dist/mcp/verify/token.js +67 -0
- package/dist/mcp/verify/token.js.map +1 -0
- package/dist/mcp/verify/verifier.js +1166 -0
- package/dist/mcp/verify/verifier.js.map +1 -0
- package/dist/org-gate.js +1 -1
- package/dist/org-gate.js.map +1 -1
- package/dist/org.js +146 -0
- package/dist/org.js.map +1 -0
- package/dist/project-create.js +129 -0
- package/dist/project-create.js.map +1 -0
- package/dist/prompts.js +21 -0
- package/dist/prompts.js.map +1 -1
- package/dist/re2.wasm +0 -0
- package/dist/status.js +61 -0
- package/dist/status.js.map +1 -1
- package/dist/uninstall.js +49 -4
- package/dist/uninstall.js.map +1 -1
- package/dist/utils.js +62 -6
- package/dist/utils.js.map +1 -1
- package/package.json +10 -3
|
@@ -0,0 +1,572 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Action Guards hardening — the integration layer that ties Level 0/1 together.
|
|
3
|
+
*
|
|
4
|
+
* The regex evaluator (`evaluate`) matches the RAW command string, so trivial
|
|
5
|
+
* rewrites slip past it as `allow`: `/bin/rm`, `rm --recursive --force`,
|
|
6
|
+
* `bash -c "rm -rf ~"`, `eval "…"`, `$( … )`, a heredoc body, `xargs`,
|
|
7
|
+
* `find -exec`. This module re-runs the SAME, already-reviewed rules against
|
|
8
|
+
* de-obfuscated forms of the action, and adds a tight local backstop for the
|
|
9
|
+
* handful of patterns that are dangerous on their face (`triage.ts`).
|
|
10
|
+
*
|
|
11
|
+
* Design guarantees:
|
|
12
|
+
* - It REUSES the existing rules; it never invents new deny logic beyond the
|
|
13
|
+
* curated `triage` dangerous set, and each local block is raised under the
|
|
14
|
+
* project's rule for that family (`LOCAL_BLOCK_RULES`), with its action.
|
|
15
|
+
* - The local backstop reads commands (executable, flags, operands), never
|
|
16
|
+
* the text of a data argument.
|
|
17
|
+
* - It NEVER REORDERS tokens and keeps each argument a single token, so the
|
|
18
|
+
* data-arg masking in `evaluate`/`preprocess` still fires — a commit message
|
|
19
|
+
* `git commit -m "fix rm -rf"` cannot become a false positive.
|
|
20
|
+
* - PURE + NEVER THROWS. Disk-backed resolution (globs/symlinks, executed
|
|
21
|
+
* scripts) is injected by the caller; absent it, this is a pure function.
|
|
22
|
+
*
|
|
23
|
+
* It is consumed by the PreToolUse hook (guard-check.ts) and by the corpus
|
|
24
|
+
* measurement; keeping the orchestration here means both see the same verdict.
|
|
25
|
+
*/
|
|
26
|
+
import { parse as shellParse } from 'shell-quote';
|
|
27
|
+
import { evaluate } from './evaluate.js';
|
|
28
|
+
import { extractInlineCode } from './inline-code.js';
|
|
29
|
+
import { normalizeCommand } from './normalize.js';
|
|
30
|
+
import { isCatastrophicPathArg, triageCommand } from './triage.js';
|
|
31
|
+
const SEVERITY_RANK = {
|
|
32
|
+
critical: 4,
|
|
33
|
+
high: 3,
|
|
34
|
+
medium: 2,
|
|
35
|
+
low: 1,
|
|
36
|
+
};
|
|
37
|
+
const VERDICT_RANK = { deny: 3, warn: 2, allow: 1 };
|
|
38
|
+
/** Shell operators that end a simple command segment. */
|
|
39
|
+
const SEGMENT_OPS = new Set([';', '&&', '||', '|', '|&', '&', '(', ')']);
|
|
40
|
+
/** Leading wrappers that don't change what runs; skipped to expose the real exe. */
|
|
41
|
+
const TRANSPARENT_PREFIXES = new Set([
|
|
42
|
+
'sudo', 'doas', 'nohup', 'command', 'time', 'nice', 'stdbuf', 'setsid', 'env',
|
|
43
|
+
]);
|
|
44
|
+
/** Long→short flag spellings for the destructive commands whose rules key on `-rf`/`-R`. */
|
|
45
|
+
const LONG_TO_SHORT = {
|
|
46
|
+
rm: { recursive: 'r', force: 'f' },
|
|
47
|
+
cp: { recursive: 'r', force: 'f' },
|
|
48
|
+
mv: { force: 'f' },
|
|
49
|
+
chmod: { recursive: 'R' },
|
|
50
|
+
chown: { recursive: 'R' },
|
|
51
|
+
};
|
|
52
|
+
const MAX_FORMS = 64;
|
|
53
|
+
function canonicalExecutable(token) {
|
|
54
|
+
// strip a single leading backslash (`\rm`), take the basename, lower-case.
|
|
55
|
+
const noEsc = token.startsWith('\\') ? token.slice(1) : token;
|
|
56
|
+
const base = noEsc.split('/').pop() ?? noEsc;
|
|
57
|
+
return base.toLowerCase();
|
|
58
|
+
}
|
|
59
|
+
/** Stronger of two decisions: deny > warn > allow; ties broken by severity. */
|
|
60
|
+
function strongest(a, b) {
|
|
61
|
+
const av = VERDICT_RANK[a.verdict];
|
|
62
|
+
const bv = VERDICT_RANK[b.verdict];
|
|
63
|
+
if (bv > av)
|
|
64
|
+
return mergeMatched(b, a);
|
|
65
|
+
if (av > bv)
|
|
66
|
+
return mergeMatched(a, b);
|
|
67
|
+
// same verdict: keep the higher max severity, union matched ids.
|
|
68
|
+
const as = a.maxSeverity ? SEVERITY_RANK[a.maxSeverity] : 0;
|
|
69
|
+
const bs = b.maxSeverity ? SEVERITY_RANK[b.maxSeverity] : 0;
|
|
70
|
+
return mergeMatched(bs > as ? b : a, bs > as ? a : b);
|
|
71
|
+
}
|
|
72
|
+
function mergeMatched(primary, other) {
|
|
73
|
+
const ids = [...new Set([...primary.matchedRuleIds, ...other.matchedRuleIds])];
|
|
74
|
+
return { ...primary, matchedRuleIds: ids };
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Split a raw command line into ordered token segments. Each segment keeps its
|
|
78
|
+
* tokens in ORIGINAL order (no reordering) so argument masking downstream still
|
|
79
|
+
* works. `$VAR` is preserved (never substituted to empty). Op objects and the
|
|
80
|
+
* argv path's bare-string ops both split a segment.
|
|
81
|
+
*/
|
|
82
|
+
function tokenSegments(raw) {
|
|
83
|
+
let tokens;
|
|
84
|
+
try {
|
|
85
|
+
tokens = shellParse(raw, (k) => '$' + k);
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return [raw.split(/\s+/).filter(Boolean)];
|
|
89
|
+
}
|
|
90
|
+
const segments = [];
|
|
91
|
+
let current = [];
|
|
92
|
+
for (const tok of tokens) {
|
|
93
|
+
if (typeof tok === 'object' && 'op' in tok) {
|
|
94
|
+
if (current.length)
|
|
95
|
+
segments.push(current);
|
|
96
|
+
current = [];
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
if (typeof tok === 'string') {
|
|
100
|
+
if (SEGMENT_OPS.has(tok)) {
|
|
101
|
+
if (current.length)
|
|
102
|
+
segments.push(current);
|
|
103
|
+
current = [];
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
current.push(tok);
|
|
107
|
+
}
|
|
108
|
+
// patterns/comments: ignore for canonical evaluation (the raw form still runs)
|
|
109
|
+
}
|
|
110
|
+
if (current.length)
|
|
111
|
+
segments.push(current);
|
|
112
|
+
return segments;
|
|
113
|
+
}
|
|
114
|
+
/** Drop leading `VAR=value` assignments and transparent wrappers to expose the real exe. */
|
|
115
|
+
function stripLeading(tokens) {
|
|
116
|
+
let i = 0;
|
|
117
|
+
while (i < tokens.length) {
|
|
118
|
+
const t = tokens[i];
|
|
119
|
+
if (/^[A-Za-z_][A-Za-z0-9_]*=/.test(t)) {
|
|
120
|
+
i++;
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
if (TRANSPARENT_PREFIXES.has(canonicalExecutable(t))) {
|
|
124
|
+
// `env`/`nice`/… may take their own options; skip a following VAR= or -opt value conservatively.
|
|
125
|
+
i++;
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
return tokens.slice(i);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Canonicalise one segment's tokens: exe basename + long→short flags.
|
|
134
|
+
*
|
|
135
|
+
* For a DESTRUCTIVE command (one in LONG_TO_SHORT: rm/cp/mv/chmod/chown) the
|
|
136
|
+
* flags are COMBINED into one `-rf`-style cluster so the existing rule regexes
|
|
137
|
+
* (which key on `-rf` / `-R`) match `rm --recursive --force ~` and `rm -r -f ~`
|
|
138
|
+
* alike. Reordering is safe here because these commands take no free-text data
|
|
139
|
+
* argument (unlike `git commit -m`), so argument-masking can never be defeated.
|
|
140
|
+
* For every other command, tokens are rewritten IN PLACE (no reorder, no flag
|
|
141
|
+
* merge) so `git commit -m "fix rm -rf"` keeps its message as one masked token.
|
|
142
|
+
*/
|
|
143
|
+
function canonicalizeSegment(tokens) {
|
|
144
|
+
const stripped = stripLeading(tokens);
|
|
145
|
+
if (stripped.length === 0)
|
|
146
|
+
return null;
|
|
147
|
+
const exe = canonicalExecutable(stripped[0]);
|
|
148
|
+
if (!exe)
|
|
149
|
+
return null;
|
|
150
|
+
const flagMap = LONG_TO_SHORT[exe];
|
|
151
|
+
const rest = stripped.slice(1);
|
|
152
|
+
if (flagMap) {
|
|
153
|
+
const letters = new Set();
|
|
154
|
+
const nonFlags = [];
|
|
155
|
+
for (const t of rest) {
|
|
156
|
+
if (t === '--')
|
|
157
|
+
continue;
|
|
158
|
+
if (t.startsWith('--')) {
|
|
159
|
+
const name = t.replace(/^--/, '').split('=')[0];
|
|
160
|
+
const short = flagMap[name];
|
|
161
|
+
if (short)
|
|
162
|
+
letters.add(short);
|
|
163
|
+
// an unmapped long flag on a destructive cmd carries no data: drop it
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
if (/^-[A-Za-z]+$/.test(t)) {
|
|
167
|
+
for (const ch of t.slice(1))
|
|
168
|
+
letters.add(ch);
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
nonFlags.push(t);
|
|
172
|
+
}
|
|
173
|
+
const argv = letters.size ? ['-' + [...letters].join(''), ...nonFlags] : nonFlags;
|
|
174
|
+
return { command: exe, argv };
|
|
175
|
+
}
|
|
176
|
+
const argv = rest.map((t) => t); // in-place, order + quote boundaries preserved
|
|
177
|
+
return { command: exe, argv };
|
|
178
|
+
}
|
|
179
|
+
function evaluateCommandForm(rules, req, command, argv) {
|
|
180
|
+
const target = { type: 'command', command, argv, cwd: req.cwd };
|
|
181
|
+
return evaluate(rules, { ...req, target });
|
|
182
|
+
}
|
|
183
|
+
/** The judge reads at most this many scripts per command. */
|
|
184
|
+
export const MAX_JUDGED_SCRIPTS = 3;
|
|
185
|
+
/**
|
|
186
|
+
* Third-party code the agent runs through a tool (`node_modules/.bin/jest`,
|
|
187
|
+
* `.venv/bin/pytest`, a package's `__main__.py`): not the agent's script, so it
|
|
188
|
+
* is not judged — unless the agent wrote it this session.
|
|
189
|
+
*/
|
|
190
|
+
const THIRD_PARTY_PATH = /\/(node_modules|site-packages|dist-packages|\.tox)\/|\/\.?venv\/(bin|lib)\//;
|
|
191
|
+
function scriptLabel(path, cwd, homeDir) {
|
|
192
|
+
if (cwd && path.startsWith(cwd.endsWith('/') ? cwd : `${cwd}/`)) {
|
|
193
|
+
return path.slice(cwd.endsWith('/') ? cwd.length : cwd.length + 1);
|
|
194
|
+
}
|
|
195
|
+
if (homeDir && path.startsWith(`${homeDir}/`))
|
|
196
|
+
return `~/${path.slice(homeDir.length + 1)}`;
|
|
197
|
+
return path;
|
|
198
|
+
}
|
|
199
|
+
/** Add a script unless the list is full or holds the same text. */
|
|
200
|
+
function addScript(list, script) {
|
|
201
|
+
if (list.length >= MAX_JUDGED_SCRIPTS)
|
|
202
|
+
return;
|
|
203
|
+
if (script.body.trim().length === 0)
|
|
204
|
+
return;
|
|
205
|
+
if (list.some((s) => s.language === script.language && s.body === script.body))
|
|
206
|
+
return;
|
|
207
|
+
list.push(script);
|
|
208
|
+
}
|
|
209
|
+
function addInline(list, command) {
|
|
210
|
+
for (const code of extractInlineCode(command)) {
|
|
211
|
+
addScript(list, { origin: 'inline', language: code.language, label: 'inline', body: code.code, truncated: false });
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Script hops: a command's script (hop 0 → 1), and a script that script or a
|
|
216
|
+
* package script runs (hop 1 → 2). A third level is not read.
|
|
217
|
+
*/
|
|
218
|
+
const MAX_SCRIPT_HOPS = 2;
|
|
219
|
+
export function analyzeCommandAction(rules, req, rawCommand, opts = {}) {
|
|
220
|
+
const forms = [];
|
|
221
|
+
let decision = evaluate(rules, req); // candidate (a): the raw action, as today
|
|
222
|
+
// The scripts this command runs, for the script judge. Collecting one never
|
|
223
|
+
// changes the verdict here.
|
|
224
|
+
const scripts = [];
|
|
225
|
+
try {
|
|
226
|
+
addInline(scripts, rawCommand);
|
|
227
|
+
}
|
|
228
|
+
catch {
|
|
229
|
+
/* never throw */
|
|
230
|
+
}
|
|
231
|
+
try {
|
|
232
|
+
// Candidate set (b): in-place canonical forms of each top-level segment.
|
|
233
|
+
for (const seg of tokenSegments(rawCommand)) {
|
|
234
|
+
const canon = canonicalizeSegment(seg);
|
|
235
|
+
if (!canon)
|
|
236
|
+
continue;
|
|
237
|
+
const form = [canon.command, ...canon.argv].join(' ');
|
|
238
|
+
if (forms.length < MAX_FORMS && !forms.includes(form)) {
|
|
239
|
+
forms.push(form);
|
|
240
|
+
decision = strongest(decision, evaluateCommandForm(rules, req, canon.command, canon.argv));
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
catch {
|
|
245
|
+
/* never throw */
|
|
246
|
+
}
|
|
247
|
+
// Candidate set (c): de-nested inner commands (bash -c, eval, $(), heredoc,
|
|
248
|
+
// xargs, find -exec). normalize recovers them; we evaluate each inner raw the
|
|
249
|
+
// same way (one more de-obfuscation hop).
|
|
250
|
+
let normalize;
|
|
251
|
+
let triage;
|
|
252
|
+
try {
|
|
253
|
+
normalize = normalizeCommand(rawCommand);
|
|
254
|
+
for (const cmd of normalize.commands) {
|
|
255
|
+
if (cmd.depth === 0)
|
|
256
|
+
continue; // top-level already covered above
|
|
257
|
+
for (const seg of tokenSegments(cmd.raw)) {
|
|
258
|
+
const canon = canonicalizeSegment(seg);
|
|
259
|
+
if (!canon)
|
|
260
|
+
continue;
|
|
261
|
+
const form = [canon.command, ...canon.argv].join(' ');
|
|
262
|
+
if (forms.length < MAX_FORMS && !forms.includes(form)) {
|
|
263
|
+
forms.push(form);
|
|
264
|
+
decision = strongest(decision, evaluateCommandForm(rules, req, canon.command, canon.argv));
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
triage = triageCommand(normalize);
|
|
269
|
+
}
|
|
270
|
+
catch {
|
|
271
|
+
/* never throw */
|
|
272
|
+
}
|
|
273
|
+
// Local backstop: a tight, curated "dangerous on its face" set (rm -rf of
|
|
274
|
+
// ~ / /, decode|shell, chmod 777 broad) that the regex may still miss after
|
|
275
|
+
// de-obfuscation. These are safe to block locally (see triage.ts).
|
|
276
|
+
let localBlockReason;
|
|
277
|
+
if (decision.verdict !== 'allow' && forms.length > 0 && decision.matchedRuleIds.length > 0) {
|
|
278
|
+
// raw already denied/warned OR a de-obfuscated form did
|
|
279
|
+
localBlockReason = decision.verdict === 'deny' ? 'regex-deobfuscated' : localBlockReason;
|
|
280
|
+
}
|
|
281
|
+
// A local block is raised under the project's rule for that family
|
|
282
|
+
// (LOCAL_BLOCK_RULES) and takes its effective action: it is recorded like any
|
|
283
|
+
// violation, the judge may overturn it, and a project that set the rule to
|
|
284
|
+
// `warn` or `off` is obeyed.
|
|
285
|
+
const supplementReason = supplementDangerous(normalize, rawCommand);
|
|
286
|
+
const localReasons = [
|
|
287
|
+
...(supplementReason ? [supplementReason] : []),
|
|
288
|
+
...(triage?.class === 'dangerous' ? triage.reasons : []),
|
|
289
|
+
];
|
|
290
|
+
for (const reason of localReasons) {
|
|
291
|
+
const local = localBlockDecision(rules, reason);
|
|
292
|
+
if (!local)
|
|
293
|
+
continue;
|
|
294
|
+
if (local.verdict === 'deny' && decision.verdict !== 'deny')
|
|
295
|
+
localBlockReason = 'triage-dangerous';
|
|
296
|
+
decision = strongest(decision, local);
|
|
297
|
+
}
|
|
298
|
+
if (decision.verdict === 'deny' && !localBlockReason && forms.length > 0) {
|
|
299
|
+
localBlockReason = 'regex-deobfuscated';
|
|
300
|
+
}
|
|
301
|
+
// Level 1 — executed scripts. When the command runs a local file the agent
|
|
302
|
+
// can control (`bash x.sh`, `./x`, `npm run …`), read it and fold the verdict
|
|
303
|
+
// of its inner commands in. A script the agent WROTE this session that runs
|
|
304
|
+
// something dangerous is the write-then-run blind spot; a script that is only
|
|
305
|
+
// suspicious escalates the judge route rather than hard-blocking (FP-averse).
|
|
306
|
+
const hop = opts._scriptHop ?? 0;
|
|
307
|
+
let scriptEscalation = 'none';
|
|
308
|
+
if (opts.resolveScript && hop < MAX_SCRIPT_HOPS) {
|
|
309
|
+
try {
|
|
310
|
+
const script = opts.resolveScript(rawCommand);
|
|
311
|
+
if (script) {
|
|
312
|
+
const writtenHere = script.path ? opts.wasWrittenThisSession?.(script.path) ?? false : false;
|
|
313
|
+
const language = script.language ?? (script.kind === 'shell' ? 'shell' : undefined);
|
|
314
|
+
if (script.kind !== 'npm-script' &&
|
|
315
|
+
script.path &&
|
|
316
|
+
language &&
|
|
317
|
+
typeof script.content === 'string' &&
|
|
318
|
+
(writtenHere || !THIRD_PARTY_PATH.test(script.path))) {
|
|
319
|
+
addScript(scripts, {
|
|
320
|
+
origin: 'file',
|
|
321
|
+
language,
|
|
322
|
+
label: scriptLabel(script.path, req.cwd, req.homeDir),
|
|
323
|
+
body: script.content,
|
|
324
|
+
truncated: script.truncated ?? false,
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
for (const inner of script.shellCommands.slice(0, MAX_FORMS)) {
|
|
328
|
+
const innerReq = {
|
|
329
|
+
...req,
|
|
330
|
+
target: { type: 'command', command: inner.split(/\s+/)[0] ?? '', argv: [], cwd: req.cwd },
|
|
331
|
+
};
|
|
332
|
+
const innerAnalysis = analyzeCommandAction(rules, innerReq, inner, {
|
|
333
|
+
...opts,
|
|
334
|
+
_scriptHop: hop + 1,
|
|
335
|
+
});
|
|
336
|
+
decision = strongest(decision, innerAnalysis.decision);
|
|
337
|
+
if (innerAnalysis.routeHint === 'catch')
|
|
338
|
+
scriptEscalation = 'catch';
|
|
339
|
+
forms.push(`script:${inner}`);
|
|
340
|
+
// A file the script runs is judged too. Inline code on a line of a
|
|
341
|
+
// shell file is already in that file's text; a package script's
|
|
342
|
+
// body is not judged as a file, so its inline code is.
|
|
343
|
+
for (const s of innerAnalysis.scripts) {
|
|
344
|
+
if (s.origin === 'file' || script.kind === 'npm-script')
|
|
345
|
+
addScript(scripts, s);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
// An interpreter body (python/node) is not parsed as shell; a script the
|
|
349
|
+
// agent wrote and now executes is worth the judge even if its body reads clean.
|
|
350
|
+
if (script.kind === 'interpreter' || writtenHere)
|
|
351
|
+
scriptEscalation = 'catch';
|
|
352
|
+
if (writtenHere && decision.verdict === 'allow') {
|
|
353
|
+
// record the signal for the route; do not hard-block on "written here" alone.
|
|
354
|
+
scriptEscalation = 'catch';
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
catch {
|
|
359
|
+
/* never throw */
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
let routeHint = decideRouteHint(decision, triage, normalize);
|
|
363
|
+
if (routeHint === 'none' && scriptEscalation === 'catch')
|
|
364
|
+
routeHint = 'catch';
|
|
365
|
+
return { decision, normalize, triage, localBlockReason, routeHint, evaluatedForms: forms, scripts };
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* A curated, LOW-false-positive local-deny supplement for dangerous families
|
|
369
|
+
* the built-in regex corpus does not yet cover after de-obfuscation. Each
|
|
370
|
+
* pattern is unambiguous enough to block locally (no cloud judge); anything
|
|
371
|
+
* fuzzier (inline-interpreter destructive calls, etc.) is left to the judge via
|
|
372
|
+
* the `catch` route instead, to keep false positives at zero.
|
|
373
|
+
*
|
|
374
|
+
* Returns a stable reason slug, or null when nothing fires.
|
|
375
|
+
*/
|
|
376
|
+
const SECRET_PATH_RE = /(^|[\/@])(\.env(\.[\w.-]+)?|\.npmrc|\.netrc|id_rsa|id_ed25519|id_ecdsa|\.pem|\.p12|\.pfx|credentials|\.aws\/|\.ssh\/|\.kube\/config|\.docker\/config)(?![\w.-]*\.example)/i;
|
|
377
|
+
const METADATA_HOST_RE = /\b(169\.254\.169\.254|169\.254\.170\.2|metadata\.google\.internal|100\.100\.100\.200)\b/;
|
|
378
|
+
/**
|
|
379
|
+
* The project rule each local block belongs to (by `builtinKey`). The block
|
|
380
|
+
* takes that rule's effective action; with no such rule, or the rule `off`,
|
|
381
|
+
* there is no local block.
|
|
382
|
+
*/
|
|
383
|
+
const LOCAL_BLOCK_RULES = {
|
|
384
|
+
'reverse-shell-devtcp': 'shell.net.netcat',
|
|
385
|
+
'reverse-shell-socat': 'shell.net.netcat',
|
|
386
|
+
'privilege-escalation': 'shell.priv.sudo',
|
|
387
|
+
'find-destructive-root-home': 'fs.delete.root_or_home',
|
|
388
|
+
'chmod-777-recursive-broad': 'shell.priv.chmod_777',
|
|
389
|
+
'secret-exfiltration-http': 'fs.read.secrets_via_shell',
|
|
390
|
+
'cloud-metadata-fetch': 'net.http.cloud_metadata',
|
|
391
|
+
'git-force-push': 'git.push.force_other',
|
|
392
|
+
'git-delete-ref': 'git.history.rewrite',
|
|
393
|
+
// triage.ts `dangerous` reasons
|
|
394
|
+
'rm-rf-root-home': 'fs.delete.root_or_home',
|
|
395
|
+
'chmod-777-broad': 'shell.priv.chmod_777',
|
|
396
|
+
'encoded-pipe-to-shell': 'shell.exec.dynamic_eval',
|
|
397
|
+
};
|
|
398
|
+
function localBlockDecision(rules, reason) {
|
|
399
|
+
const key = LOCAL_BLOCK_RULES[reason];
|
|
400
|
+
const rule = key ? rules.find((r) => (r.builtinKey ?? r.id) === key) : undefined;
|
|
401
|
+
if (!rule || (rule.action !== 'deny' && rule.action !== 'warn'))
|
|
402
|
+
return null;
|
|
403
|
+
return {
|
|
404
|
+
verdict: rule.action,
|
|
405
|
+
matchedRuleIds: [rule.id],
|
|
406
|
+
message: `${rule.action === 'deny' ? 'Blocked' : 'Flagged'} (${rule.name ?? rule.id}): this command ` +
|
|
407
|
+
`matches a dangerous pattern (${reason}) even after removing obfuscation. ` +
|
|
408
|
+
`Confirm intent before re-running.`,
|
|
409
|
+
maxSeverity: rule.severity,
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
/** Names whose presence next to a `/dev/tcp/…` target makes a reverse shell. */
|
|
413
|
+
const REVERSE_SHELL_EXES = new Set(['bash', 'sh', 'zsh', 'ksh', 'dash', 'nc', 'ncat', 'exec', 'eval']);
|
|
414
|
+
const PRIVILEGE_WRAPPERS = new Set(['doas', 'pkexec']);
|
|
415
|
+
const UPLOAD_FLAGS = new Set(['-d', '--data', '--data-binary', '-T', '--upload-file']);
|
|
416
|
+
/**
|
|
417
|
+
* Segments of the raw line, split on command separators only: a redirect
|
|
418
|
+
* target (`>& /dev/tcp/…`) stays in its command's segment, and a quoted
|
|
419
|
+
* argument stays ONE token, so a message or a pattern is never read as a command.
|
|
420
|
+
*/
|
|
421
|
+
function segmentsWithRedirects(raw) {
|
|
422
|
+
const segments = [];
|
|
423
|
+
for (const line of raw.split('\n')) {
|
|
424
|
+
let tokens;
|
|
425
|
+
try {
|
|
426
|
+
tokens = shellParse(line, (k) => '$' + k);
|
|
427
|
+
}
|
|
428
|
+
catch {
|
|
429
|
+
continue;
|
|
430
|
+
}
|
|
431
|
+
let current = [];
|
|
432
|
+
for (const tok of tokens) {
|
|
433
|
+
if (typeof tok === 'string') {
|
|
434
|
+
current.push(tok);
|
|
435
|
+
}
|
|
436
|
+
else if ('op' in tok && SEGMENT_OPS.has(tok.op)) {
|
|
437
|
+
if (current.length)
|
|
438
|
+
segments.push(current);
|
|
439
|
+
current = [];
|
|
440
|
+
}
|
|
441
|
+
else if ('pattern' in tok) {
|
|
442
|
+
current.push(tok.pattern);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
if (current.length)
|
|
446
|
+
segments.push(current);
|
|
447
|
+
}
|
|
448
|
+
return segments;
|
|
449
|
+
}
|
|
450
|
+
/** The command runs under `doas` / `pkexec` (leading assignments and wrappers skipped). */
|
|
451
|
+
function runsUnder(tokens, wrappers) {
|
|
452
|
+
for (const t of tokens) {
|
|
453
|
+
if (/^[A-Za-z_][A-Za-z0-9_]*=/.test(t) || t.startsWith('-'))
|
|
454
|
+
continue;
|
|
455
|
+
const exe = canonicalExecutable(t);
|
|
456
|
+
if (wrappers.has(exe))
|
|
457
|
+
return true;
|
|
458
|
+
if (!TRANSPARENT_PREFIXES.has(exe))
|
|
459
|
+
return false;
|
|
460
|
+
}
|
|
461
|
+
return false;
|
|
462
|
+
}
|
|
463
|
+
/** The git subcommand and what follows it (`-C <dir>` / `-c <k=v>` skipped). */
|
|
464
|
+
function gitSubcommand(args) {
|
|
465
|
+
for (let i = 0; i < args.length; i++) {
|
|
466
|
+
const t = args[i];
|
|
467
|
+
if (t === '-C' || t === '-c') {
|
|
468
|
+
i++;
|
|
469
|
+
continue;
|
|
470
|
+
}
|
|
471
|
+
if (t.startsWith('-'))
|
|
472
|
+
continue;
|
|
473
|
+
return { sub: t, rest: args.slice(i + 1) };
|
|
474
|
+
}
|
|
475
|
+
return null;
|
|
476
|
+
}
|
|
477
|
+
/** `-f`, a short cluster holding `f`, `--force` or a `+refspec`; never `--force-with-lease`. */
|
|
478
|
+
function isForcePushToken(t) {
|
|
479
|
+
return /^-[A-Za-z]*f[A-Za-z]*$/.test(t) || t === '--force' || /^\+\S/.test(t);
|
|
480
|
+
}
|
|
481
|
+
/** The operands curl/wget uploads (`-d @f`, `--data=@f`, `-d@f`, `-T f`). */
|
|
482
|
+
function uploadOperands(args) {
|
|
483
|
+
const out = [];
|
|
484
|
+
for (let i = 0; i < args.length; i++) {
|
|
485
|
+
const t = args[i];
|
|
486
|
+
if (UPLOAD_FLAGS.has(t)) {
|
|
487
|
+
if (i + 1 < args.length)
|
|
488
|
+
out.push(args[i + 1]);
|
|
489
|
+
continue;
|
|
490
|
+
}
|
|
491
|
+
const m = /^(?:--data|--data-binary|--upload-file)=(.+)$/.exec(t) ?? /^-[dT](.+)$/.exec(t);
|
|
492
|
+
if (m)
|
|
493
|
+
out.push(m[1]);
|
|
494
|
+
}
|
|
495
|
+
return out;
|
|
496
|
+
}
|
|
497
|
+
/** One effective command, read by its executable, flags and operands. */
|
|
498
|
+
function commandDanger(cmd) {
|
|
499
|
+
const tokens = cmd.raw.split(/\s+/).filter(Boolean);
|
|
500
|
+
if (runsUnder(tokens, PRIVILEGE_WRAPPERS))
|
|
501
|
+
return 'privilege-escalation';
|
|
502
|
+
const at = tokens.findIndex((t) => canonicalExecutable(t) === cmd.executable);
|
|
503
|
+
const after = at >= 0 ? tokens.slice(at + 1) : [];
|
|
504
|
+
switch (cmd.executable) {
|
|
505
|
+
case 'find': {
|
|
506
|
+
const roots = [];
|
|
507
|
+
for (const t of after) {
|
|
508
|
+
if (t === '-H' || t === '-L' || t === '-P')
|
|
509
|
+
continue;
|
|
510
|
+
if (t.startsWith('-') || t === '(' || t === '!')
|
|
511
|
+
break;
|
|
512
|
+
roots.push(t);
|
|
513
|
+
}
|
|
514
|
+
const exec = after.findIndex((t) => ['-exec', '-execdir', '-ok', '-okdir'].includes(t));
|
|
515
|
+
const removes = after.includes('-delete') ||
|
|
516
|
+
(exec >= 0 && after.slice(exec + 1).some((t) => /^(rm|unlink|shred)$/.test(canonicalExecutable(t))));
|
|
517
|
+
return removes && roots.some(isCatastrophicPathArg) ? 'find-destructive-root-home' : null;
|
|
518
|
+
}
|
|
519
|
+
case 'chmod': {
|
|
520
|
+
const recursive = cmd.flagLetters.has('R') || cmd.longFlags.includes('recursive');
|
|
521
|
+
const mode777 = cmd.args.some((a) => /^0*777$/.test(a) || /^a[+=]rwx$/.test(a));
|
|
522
|
+
const broad = cmd.args.some((a) => /^[/~]/.test(a));
|
|
523
|
+
return recursive && mode777 && broad ? 'chmod-777-recursive-broad' : null;
|
|
524
|
+
}
|
|
525
|
+
case 'curl':
|
|
526
|
+
case 'wget':
|
|
527
|
+
if (uploadOperands(after).some((o) => SECRET_PATH_RE.test(o)))
|
|
528
|
+
return 'secret-exfiltration-http';
|
|
529
|
+
return cmd.args.some((a) => METADATA_HOST_RE.test(a)) ? 'cloud-metadata-fetch' : null;
|
|
530
|
+
case 'git': {
|
|
531
|
+
const git = gitSubcommand(after);
|
|
532
|
+
if (git?.sub === 'push' && git.rest.some(isForcePushToken))
|
|
533
|
+
return 'git-force-push';
|
|
534
|
+
if (git?.sub === 'update-ref' && git.rest.includes('-d'))
|
|
535
|
+
return 'git-delete-ref';
|
|
536
|
+
return null;
|
|
537
|
+
}
|
|
538
|
+
default:
|
|
539
|
+
return null;
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
export function supplementDangerous(normalize, rawCommand) {
|
|
543
|
+
// Reverse shells live in redirect targets and socat addresses, which do not
|
|
544
|
+
// survive into a parsed command: read them on the raw line's segments.
|
|
545
|
+
for (const seg of segmentsWithRedirects(rawCommand)) {
|
|
546
|
+
const names = seg.map(canonicalExecutable);
|
|
547
|
+
if (seg.some((t) => /\/dev\/(tcp|udp)\//.test(t)) && names.some((n) => REVERSE_SHELL_EXES.has(n))) {
|
|
548
|
+
return 'reverse-shell-devtcp';
|
|
549
|
+
}
|
|
550
|
+
if (names.includes('socat') && seg.some((t) => /\b(EXEC|SYSTEM):/i.test(t)))
|
|
551
|
+
return 'reverse-shell-socat';
|
|
552
|
+
}
|
|
553
|
+
// Everything else, on each effective command the normalizer recovered
|
|
554
|
+
// (nested `bash -c`, `eval`, `$( … )`, heredocs included).
|
|
555
|
+
for (const cmd of normalize?.commands ?? []) {
|
|
556
|
+
const reason = commandDanger(cmd);
|
|
557
|
+
if (reason)
|
|
558
|
+
return reason;
|
|
559
|
+
}
|
|
560
|
+
return null;
|
|
561
|
+
}
|
|
562
|
+
/** Advisory judge route (the hook turns this into a real call via judge-triage). */
|
|
563
|
+
function decideRouteHint(decision, triage, normalize) {
|
|
564
|
+
if (decision.verdict === 'deny')
|
|
565
|
+
return 'confirm';
|
|
566
|
+
if (triage && triage.class !== 'safe')
|
|
567
|
+
return 'catch';
|
|
568
|
+
if (normalize?.incomplete)
|
|
569
|
+
return 'catch';
|
|
570
|
+
return 'none';
|
|
571
|
+
}
|
|
572
|
+
//# sourceMappingURL=command-analysis.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-analysis.js","sourceRoot":"","sources":["../../src/guards-evaluator/command-analysis.ts"],"names":[],"mappings":"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"}
|