@agent-beam/beam 0.2.40 → 0.2.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/access-risk.d.ts +1 -1
- package/dist/access-risk.js +7 -2
- package/dist/access-risk.js.map +1 -1
- package/dist/action-context.d.ts +5 -0
- package/dist/action-context.js +5 -2
- package/dist/action-context.js.map +1 -1
- package/dist/core.d.ts +5 -0
- package/dist/core.js +55 -5
- package/dist/core.js.map +1 -1
- package/dist/credential-egress.d.ts +7 -0
- package/dist/credential-egress.js +52 -6
- package/dist/credential-egress.js.map +1 -1
- package/dist/destructive-risk.d.ts +5 -1
- package/dist/destructive-risk.js +63 -5
- package/dist/destructive-risk.js.map +1 -1
- package/dist/flow.d.ts +63 -0
- package/dist/flow.js +196 -0
- package/dist/flow.js.map +1 -0
- package/dist/plain-explain.d.ts +38 -0
- package/dist/plain-explain.js +197 -0
- package/dist/plain-explain.js.map +1 -0
- package/dist/repo-remote.d.ts +39 -0
- package/dist/repo-remote.js +191 -0
- package/dist/repo-remote.js.map +1 -0
- package/dist/rule-catalog.js +237 -15
- package/dist/rule-catalog.js.map +1 -1
- package/dist/secret-use.d.ts +23 -0
- package/dist/secret-use.js +142 -0
- package/dist/secret-use.js.map +1 -0
- package/dist/skill-context.js +5 -2
- package/dist/skill-context.js.map +1 -1
- package/dist/skill-risk-rules.js +3 -1
- package/dist/skill-risk-rules.js.map +1 -1
- package/dist/skill-scan.d.ts +4 -0
- package/dist/skill-scan.js +31 -8
- package/dist/skill-scan.js.map +1 -1
- package/package.json +1 -1
- package/stress-report.json +45 -45
package/dist/destructive-risk.js
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
import { shellActionCommands } from "./credential-egress.js";
|
|
2
2
|
// Deliberately lexical: an explicit, narrow test/scratch path can lower the
|
|
3
3
|
// severity, but does not establish ownership or inspect symlinks on the host.
|
|
4
|
-
export function isScopedTemporaryCleanup(text, depth = 0) {
|
|
4
|
+
export function isScopedTemporaryCleanup(text, depth = 0, accept = isTemporaryTestPath) {
|
|
5
5
|
if (depth > 4)
|
|
6
6
|
return false;
|
|
7
|
+
// `S=/literal/path; rm -rf $S/x` -- resolve plain literal assignments made earlier in the text.
|
|
8
|
+
const vars = new Map();
|
|
9
|
+
for (const m of text.matchAll(/(?:^|[;&\n]\s*)(?:export\s+)?([A-Za-z_]\w*)=([^\s;&|$`"'()*?{}\[\]]+)(?=\s*(?:[;&\n]|$))/g))
|
|
10
|
+
vars.set(m[1], m[2]);
|
|
7
11
|
const commands = shellActionCommands(text);
|
|
8
12
|
if (commands.length === 1) {
|
|
9
13
|
const tokens = commands[0].tokens;
|
|
10
14
|
if (tokens.length === 3 && /(?:^|\/)(?:bash|sh|zsh)$/.test(tokens[0].value) && /^-[a-z]*c[a-z]*$/.test(tokens[1].value) && /^['"]/.test(tokens[2].raw))
|
|
11
|
-
return isScopedTemporaryCleanup(tokens[2].value, depth + 1);
|
|
15
|
+
return isScopedTemporaryCleanup(tokens[2].value, depth + 1, accept);
|
|
12
16
|
}
|
|
13
17
|
let found = false;
|
|
14
18
|
for (const segment of text.split(/[;&|\n]/)) {
|
|
@@ -18,7 +22,8 @@ export function isScopedTemporaryCleanup(text, depth = 0) {
|
|
|
18
22
|
const command = /^(?:\/(?:usr\/)?bin\/)?rm\s+(.+)$/.exec(segment.trim());
|
|
19
23
|
if (!command)
|
|
20
24
|
return false;
|
|
21
|
-
|
|
25
|
+
// Redirections to /dev/null (`2>/dev/null`, `2>&1`) are not paths; any other redirect is kept and blocks the scoped reading.
|
|
26
|
+
const raw = command[1].replace(/\s+\d*>&\d+/g, "").replace(/\s+(?:\d*>>?|&>)\s*\/dev\/null\b/g, "").replace(/\$\{?([A-Za-z_]\w*)\}?/g, (m, n) => vars.get(n) ?? m);
|
|
22
27
|
if (/[$`*?{}()[\]<>\\]/.test(raw))
|
|
23
28
|
return false;
|
|
24
29
|
const tokens = raw.match(/"[^"]*"|'[^']*'|\S+/g) ?? [];
|
|
@@ -45,7 +50,7 @@ export function isScopedTemporaryCleanup(text, depth = 0) {
|
|
|
45
50
|
else
|
|
46
51
|
paths.push(value);
|
|
47
52
|
}
|
|
48
|
-
if (!paths.length || !paths.every(
|
|
53
|
+
if (!paths.length || !paths.every(accept))
|
|
49
54
|
return false;
|
|
50
55
|
// Ordinary rm in a mixed cleanup must be scoped too, but this rule's trigger
|
|
51
56
|
// is still recursive + force. Never create a finding for a plain file delete.
|
|
@@ -63,8 +68,61 @@ function isTemporaryTestPath(path) {
|
|
|
63
68
|
if (!/^[A-Za-z0-9._-]+$/.test(match[1]))
|
|
64
69
|
return false;
|
|
65
70
|
// A name is a confidence signal, not permission: keep an alert at MEDIUM.
|
|
66
|
-
if (!/(?:^|[-_.])(?:test|tests|tmp|temp|scratch|verify)(?:$|[-_.])/i.test(match[1]))
|
|
71
|
+
if (!/(?:^|[-_.])(?:test|tests|tmp|temp|scratch|verify|download|downloads|cache|build|output|artifacts|probe|preview|draft|demo)(?:$|[-_.])/i.test(match[1]))
|
|
67
72
|
return false;
|
|
68
73
|
return !/(?:^|[/._-])(?:credentials?|secrets?|backups?|production|prod|\.env)(?:$|[/._-])/i.test(path);
|
|
69
74
|
}
|
|
75
|
+
// The agent harness's own per-session scratch folder, and caches a build recreates on demand.
|
|
76
|
+
// Deleting these loses nothing that wasn't generated, so they are LOW rather than a destructive alert.
|
|
77
|
+
const AGENT_SCRATCH = /^\/(?:private\/)?tmp\/claude-\d+\/[A-Za-z0-9._-]+\/[A-Za-z0-9._-]+\/scratchpad(?:\/[A-Za-z0-9._/-]*)?\/?$/;
|
|
78
|
+
const REGENERABLE = /^(?:\.\/)?(?:[A-Za-z0-9._-]+\/)*(?:\.next(?:\/[A-Za-z0-9._/-]*)?|__pycache__|node_modules(?:\/[A-Za-z0-9._@/-]*)?|\.turbo|\.cache|\.pytest_cache|\.mypy_cache|\.parcel-cache|\.vite|\.nyc_output|dist|build|coverage|\.svelte-kit|\.nuxt|\.output)\/?$/;
|
|
79
|
+
// Per-user caches (uv, npm, pip, Library/Caches) are rebuilt on demand.
|
|
80
|
+
const USER_CACHE = /^~\/(?:\.cache|Library\/Caches)\/[A-Za-z0-9._@/-]+\/?$/;
|
|
81
|
+
function isLowRiskPath(path) {
|
|
82
|
+
if (path.split("/").some(p => p === "..") || /\/\//.test(path))
|
|
83
|
+
return false;
|
|
84
|
+
return AGENT_SCRATCH.test(path) || USER_CACHE.test(path) || (!path.startsWith("/") && !path.startsWith("~") && REGENERABLE.test(path));
|
|
85
|
+
}
|
|
86
|
+
export function isLowRiskCleanup(text) {
|
|
87
|
+
return isScopedTemporaryCleanup(text, 0, isLowRiskPath);
|
|
88
|
+
}
|
|
89
|
+
// Paths this same command creates (mkdir, cat > f, tee, cp/mv destination, touch): deleting what
|
|
90
|
+
// you just made is cleaning up after yourself, not destroying existing work.
|
|
91
|
+
const norm = (p) => p.replace(/^["']|["']$/g, "").replace(/^\.\//, "").replace(/\/+$/, "");
|
|
92
|
+
function createdPaths(text) {
|
|
93
|
+
const made = [];
|
|
94
|
+
for (const segment of text.split(/[;&|\n]/)) {
|
|
95
|
+
const w = segment.trim().split(/\s+/);
|
|
96
|
+
const head = w[0];
|
|
97
|
+
const args = w.slice(1).filter(a => !a.startsWith("-"));
|
|
98
|
+
if (head === "mkdir" || head === "touch")
|
|
99
|
+
made.push(...args.map(norm));
|
|
100
|
+
else if ((head === "cp" || head === "mv") && args.length >= 2)
|
|
101
|
+
made.push(norm(args[args.length - 1]));
|
|
102
|
+
const redirect = /(?:^|\s)(?:tee\s+(?:-a\s+)?|>>?\s*)["']?([^\s"'<>|;&]+)/.exec(segment);
|
|
103
|
+
if (redirect)
|
|
104
|
+
made.push(norm(redirect[1]));
|
|
105
|
+
}
|
|
106
|
+
return made.filter(Boolean);
|
|
107
|
+
}
|
|
108
|
+
const madeHere = (path, made) => { const p = norm(path); return made.some(m => p === m || m.startsWith(p + "/") || p.startsWith(m + "/")); };
|
|
109
|
+
// MEDIUM: contained to the project -- a relative path two or more levels deep, or anything this
|
|
110
|
+
// same command created. Top-level names (rm -rf src), absolute paths, ~ and .. stay HIGH.
|
|
111
|
+
const SENSITIVE = /(?:^|[/._-])(?:credentials?|secrets?|backups?|production|prod|\.env|\.ssh|\.aws)(?:$|[/._-])/i;
|
|
112
|
+
function isProjectScopedPath(path) {
|
|
113
|
+
if (path.split("/").some(p => p === ".." || p === ".") || /\/\//.test(path) || SENSITIVE.test(path))
|
|
114
|
+
return false;
|
|
115
|
+
if (path.startsWith("/") || path.startsWith("~") || /[$`*?{}()[\]<>\\]/.test(path))
|
|
116
|
+
return false;
|
|
117
|
+
return norm(path).split("/").filter(Boolean).length >= 2;
|
|
118
|
+
}
|
|
119
|
+
export function isProjectScopedCleanup(text) {
|
|
120
|
+
const made = createdPaths(text);
|
|
121
|
+
return isScopedTemporaryCleanup(text, 0, p => isProjectScopedPath(p) || (!SENSITIVE.test(p) && !p.startsWith("/") && !p.startsWith("~") && !p.includes("..") && madeHere(p, made)));
|
|
122
|
+
}
|
|
123
|
+
/** `find DIR -type l -delete` removes only symlinks. */
|
|
124
|
+
export function isSymlinkOnlyDelete(text) {
|
|
125
|
+
const deletes = text.split(/[;&|\n]/).filter(seg => /-delete\b/.test(seg));
|
|
126
|
+
return deletes.length > 0 && deletes.every(seg => /\bfind\b[^\n]*-type\s+l\b[^\n]*-delete\b/.test(seg)) && !/\brm\b/.test(text);
|
|
127
|
+
}
|
|
70
128
|
//# sourceMappingURL=destructive-risk.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"destructive-risk.js","sourceRoot":"","sources":["../src/destructive-risk.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,4EAA4E;AAC5E,8EAA8E;AAC9E,MAAM,UAAU,wBAAwB,CAAC,IAAY,EAAE,KAAK,GAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"destructive-risk.js","sourceRoot":"","sources":["../src/destructive-risk.ts"],"names":[],"mappings":"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"}
|
package/dist/flow.d.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { ActionContext } from "./action-context.js";
|
|
2
|
+
/**
|
|
3
|
+
* One small, redacted record per event that lets the dashboard draw the chain of steps in a session:
|
|
4
|
+
* what each step did in plain words, what it touched, whether it sent anything outward, and what
|
|
5
|
+
* came of it. Built deterministically from the event (no model, no network). Strings are short,
|
|
6
|
+
* paths are trimmed to their last two segments, and no file or command output is ever included --
|
|
7
|
+
* only counts of secret-looking values found in the output.
|
|
8
|
+
*
|
|
9
|
+
* Every field is optional beyond `v`/`label`/`kind`, and older CLI versions send none of it: the
|
|
10
|
+
* dashboard falls back to the event's own summary for those, so nothing depends on this existing.
|
|
11
|
+
*/
|
|
12
|
+
export type FlowKind = "prompt" | "read" | "write" | "search" | "run" | "web" | "mcp" | "delete" | "git" | "other";
|
|
13
|
+
export type FlowOutward = {
|
|
14
|
+
kind: "push" | "upload" | "post" | "publish" | "deploy";
|
|
15
|
+
target?: string;
|
|
16
|
+
};
|
|
17
|
+
export type FlowInfo = {
|
|
18
|
+
v: 1;
|
|
19
|
+
label: string;
|
|
20
|
+
kind: FlowKind;
|
|
21
|
+
effects?: {
|
|
22
|
+
read?: string[];
|
|
23
|
+
wrote?: string[];
|
|
24
|
+
deleted?: string[];
|
|
25
|
+
hosts?: string[];
|
|
26
|
+
ran?: string[];
|
|
27
|
+
staged?: string[];
|
|
28
|
+
};
|
|
29
|
+
/** A private file's contents were opened by this step. */
|
|
30
|
+
sensitive?: true;
|
|
31
|
+
outward?: FlowOutward;
|
|
32
|
+
/** Only with `outward`: does the same command reference a secret (a private file, a credential variable)? */
|
|
33
|
+
carriesSensitive?: "yes" | "no-sign";
|
|
34
|
+
outcome?: "ok" | "failed" | "denied" | "asked";
|
|
35
|
+
/** From the tool's output, post-run only: how many secret-looking values appeared (never the values). */
|
|
36
|
+
exposure?: {
|
|
37
|
+
secrets: number;
|
|
38
|
+
kinds?: string[];
|
|
39
|
+
};
|
|
40
|
+
toolUseId?: string;
|
|
41
|
+
turn?: number;
|
|
42
|
+
};
|
|
43
|
+
export type FlowInput = {
|
|
44
|
+
type: string;
|
|
45
|
+
tool: string;
|
|
46
|
+
command: string;
|
|
47
|
+
path: string;
|
|
48
|
+
url: string;
|
|
49
|
+
phase?: string;
|
|
50
|
+
policyAction?: string;
|
|
51
|
+
promptTopic?: string;
|
|
52
|
+
toolResponse?: unknown;
|
|
53
|
+
toolUseId?: string;
|
|
54
|
+
turn?: number;
|
|
55
|
+
mcp?: {
|
|
56
|
+
server: string;
|
|
57
|
+
tool?: string;
|
|
58
|
+
};
|
|
59
|
+
context?: ActionContext;
|
|
60
|
+
safe: (s: string) => string;
|
|
61
|
+
};
|
|
62
|
+
/** Builds the flow record for one event. Never throws. */
|
|
63
|
+
export declare function buildFlow(i: FlowInput): FlowInfo | undefined;
|
package/dist/flow.js
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { basename } from "node:path";
|
|
2
|
+
import { shellActionCommands } from "./credential-egress.js";
|
|
3
|
+
import { narrateCommand, friendlyName, shortPath } from "./plain-explain.js";
|
|
4
|
+
import { PRIVATE_PATH, isTemplateEnvPath, touchesSecretContent, patchTargetText } from "./secret-use.js";
|
|
5
|
+
import { detectSensitive } from "./data-detectors.js";
|
|
6
|
+
const clip = (s, n) => (s.length > n ? s.slice(0, n - 1) + "…" : s);
|
|
7
|
+
const list = (items, max = 6) => [...new Set(items.filter((x) => !!x))].slice(0, max).map(x => clip(x, 70));
|
|
8
|
+
const hostOf = (url) => {
|
|
9
|
+
if (!url)
|
|
10
|
+
return undefined;
|
|
11
|
+
try {
|
|
12
|
+
return new URL(/^[a-z]+:\/\//i.test(url) ? url : `https://${url}`).hostname.toLowerCase() || undefined;
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
const MCP_WRITE = /(?:create|update|delete|write|send|post|put|patch|execute|run|publish|deploy|remove|save|insert|add|grant|revoke|assign)/i;
|
|
19
|
+
const SECRET_KINDS = new Set(["SECRET", "API_KEY", "PASSWORD", "PRIVATE_KEY"]);
|
|
20
|
+
const CREDENTIAL_VAR = /\$\{?[A-Za-z][A-Za-z0-9]*(?:_[A-Za-z0-9]+)*_(?:KEY|SECRET|TOKEN|PASSWORD|CREDENTIAL)S?\}?/;
|
|
21
|
+
function commandsOf(command) {
|
|
22
|
+
const out = [];
|
|
23
|
+
for (const c of shellActionCommands(command)) {
|
|
24
|
+
const t = c.tokens;
|
|
25
|
+
let at = 0;
|
|
26
|
+
while (/^[A-Za-z_]\w*=/.test(t[at]?.value ?? ""))
|
|
27
|
+
at++;
|
|
28
|
+
if (t[at]?.value === "sudo")
|
|
29
|
+
at++;
|
|
30
|
+
const cmd = basename(t[at]?.value ?? "").toLowerCase();
|
|
31
|
+
if (cmd)
|
|
32
|
+
out.push({ cmd, args: t.slice(at + 1).map(x => x.value) });
|
|
33
|
+
}
|
|
34
|
+
return out;
|
|
35
|
+
}
|
|
36
|
+
const isPrivate = (p) => PRIVATE_PATH.test(p) && !isTemplateEnvPath(p);
|
|
37
|
+
/** What this command sends outward, if anything (a push, an upload, a POST, a publish, a deploy). */
|
|
38
|
+
function outwardOf(cmds, ctx, safe) {
|
|
39
|
+
for (const { cmd, args } of cmds) {
|
|
40
|
+
const sub = args.find(a => !a.startsWith("-"));
|
|
41
|
+
if (cmd === "git" && sub === "push")
|
|
42
|
+
return { kind: "push", target: ctx?.repository?.remote?.path ?? ctx?.repository?.name };
|
|
43
|
+
if (/^(?:docker|podman)$/.test(cmd) && sub === "push") {
|
|
44
|
+
const ref = args.filter(a => !a.startsWith("-"))[1];
|
|
45
|
+
return { kind: "push", target: ref ? clip(safe(ref.split(":")[0]), 70) : undefined };
|
|
46
|
+
}
|
|
47
|
+
if (/^(?:npm|pnpm|yarn|bun)$/.test(cmd) && sub === "publish")
|
|
48
|
+
return { kind: "publish", target: "package registry" };
|
|
49
|
+
if (/^(?:twine|cargo|gem)$/.test(cmd) && /^(?:upload|publish|push)$/.test(sub ?? ""))
|
|
50
|
+
return { kind: "publish", target: cmd };
|
|
51
|
+
if (/^(?:vercel|netlify|railway|fly|flyctl|heroku|wrangler|firebase)$/.test(cmd) && (/^(?:deploy|up|publish|push|release)$/.test(sub ?? "") || args.includes("--prod")))
|
|
52
|
+
return { kind: "deploy", target: cmd };
|
|
53
|
+
if (cmd === "gh" && /^(?:pr|gist|issue|release|repo)$/.test(sub ?? "") && /^(?:create|comment|edit|upload|merge)$/.test(args.filter(a => !a.startsWith("-"))[1] ?? ""))
|
|
54
|
+
return { kind: "post", target: ctx?.repository?.remote?.path ?? "GitHub" };
|
|
55
|
+
if (cmd === "aws" && sub === "s3") {
|
|
56
|
+
const dest = args.find(a => /^s3:\/\//.test(a));
|
|
57
|
+
if (dest && /^(?:cp|sync|mv)$/.test(args.filter(a => !a.startsWith("-"))[1] ?? ""))
|
|
58
|
+
return { kind: "upload", target: clip(safe(dest), 70) };
|
|
59
|
+
}
|
|
60
|
+
if (/^(?:scp|rsync|sftp)$/.test(cmd)) {
|
|
61
|
+
const remote = args.find(a => /^[^/\s-][^/\s]*@?[^/\s]*:/.test(a) && !a.startsWith("-"));
|
|
62
|
+
if (remote)
|
|
63
|
+
return { kind: "upload", target: clip(safe(remote.split(":")[0].replace(/^.*@/, "")), 70) };
|
|
64
|
+
}
|
|
65
|
+
if (/^(?:curl|wget)$/.test(cmd)) {
|
|
66
|
+
const url = args.find(a => /^https?:\/\//i.test(a.replace(/^["']|["']$/g, "")))?.replace(/^["']|["']$/g, "");
|
|
67
|
+
const sends = args.some(a => /^(?:-d|--data(?:-binary|-raw|-urlencode)?|-F|--form|-T|--upload-file|--post-data|--post-file)$/.test(a) || /^-d.+/.test(a))
|
|
68
|
+
|| args.some((a, i) => /^(?:-X|--request)$/.test(a) && /^(?:POST|PUT|PATCH)$/i.test(args[i + 1] ?? ""));
|
|
69
|
+
if (sends)
|
|
70
|
+
return { kind: args.some(a => /^(?:-T|--upload-file|-F|--form)$/.test(a)) ? "upload" : "post", target: hostOf(url) };
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
function referencesSecret(cmds, command) {
|
|
76
|
+
if (cmds.some(({ args }) => args.some(a => isPrivate(a.replace(/^@/, "")) || /@[^\s]*\.env\b/.test(a))))
|
|
77
|
+
return true;
|
|
78
|
+
if (CREDENTIAL_VAR.test(command))
|
|
79
|
+
return true;
|
|
80
|
+
// `git add .env && git push`: anything private staged earlier in the same command.
|
|
81
|
+
return cmds.some(({ cmd, args }) => cmd === "git" && args[0] === "add" && args.slice(1).some(a => isPrivate(a)));
|
|
82
|
+
}
|
|
83
|
+
function exposureOf(toolResponse) {
|
|
84
|
+
if (toolResponse === undefined || toolResponse === null)
|
|
85
|
+
return undefined;
|
|
86
|
+
let text;
|
|
87
|
+
try {
|
|
88
|
+
text = typeof toolResponse === "string" ? toolResponse : JSON.stringify(toolResponse);
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
if (!text)
|
|
94
|
+
return undefined;
|
|
95
|
+
const found = detectSensitive(text.slice(0, 200_000)).filter(f => SECRET_KINDS.has(f.kind));
|
|
96
|
+
const kinds = [...new Set(found.map(f => f.kind))].slice(0, 4);
|
|
97
|
+
return { secrets: Math.min(found.length, 999), ...(kinds.length ? { kinds } : {}) };
|
|
98
|
+
}
|
|
99
|
+
/** Builds the flow record for one event. Never throws. */
|
|
100
|
+
export function buildFlow(i) {
|
|
101
|
+
try {
|
|
102
|
+
const safe = i.safe;
|
|
103
|
+
let label = "", kind = "other";
|
|
104
|
+
let effects = {};
|
|
105
|
+
let sensitive, outward, carries;
|
|
106
|
+
if (i.type === "prompt.submit") {
|
|
107
|
+
kind = "prompt";
|
|
108
|
+
label = i.promptTopic ? `You: “${clip(safe(i.promptTopic), 60)}”` : "You sent a message";
|
|
109
|
+
}
|
|
110
|
+
else if (/^session\.start/.test(i.type))
|
|
111
|
+
label = "Session started";
|
|
112
|
+
else if (/^session\.end/.test(i.type))
|
|
113
|
+
label = "Session ended";
|
|
114
|
+
else if (/^message/.test(i.type))
|
|
115
|
+
label = "The agent replied";
|
|
116
|
+
else if (i.type === "command.exec" && i.command) {
|
|
117
|
+
const cmds = commandsOf(i.command);
|
|
118
|
+
const narrated = narrateCommand(i.command, safe);
|
|
119
|
+
const steps = narrated.steps;
|
|
120
|
+
label = steps.length ? (steps.length === 1 ? steps[0] : `${steps[0]}, +${steps.length - 1} more`) : "ran a command";
|
|
121
|
+
const actions = i.context?.actions ?? [];
|
|
122
|
+
effects = {
|
|
123
|
+
read: list(actions.filter(a => (a.operation === "file-read" || a.operation === "file-search" || a.operation === "source-search") && a.target && a.target !== "standard input").map(a => shortPath(a.target, safe))),
|
|
124
|
+
wrote: list(actions.filter(a => a.operation === "file-write").map(a => a.target && shortPath(a.target, safe))),
|
|
125
|
+
deleted: list(actions.filter(a => a.operation === "delete").map(a => a.target && shortPath(a.target, safe))),
|
|
126
|
+
hosts: list(actions.filter(a => a.operation === "network-request").map(a => hostOf(a.target))),
|
|
127
|
+
ran: list(cmds.map(c => c.cmd).filter(c => !/^(?:cd|echo|printf|true|false|export|set|sleep|cut|wc|sort|uniq|tr|head|tail|xargs|tee)$/.test(c)), 5),
|
|
128
|
+
staged: list(cmds.filter(c => c.cmd === "git" && c.args[0] === "add").flatMap(c => c.args.slice(1).filter(a => !a.startsWith("-")).map(a => (a === "." ? "everything" : shortPath(a, safe))))),
|
|
129
|
+
};
|
|
130
|
+
kind = actions.some(a => a.operation === "delete") ? "delete"
|
|
131
|
+
: cmds.some(c => c.cmd === "git") ? "git"
|
|
132
|
+
: actions.some(a => a.operation === "file-write") ? "write"
|
|
133
|
+
: actions.some(a => a.operation === "network-request") ? "web"
|
|
134
|
+
: actions.some(a => a.operation === "file-search" || a.operation === "source-search") ? "search"
|
|
135
|
+
: actions.some(a => a.operation === "file-read") ? "read"
|
|
136
|
+
: "run";
|
|
137
|
+
outward = outwardOf(cmds, i.context, safe);
|
|
138
|
+
if (outward)
|
|
139
|
+
carries = referencesSecret(cmds, i.command) ? "yes" : "no-sign";
|
|
140
|
+
const privateTouched = actions.some(a => isPrivate(a.resolvedPath ?? a.target ?? "")) || cmds.some(c => c.args.some(a => isPrivate(a)));
|
|
141
|
+
if (privateTouched && i.context && touchesSecretContent(i.command, i.context))
|
|
142
|
+
sensitive = true;
|
|
143
|
+
}
|
|
144
|
+
else if (i.type === "file.read") {
|
|
145
|
+
kind = "read";
|
|
146
|
+
label = i.path ? `read ${friendlyName(i.path, safe)}` : "read a file";
|
|
147
|
+
effects = { read: i.path ? list([shortPath(i.path, safe)]) : [] };
|
|
148
|
+
if (i.path && isPrivate(i.path))
|
|
149
|
+
sensitive = true;
|
|
150
|
+
}
|
|
151
|
+
else if (i.type === "file.write") {
|
|
152
|
+
kind = "write";
|
|
153
|
+
const patch = patchTargetText(i.command);
|
|
154
|
+
const files = patch !== undefined ? patch.split("\n").filter(Boolean) : i.path ? [i.path] : [];
|
|
155
|
+
label = files.length > 1 ? `edited ${files.length} files, starting with ${friendlyName(files[0], safe)}` : `edited ${files[0] ? friendlyName(files[0], safe) : "a file"}`;
|
|
156
|
+
effects = { wrote: list(files.map(f => shortPath(f, safe))) };
|
|
157
|
+
}
|
|
158
|
+
else if (/^(?:browser\.navigate|web\.search)$/.test(i.type) || /^(?:WebFetch|WebSearch)$/i.test(i.tool)) {
|
|
159
|
+
kind = "web";
|
|
160
|
+
const host = hostOf(i.url);
|
|
161
|
+
label = host ? `looked at ${safe(host)}` : "searched the web";
|
|
162
|
+
if (host)
|
|
163
|
+
effects = { hosts: [host] };
|
|
164
|
+
}
|
|
165
|
+
else if (i.mcp) {
|
|
166
|
+
kind = "mcp";
|
|
167
|
+
label = `used ${safe(i.mcp.server)}${i.mcp.tool ? `: ${safe(i.mcp.tool)}` : ""}`;
|
|
168
|
+
if (MCP_WRITE.test(i.mcp.tool ?? "")) {
|
|
169
|
+
outward = { kind: "post", target: clip(safe(i.mcp.server), 70) };
|
|
170
|
+
carries = "no-sign";
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
else if (i.tool)
|
|
174
|
+
label = `used ${safe(i.tool)}`;
|
|
175
|
+
else
|
|
176
|
+
return undefined;
|
|
177
|
+
const outcome = i.policyAction === "deny" ? "denied" : i.policyAction === "ask" ? "asked"
|
|
178
|
+
: i.phase === "failed hook" ? "failed" : i.phase === "completed hook" ? "ok" : undefined;
|
|
179
|
+
const exposure = exposureOf(i.toolResponse);
|
|
180
|
+
const compact = Object.fromEntries(Object.entries(effects).filter(([, v]) => v && v.length));
|
|
181
|
+
return {
|
|
182
|
+
v: 1, label: clip(label, 90), kind,
|
|
183
|
+
...(compact && Object.keys(compact).length ? { effects: compact } : {}),
|
|
184
|
+
...(sensitive ? { sensitive } : {}),
|
|
185
|
+
...(outward ? { outward, ...(carries ? { carriesSensitive: carries } : {}) } : {}),
|
|
186
|
+
...(outcome ? { outcome } : {}),
|
|
187
|
+
...(exposure ? { exposure } : {}),
|
|
188
|
+
...(i.toolUseId ? { toolUseId: clip(i.toolUseId, 80) } : {}),
|
|
189
|
+
...(i.turn ? { turn: i.turn } : {}),
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
return undefined;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=flow.js.map
|
package/dist/flow.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flow.js","sourceRoot":"","sources":["../src/flow.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ActionContext } from "./action-context.js";
|
|
2
|
+
/**
|
|
3
|
+
* Event-specific plain-language facts, built without any model: what the agent actually did, step
|
|
4
|
+
* by step, and -- for secret-looking files -- whether anything opened their contents. The dashboard
|
|
5
|
+
* combines this with its own per-rule wording ("why it matters", "what to do") to show a non-technical
|
|
6
|
+
* reader a 4-8 line explanation. Only short, redacted strings are produced; nothing here is a
|
|
7
|
+
* detection verdict, it just narrates the command the detector already looked at.
|
|
8
|
+
*/
|
|
9
|
+
export type PlainExplanation = {
|
|
10
|
+
v: 1;
|
|
11
|
+
/** Ordered, everyday-language steps (at most 6, each at most 140 chars). */
|
|
12
|
+
steps: string[];
|
|
13
|
+
/** For private files: were their contents opened, or only their names listed/mentioned? */
|
|
14
|
+
opened?: "contents" | "names-only" | "none";
|
|
15
|
+
/** Friendly names of sensitive things involved (at most 4). */
|
|
16
|
+
touched?: string[];
|
|
17
|
+
/** A hint for triage, not a verdict: routine, worth a check, or risky. */
|
|
18
|
+
verdict: "routine" | "check" | "risky";
|
|
19
|
+
/** One sentence tying this event to the rule: what the detector saw vs. what really happened. */
|
|
20
|
+
nuance?: string;
|
|
21
|
+
};
|
|
22
|
+
/** Last two path segments, no quotes -- the form used inside data fields. */
|
|
23
|
+
export declare function shortPath(path: string, safe: (s: string) => string): string;
|
|
24
|
+
/** Quoted friendly name for reading in a sentence. */
|
|
25
|
+
export declare const friendlyName: (path: string, safe: (s: string) => string) => string;
|
|
26
|
+
/** Steps for a shell command, in order, with plumbing left out and repeats merged. */
|
|
27
|
+
export declare function narrateCommand(command: string, safe: (s: string) => string): {
|
|
28
|
+
steps: string[];
|
|
29
|
+
admin: boolean;
|
|
30
|
+
};
|
|
31
|
+
/** Builds the event-specific explanation. Returns undefined when there is nothing useful to narrate. */
|
|
32
|
+
export declare function explainFinding(input: {
|
|
33
|
+
ruleId: string;
|
|
34
|
+
severity: string;
|
|
35
|
+
command: string;
|
|
36
|
+
context?: ActionContext;
|
|
37
|
+
safe: (s: string) => string;
|
|
38
|
+
}): PlainExplanation | undefined;
|