@agent-beam/beam 0.2.28 → 0.2.29
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 +69 -13
- package/Skills/agentbeam-app-monitoring/SKILL.md +15 -3
- package/dist/cli.js +43 -4
- package/dist/cli.js.map +1 -1
- package/dist/client.js +103 -81
- package/dist/client.js.map +1 -1
- package/dist/monitor-config.d.ts +39 -0
- package/dist/monitor-config.js +134 -0
- package/dist/monitor-config.js.map +1 -0
- package/dist/monitor-llm.d.ts +50 -7
- package/dist/monitor-llm.js +227 -31
- package/dist/monitor-llm.js.map +1 -1
- package/dist/monitor-pipeline.d.ts +65 -2
- package/dist/monitor-pipeline.js +145 -21
- package/dist/monitor-pipeline.js.map +1 -1
- package/dist/monitor-rules.d.ts +8 -4
- package/dist/monitor-rules.js +106 -12
- package/dist/monitor-rules.js.map +1 -1
- package/dist/monitor.d.ts +30 -3
- package/dist/monitor.js +198 -30
- package/dist/monitor.js.map +1 -1
- package/dist/prompt-attacks.d.ts +29 -0
- package/dist/prompt-attacks.js +237 -0
- package/dist/prompt-attacks.js.map +1 -0
- package/dist/rule-catalog.js +36 -6
- package/dist/rule-catalog.js.map +1 -1
- package/dist/sdk.d.ts +54 -1
- package/dist/sdk.js +198 -58
- package/dist/sdk.js.map +1 -1
- package/package.json +4 -2
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
// Attacks on LLM-powered apps (OWASP Top 10 for LLM Applications): direct and indirect prompt
|
|
2
|
+
// injection, instructions smuggled in invisible Unicode or base64, forged chat-template tokens,
|
|
3
|
+
// jailbreak personas, system prompt extraction, attempts to talk an AI reviewer out of an alert,
|
|
4
|
+
// and data exfiltration through model output.
|
|
5
|
+
//
|
|
6
|
+
// Used three ways: as `beam monitor` rules over logs and traffic, by the SDK's prompt() and
|
|
7
|
+
// output() checks, and to keep the optional LLM check from being argued out of an alert by the
|
|
8
|
+
// line it is judging (looksLikeInjection). Pure TypeScript with no Node.js built-ins, so it runs
|
|
9
|
+
// in edge runtimes. Heuristic like the rest of Beam: a new phrasing can get past it.
|
|
10
|
+
const TAG_CHAR = /[\u{E0000}-\u{E007F}]/u;
|
|
11
|
+
const TAG_RUN = /(\u{1F3F4})?([\u{E0000}-\u{E007F}]+)/gu;
|
|
12
|
+
// Zero-width characters and soft hyphens split words ("ignore") so phrase rules miss them.
|
|
13
|
+
const ZERO_WIDTH = /[-]/g;
|
|
14
|
+
const NON_ASCII = /[^\x00-\x7F]/;
|
|
15
|
+
/**
|
|
16
|
+
* Text hidden in Unicode tag characters ("ASCII smuggling"): invisible on screen, read by models.
|
|
17
|
+
* A subdivision flag (🏴 + a few tags, like England's) is an emoji, not hidden text.
|
|
18
|
+
*/
|
|
19
|
+
export function hiddenTagText(text) {
|
|
20
|
+
if (!TAG_CHAR.test(text))
|
|
21
|
+
return "";
|
|
22
|
+
let out = "";
|
|
23
|
+
for (const [, flag, run] of text.matchAll(TAG_RUN)) {
|
|
24
|
+
const chars = [...run];
|
|
25
|
+
if (flag && chars.length <= 8 && chars.at(-1) === "\u{E007F}")
|
|
26
|
+
continue;
|
|
27
|
+
for (const ch of chars) {
|
|
28
|
+
const c = ch.codePointAt(0) - 0xe0000;
|
|
29
|
+
if (c >= 0x20 && c < 0x7f)
|
|
30
|
+
out += String.fromCharCode(c);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return out;
|
|
34
|
+
}
|
|
35
|
+
/** For evidence a person reads: hidden tag text becomes visible as ⟦hidden: …⟧. */
|
|
36
|
+
export function revealHidden(text) {
|
|
37
|
+
if (!TAG_CHAR.test(text))
|
|
38
|
+
return text;
|
|
39
|
+
return text.replace(TAG_RUN, (whole, flag) => {
|
|
40
|
+
const hidden = hiddenTagText(whole);
|
|
41
|
+
return hidden ? `${flag ?? ""}⟦hidden: ${hidden}⟧` : whole;
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
const atobSafe = (s) => {
|
|
45
|
+
try {
|
|
46
|
+
return atob(s.slice(0, s.length - (s.length % 4)));
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return "";
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
const isBase64Char = (c) => (c >= 65 && c <= 90) || (c >= 97 && c <= 122) || (c >= 48 && c <= 57) || c === 43 || c === 47;
|
|
53
|
+
/**
|
|
54
|
+
* Base64 runs that decode to readable sentences (a common way to slip instructions past filters).
|
|
55
|
+
* One linear pass: a regex like /[A-Za-z0-9+/]{24,}/ rescans every short run from each start.
|
|
56
|
+
*/
|
|
57
|
+
function decodedBase64(text) {
|
|
58
|
+
const out = [];
|
|
59
|
+
let start = -1;
|
|
60
|
+
for (let i = 0; i <= text.length && out.length < 4; i++) {
|
|
61
|
+
if (i < text.length && isBase64Char(text.charCodeAt(i))) {
|
|
62
|
+
if (start < 0)
|
|
63
|
+
start = i;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
if (start >= 0 && i - start >= 24) {
|
|
67
|
+
const run = text.slice(start, Math.min(i, start + 4096));
|
|
68
|
+
// Encoded prose mixes cases; hex digests and ids don't, and aren't worth decoding.
|
|
69
|
+
if (/[a-z]/.test(run) && /[A-Z]/.test(run)) {
|
|
70
|
+
const decoded = atobSafe(run);
|
|
71
|
+
let printable = 0, spaces = 0;
|
|
72
|
+
for (let j = 0; j < decoded.length; j++) {
|
|
73
|
+
const c = decoded.charCodeAt(j);
|
|
74
|
+
if ((c >= 0x20 && c < 0x7f) || c === 9 || c === 10)
|
|
75
|
+
printable++;
|
|
76
|
+
if (c === 0x20)
|
|
77
|
+
spaces++;
|
|
78
|
+
}
|
|
79
|
+
if (decoded.length >= 16 && printable >= decoded.length * 0.9 && spaces >= 3)
|
|
80
|
+
out.push(decoded.replace(/[^\x20-\x7E\t\n]/g, ""));
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
start = -1;
|
|
84
|
+
}
|
|
85
|
+
return out.join("\n");
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* What the phrase rules read: full-width and styled letters folded to ASCII, zero-width characters
|
|
89
|
+
* removed, plus any tag-hidden text and readable base64, appended.
|
|
90
|
+
*/
|
|
91
|
+
export function injectionView(text) {
|
|
92
|
+
let s = text.length > 16_384 ? text.slice(0, 16_384) : text;
|
|
93
|
+
const hidden = hiddenTagText(s);
|
|
94
|
+
if (NON_ASCII.test(s))
|
|
95
|
+
s = s.normalize("NFKC").replace(ZERO_WIDTH, "");
|
|
96
|
+
const decoded = decodedBase64(s);
|
|
97
|
+
return hidden || decoded ? [s, hidden, decoded].filter(Boolean).join("\n") : s;
|
|
98
|
+
}
|
|
99
|
+
// The same decoded line is handed to every rule in turn; build its view once.
|
|
100
|
+
let lastText = "";
|
|
101
|
+
let lastView = "";
|
|
102
|
+
function view(text) {
|
|
103
|
+
if (text !== lastText) {
|
|
104
|
+
lastText = text;
|
|
105
|
+
lastView = injectionView(text);
|
|
106
|
+
}
|
|
107
|
+
return lastView;
|
|
108
|
+
}
|
|
109
|
+
const re = (parts, flags = "i") => new RegExp(parts.join("|"), flags);
|
|
110
|
+
const OVERRIDE = re([
|
|
111
|
+
// "ignore all previous instructions", "disregard the rules above", "bypass your system prompt"
|
|
112
|
+
String.raw `\b(?:ignore|disregard|forget|override|bypass)\s+(?:all\s+|any\s+|every\s+)?(?:of\s+)?(?:the\s+|your\s+|these\s+|those\s+)?(?:previous|prior|above|earlier|preceding|original|initial|system|safety|existing|developer)\s+(?:system\s+)?(?:instructions?|prompts?|rules|directions|directives|guidelines|guardrails|constraints|messages|context)\b`,
|
|
113
|
+
String.raw `\bforget\s+(?:everything|all)\s+(?:above|before|you\s+(?:were|have\s+been)\s+told)\b`,
|
|
114
|
+
String.raw `\b(?:new|updated|revised|real|actual)\s+(?:system\s+)?instructions?\s*:`,
|
|
115
|
+
String.raw `\bsystem\s+(?:prompt|message)\s+(?:override|update)\b|\bend\s+of\s+(?:the\s+)?(?:system\s+prompt|instructions|user\s+input)\b`,
|
|
116
|
+
String.raw `\bfrom\s+now\s+on,?\s+you\s+(?:will|must|are\s+to|shall)\s+(?:ignore|answer|respond|reply|act|obey|only)\b`,
|
|
117
|
+
String.raw `\byou\s+are\s+now\s+(?:in\s+)?(?:DAN|developer\s+mode|jailbroken|an?\s+unrestricted|free\s+(?:from|of))\b`,
|
|
118
|
+
String.raw `\b(?:do\s+not|don'?t|never)\s+(?:tell|inform|notify|alert|warn)\s+(?:the\s+)?(?:user|admin|administrator|operator|security\s+team)\b`,
|
|
119
|
+
String.raw `\bdisable\s+(?:the\s+|your\s+|all\s+)?(?:security|safety|logging|audit(?:ing)?|content\s+filter(?:s|ing)?|guardrails|moderation)\b`,
|
|
120
|
+
]);
|
|
121
|
+
// Aimed at whoever, or whatever, reviews the line, including Beam's own LLM check.
|
|
122
|
+
const REVIEWER = re([
|
|
123
|
+
String.raw `\b(?:note|message|instructions?|attention)\s+(?:to|for)\s+(?:the\s+|any\s+|all\s+)?(?:ai|llm|language\s+model|model|assistant|chatbot|gpt|claude|security\s+(?:analyst|reviewer|scanner|tool|team)|reviewer|classifier|moderator|monitor)s?\b`,
|
|
124
|
+
String.raw `\b(?:classify|mark|label|treat|report|rate|consider)\s+(?:this|these|it|the\s+(?:following|above))\s+(?:(?:line|lines|request|requests|input|message|traffic|entry|log|finding)\s+)?as\s+(?:benign|safe|harmless|legitimate|a\s+false\s+positive|not\s+(?:malicious|an?\s+attack))\b`,
|
|
125
|
+
String.raw `\b(?:this|the\s+following)\s+(?:is|request\s+is|line\s+is|traffic\s+is)\s+(?:an?\s+)?(?:authori[sz]ed|approved|sanctioned)\s+(?:security\s+)?(?:test|pentest|penetration\s+test|scan|audit)\b`,
|
|
126
|
+
String.raw `["']?verdict["']?\s*[:=]\s*["']?benign\b`,
|
|
127
|
+
]);
|
|
128
|
+
const CHAT_TEMPLATE = re([
|
|
129
|
+
String.raw `<\|(?:im_start|im_end|im_sep|system|user|assistant|endoftext|begin_of_text|start_header_id|end_header_id|eot_id|eom_id|start|end|message|channel|return|call)\|>`,
|
|
130
|
+
String.raw `\[\/?INST\]|<<\/?SYS>>|<\/?(?:start|end)_of_turn>`,
|
|
131
|
+
String.raw `<\s*\/?\s*(?:system|important|instructions?|system[-_]reminder|admin[-_]override)\s*>`,
|
|
132
|
+
String.raw `\b(?:BEGIN|END)\s+(?:SYSTEM\s+PROMPT|SYSTEM\s+INSTRUCTIONS)\b`,
|
|
133
|
+
]);
|
|
134
|
+
const JAILBREAK = re([
|
|
135
|
+
String.raw `\bdo\s+anything\s+now\b`,
|
|
136
|
+
String.raw `\b(?:developer|god|jailbreak|unrestricted|unfiltered|evil|opposite)\s+mode\s+(?:enabled|activated|on|output)\b|\benable\s+(?:developer|jailbreak|god|unrestricted)\s+mode\b`,
|
|
137
|
+
String.raw `\b(?:respond|answer|reply|act|operate|talk|behave)\s+(?:freely\s+)?without\s+(?:any\s+)?(?:restrictions|limitations|filters|guidelines|censorship|content\s+polic(?:y|ies)|ethical\s+(?:guidelines|constraints))\b`,
|
|
138
|
+
String.raw `\b(?:pretend|act\s+as\s+if|imagine)\s+(?:that\s+)?you\s+(?:are|have)\s+(?:an?\s+)?(?:ai\s+)?(?:with\s+no\s+(?:restrictions|filters|rules|limits)|without\s+(?:restrictions|filters|rules|limits)|unrestricted|jailbroken|evil)\b`,
|
|
139
|
+
String.raw `\b(?:amoral|unethical)\s+(?:and\s+)?(?:unfiltered|uncensored)\b|\buncensored\s+and\s+unfiltered\b`,
|
|
140
|
+
]);
|
|
141
|
+
const EXTRACTION = re([
|
|
142
|
+
String.raw `\b(?:repeat|print|reveal|output|display|dump|leak|recite|write\s+out|show|tell\s+me|give\s+me)\s+(?:me\s+)?(?:back\s+)?(?:your|the)\s+(?:(?:entire|full|complete|exact|original|initial|hidden|secret)\s+)*(?:system\s+(?:prompt|message|instructions)|initial\s+(?:prompt|instructions)|(?:original|hidden|secret|developer|internal)\s+(?:instructions|prompt|message)|instructions\s+(?:above|you\s+were\s+given)|prompt\s+above|(?:words|text|everything)\s+above)\b`,
|
|
143
|
+
String.raw `\bwhat\s+(?:is|are|was|were)\s+your\s+(?:system\s+prompt|initial\s+instructions|original\s+instructions)\b`,
|
|
144
|
+
String.raw `\b(?:repeat|output|print)\s+(?:everything|all\s+(?:the\s+)?(?:text|words))\s+(?:above|before\s+this)\b|\bstarting\s+with\s+["'“]you\s+are\b`,
|
|
145
|
+
String.raw `\brepeat\s+(?:the\s+)?(?:word|phrase|token)\s+\S+\s+forever\b`,
|
|
146
|
+
String.raw `\b(?:show|give|tell|list)\s+me\s+(?:what\s+)?other\s+users?(?:'s?)?\s+(?:asked|said|wrote|conversations?|chats?|messages|prompts)\b`,
|
|
147
|
+
]);
|
|
148
|
+
// Asking the model, or an agent with tools, for the app's keys, tokens or environment. "Your"
|
|
149
|
+
// addresses the app itself; a user asking where to find their own API key doesn't match.
|
|
150
|
+
const VERB = String.raw `(?:reveal|print|show|give|tell|output|display|dump|leak|list|send|share|repeat|return|read|expose|paste|email|post|write\s+out)`;
|
|
151
|
+
const PROVIDER = String.raw `(?:(?:openai|anthropic|claude|gemini|google|aws|azure|gcp|stripe|github|supabase|firebase|database|db|admin|service|secret|private|internal|server|backend|production|prod)\s+)*`;
|
|
152
|
+
const SECRET_REQUEST = re([
|
|
153
|
+
String.raw `\b${VERB}\s+(?:me\s+|us\s+)?(?:all\s+(?:of\s+)?)?your\s+${PROVIDER}(?:api[\s_-]?keys?|secret[\s_-]?keys?|access[\s_-]?(?:keys?|tokens?)|auth(?:entication)?\s+tokens?|bearer\s+tokens?|tokens|keys|credentials|passwords?|connection\s+strings?|private\s+keys?|secrets|env(?:ironment)?\s+(?:variables|vars)|\.env(?:\s+file)?)\b`,
|
|
154
|
+
String.raw `\b${VERB}\s+(?:me\s+|us\s+)?(?:all\s+(?:of\s+)?)?(?:the\s+)?(?:(?:server|system|app|application|backend|container|process|host|machine)(?:'s)?\s+)?(?:env(?:ironment)?\s+(?:variables|vars)|\.env\s+file|env\s+file|process\.env|os\.environ)\b`,
|
|
155
|
+
String.raw `\bwhat\s+(?:is|are)\s+your\s+${PROVIDER}(?:api[\s_-]?keys?|secret[\s_-]?keys?|access\s+tokens?|credentials|passwords?|env(?:ironment)?\s+variables)\b`,
|
|
156
|
+
]);
|
|
157
|
+
// The same, by variable name: "print OPENAI_API_KEY", "what's $STRIPE_SECRET_KEY". Case-sensitive
|
|
158
|
+
// on the name, so ordinary words don't match.
|
|
159
|
+
const SECRET_BY_NAME = /(?:[Pp]rint|[Ee]cho|[Rr]eveal|[Ss]how|[Oo]utput|[Tt]ell\s+me|[Gg]ive\s+me|[Ww]hat(?:'s|\s+is)|[Vv]alue\s+of|[Cc]ontents\s+of|[Dd]ump|[Ll]eak|[Ss]end)\b[^\n]{0,40}?\$?\{?\b[A-Z][A-Z0-9_]*_(?:API_KEY|SECRET|SECRET_KEY|ACCESS_KEY|ACCESS_KEY_ID|AUTH_TOKEN|PRIVATE_KEY|TOKEN|PASSWORD|DATABASE_URL)\b/;
|
|
160
|
+
// Commands that print secrets, sent where an agent with a shell or file tool might run them.
|
|
161
|
+
const SECRET_COMMAND = /\b(?:cat|type|less|more|head|tail|strings|base64)\s+(?:\S*\/)?\.env(?:\.[\w-]+)?\b|\bprintenv\b|\benv\s*\|\s*(?:grep|sort|base64|curl|nc|tee)\b|\becho\s+["']?\$\{?[A-Z_]*(?:KEY|SECRET|TOKEN|PASSWORD)|\bGet-ChildItem\s+env:|\/proc\/self\/environ\b/;
|
|
162
|
+
// Environment-style assignments in model output: KEY_NAME=value.
|
|
163
|
+
const ENV_SECRET = /\b[A-Z][A-Z0-9_]*(?:API_KEY|SECRET(?:_KEY)?|ACCESS_KEY|AUTH_TOKEN|PASSWORD|PRIVATE_KEY)\s*[=:]\s*["']?[A-Za-z0-9/+_\-.]{12,}/;
|
|
164
|
+
// A markdown image (or HTML img) whose URL carries a long value: rendering it sends that value to
|
|
165
|
+
// the URL's server without a click (the EchoLeak family of zero-click exfiltration). Found with
|
|
166
|
+
// bounded indexOf scans, because model output is attacker-influenced and a regex here backtracked
|
|
167
|
+
// quadratically on long runs of "![" or "?".
|
|
168
|
+
const MAX_TAGS = 200;
|
|
169
|
+
function carriesData(url) {
|
|
170
|
+
if (!/^https?:\/\//i.test(url))
|
|
171
|
+
return false;
|
|
172
|
+
const q = url.search(/[?#]/);
|
|
173
|
+
if (q < 0)
|
|
174
|
+
return false;
|
|
175
|
+
return url.slice(q + 1).split(/[&;?#]/).some(part => { const eq = part.indexOf("="); return eq >= 0 && part.length - eq - 1 >= 16; });
|
|
176
|
+
}
|
|
177
|
+
/** The URL starting at `from`, up to the first character in `stop` (at most 4 KB). */
|
|
178
|
+
function urlAt(s, from, stop) {
|
|
179
|
+
const rest = s.slice(from, from + 4096);
|
|
180
|
+
const end = rest.search(stop);
|
|
181
|
+
return end < 0 ? rest : rest.slice(0, end);
|
|
182
|
+
}
|
|
183
|
+
function markdownExfil(s) {
|
|
184
|
+
let tags = 0;
|
|
185
|
+
for (let i = s.indexOf("!["); i >= 0 && tags++ < MAX_TAGS; i = s.indexOf("![", i + 2)) {
|
|
186
|
+
const alt = s.slice(i + 2, i + 203);
|
|
187
|
+
const close = alt.indexOf("]");
|
|
188
|
+
if (close < 0 || alt.slice(0, close).includes("\n") || alt[close + 1] !== "(")
|
|
189
|
+
continue;
|
|
190
|
+
let from = i + 2 + close + 2;
|
|
191
|
+
while (s[from] === " " || s[from] === "\t")
|
|
192
|
+
from++;
|
|
193
|
+
if (s[from] === "<")
|
|
194
|
+
from++;
|
|
195
|
+
if (carriesData(urlAt(s, from, /[)\s>]/)))
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
function imgExfil(s) {
|
|
201
|
+
const tag = /<img\b/gi;
|
|
202
|
+
let tags = 0;
|
|
203
|
+
for (let m = tag.exec(s); m && tags++ < MAX_TAGS; m = tag.exec(s)) {
|
|
204
|
+
const src = /\bsrc\s*=\s*["']?/i.exec(s.slice(m.index, m.index + 220));
|
|
205
|
+
if (src && carriesData(urlAt(s, m.index + src.index + src[0].length, /["'\s>]/)))
|
|
206
|
+
return true;
|
|
207
|
+
}
|
|
208
|
+
return false;
|
|
209
|
+
}
|
|
210
|
+
/** Instructions aimed at a model: override phrases, forged chat markers, hidden text, or appeals to a reviewer. */
|
|
211
|
+
export function looksLikeInjection(text) {
|
|
212
|
+
const v = view(text);
|
|
213
|
+
return OVERRIDE.test(v) || REVIEWER.test(v) || CHAT_TEMPLATE.test(v) || hiddenTagText(text).length >= 4;
|
|
214
|
+
}
|
|
215
|
+
export const promptAttack = {
|
|
216
|
+
override: (s) => OVERRIDE.test(view(s)),
|
|
217
|
+
reviewer: (s) => REVIEWER.test(view(s)),
|
|
218
|
+
chatTemplate: (s) => CHAT_TEMPLATE.test(view(s)),
|
|
219
|
+
hidden: (s) => hiddenTagText(s).length >= 4,
|
|
220
|
+
jailbreak: (s) => JAILBREAK.test(view(s)),
|
|
221
|
+
extraction: (s) => EXTRACTION.test(view(s)),
|
|
222
|
+
secretRequest: (s) => SECRET_REQUEST.test(view(s)),
|
|
223
|
+
// Not for app logs: "value of OPENAI_API_KEY is empty" is an ordinary config error there.
|
|
224
|
+
secretCommand: (s) => { const v = view(s); return SECRET_COMMAND.test(v) || SECRET_BY_NAME.test(v); },
|
|
225
|
+
envSecret: (s) => ENV_SECRET.test(s),
|
|
226
|
+
markdownExfil: (s) => markdownExfil(s),
|
|
227
|
+
htmlExfil: (s) => markdownExfil(s) || imgExfil(s),
|
|
228
|
+
};
|
|
229
|
+
/** A canary planted in a system prompt, found in text: compared without case, spacing or punctuation, so light reformatting doesn't hide it. */
|
|
230
|
+
export function containsCanary(text, canaries) {
|
|
231
|
+
if (!canaries.length)
|
|
232
|
+
return false;
|
|
233
|
+
const squash = (s) => s.normalize("NFKC").toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
234
|
+
const haystack = squash(text);
|
|
235
|
+
return canaries.some(c => { const needle = squash(c); return needle.length >= 8 && haystack.includes(needle); });
|
|
236
|
+
}
|
|
237
|
+
//# sourceMappingURL=prompt-attacks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt-attacks.js","sourceRoot":"","sources":["../src/prompt-attacks.ts"],"names":[],"mappings":"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"}
|
package/dist/rule-catalog.js
CHANGED
|
@@ -1,23 +1,53 @@
|
|
|
1
1
|
const secret = /(?:\.env(?:\b|[./])|\.ssh[\\/]|id_rsa|id_ed25519|\.aws[\\/]credentials|(?:api[_-]?key|access[_-]?token|password|secret)\b)/i;
|
|
2
2
|
const egress = /(?:https?:\/\/|\bcurl\b|\bwget\b|\bupload\b|\bwebhook\b|\bsend\b|\bexfiltrat\w*)/i;
|
|
3
|
+
// Linear checks for "something | sh". As regexes (/curl[^\n]*\|\s*sh/) they backtrack
|
|
4
|
+
// quadratically or worse on long hostile lines, and these rules also run on attacker-written
|
|
5
|
+
// text inside customer apps (App monitoring). Each line's pipes are split once and scanned in order.
|
|
6
|
+
const SHELL_AFTER_PIPE = /^\s*(?:sudo\s+)?(?:ba|z|fi)?sh\b/i;
|
|
7
|
+
function pipesIntoShell(s, newArmer) {
|
|
8
|
+
for (const line of s.split("\n")) {
|
|
9
|
+
if (!line.includes("|"))
|
|
10
|
+
continue;
|
|
11
|
+
const arms = newArmer();
|
|
12
|
+
let armed = false;
|
|
13
|
+
for (const [i, segment] of line.split("|").entries()) {
|
|
14
|
+
if (i > 0 && armed && SHELL_AFTER_PIPE.test(segment))
|
|
15
|
+
return true;
|
|
16
|
+
armed = arms(segment) || armed;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
const downloads = () => (segment) => /\b(?:curl|wget)\b/i.test(segment);
|
|
22
|
+
// base64, then a decode flag after it (in the same segment or a later one).
|
|
23
|
+
const decodes = () => {
|
|
24
|
+
let base64 = false;
|
|
25
|
+
return (segment) => {
|
|
26
|
+
const at = base64 ? 0 : segment.search(/\bbase64\b/i);
|
|
27
|
+
if (at < 0)
|
|
28
|
+
return false;
|
|
29
|
+
base64 = true;
|
|
30
|
+
return /(?:^|\s)(?:-\w*d\w*|--decode)\b/i.test(segment.slice(at));
|
|
31
|
+
};
|
|
32
|
+
};
|
|
3
33
|
export const builtinRules = [
|
|
4
|
-
{ id: "destructive.delete", title: "Destructive operation", severity: "high", category: "impact", explanation: "Review the target and backups before allowing a recursive delete or destructive data operation.", match: s => /\brm\s+[^\n]
|
|
34
|
+
{ id: "destructive.delete", title: "Destructive operation", severity: "high", category: "impact", explanation: "Review the target and backups before allowing a recursive delete or destructive data operation.", match: s => /\brm\s+[^\n]{0,1000}?(?:-[a-z]*r[a-z]*f|-[a-z]*f[a-z]*r|--recursive)|\b(?:drop\s+(?:table|database)|truncate\s+(?:table\s+)?\w+)|\bRemove-Item\b[^\n]{0,1000}?(?:-Recurse|-Force)|\bgit\s+(?:reset\s+--hard|clean\s+-[^\n]{0,1000}?f)/i.test(s) },
|
|
5
35
|
{ id: "destructive.production", title: "Production change", severity: "high", category: "impact", explanation: "This action targets a production environment. Confirm the scope and rollback plan before proceeding.", match: s => /\b(?:production|prod)\b/i.test(s) && /\b(?:deploy|delete|drop|truncate|migrate|apply|destroy|restart|rollback|scale)\b/i.test(s) },
|
|
6
36
|
{ id: "credentials.environment", title: "Environment variable access", severity: "high", category: "secrets", explanation: "The action reads exported environment variables that may contain credentials or private configuration.", match: s => /\b(?:printenv|env|export\s+-p|process\.env|os\.environ|System\.getenv)\b|\$\{?[A-Z][A-Z0-9_]*\}?/i.test(s) },
|
|
7
37
|
{ id: "credentials.access", title: "Sensitive credential reference", severity: "medium", category: "secrets", explanation: "This action or instruction references a credential location. Confirm the agent needs access.", match: s => secret.test(s) },
|
|
8
38
|
{ id: "source.private_files", title: "Private source or configuration access", severity: "high", category: "secrets", explanation: "This action accesses a private credential or configuration file. Confirm that the agent needs the contents.", match: s => /(?:\.env(?:\.[\w.-]+)?|\.ssh[\\/]|\.aws[\\/]credentials|id_(?:rsa|ed25519)|\.npmrc|\.netrc|kubeconfig|private.?key)/i.test(s) },
|
|
9
39
|
{ id: "mcp.write", title: "MCP write operation", severity: "high", category: "impact", explanation: "The MCP tool appears to modify data or send an external side effect. Require approval before allowing it.", match: s => /\bmcp(?:__|:)[^\s]*(?:create|update|delete|write|send|post|put|patch|execute|run|publish|deploy|remove)\b/i.test(s) },
|
|
10
40
|
{ id: "credentials.egress", title: "Possible credential exposure", severity: "critical", category: "exfil", explanation: "Credential references and outbound delivery appear together. Inspect the destination and data before running this.", match: s => secret.test(s) && egress.test(s) },
|
|
11
|
-
{ id: "execution.remote", title: "Remote code execution pattern", severity: "high", category: "exec", explanation: "Downloaded content is piped directly into a shell without review.", match: s =>
|
|
12
|
-
{ id: "execution.obfuscated", title: "Encoded execution", severity: "high", category: "exec", explanation: "Encoded content is decoded for execution. Review the decoded payload separately; Beam never executes it.", match: s =>
|
|
41
|
+
{ id: "execution.remote", title: "Remote code execution pattern", severity: "high", category: "exec", explanation: "Downloaded content is piped directly into a shell without review.", match: s => pipesIntoShell(s, downloads) },
|
|
42
|
+
{ id: "execution.obfuscated", title: "Encoded execution", severity: "high", category: "exec", explanation: "Encoded content is decoded for execution. Review the decoded payload separately; Beam never executes it.", match: s => pipesIntoShell(s, decodes) || /\b(?:powershell|pwsh)\b[^\n]{0,500}?\s-(?:enc|encodedcommand)\b/i.test(s) },
|
|
13
43
|
{ id: "recon.network_sweep", title: "Network sweep", severity: "medium", category: "recon", explanation: "A scanner targets a network range. Verify scope and authorization before the agent probes other systems (ATT&CK T1046).", match: s => /\b(?:nmap|masscan|rustscan)\b/i.test(s) && /(?:\d{1,3}\.){3}\d{1,3}\/\d{1,2}|(?:\d{1,3}\.){3}\d{1,3}-\d{1,3}/.test(s) },
|
|
14
44
|
{ id: "privilege.elevation", title: "Elevated privileges", severity: "medium", category: "privilege", explanation: "The action requests elevated privileges or broad write permissions.", match: s => /\bsudo\s|\bchmod\s+(?:-R\s+)?777\b/i.test(s) },
|
|
15
45
|
{ id: "network.metadata", title: "Cloud metadata access", severity: "high", category: "secrets", explanation: "Cloud metadata endpoints can expose temporary instance credentials.", match: s => /169\.254\.169\.254|metadata\.google\.internal/i.test(s) },
|
|
16
46
|
{ id: "persistence.config", title: "Security-sensitive configuration", severity: "high", category: "persistence", explanation: "A persistence or agent configuration target is referenced. Check the intended change and trust boundary.", match: s => /authorized_keys|\bcrontab\b|LaunchAgents[\\/]|ANTHROPIC_BASE_URL/i.test(s) },
|
|
17
|
-
{ id: "network.reverse-shell", title: "Reverse shell pattern", severity: "critical", category: "exec", explanation: "This pattern can connect a command shell to another machine.", match: s => /\/dev\/tcp\/|\bnc\b[^\n]
|
|
47
|
+
{ id: "network.reverse-shell", title: "Reverse shell pattern", severity: "critical", category: "exec", explanation: "This pattern can connect a command shell to another machine.", match: s => /\/dev\/tcp\/|\bnc\b[^\n]{0,300}?\s-e\s|socket[\s\S]{0,200}?subprocess/i.test(s) },
|
|
18
48
|
{ id: "instructions.override", title: "Instruction override attempt", severity: "high", category: "integrity", explanation: "Instructions attempt to override existing safeguards or conceal activity from the user.", match: s => /ignore\s+(?:all\s+)?(?:previous|prior|system|safety)\s+(?:instructions|rules|prompts)|(?:do not|don't|never)\s+(?:tell|inform|notify)\s+(?:the\s+)?user|disable\s+(?:security|safety|logging|audit)/i.test(s) },
|
|
19
|
-
{ id: "source_control.history_rewrite", title: "Git history rewrite", severity: "medium", category: "source_control", explanation: "Force-pushing or rewriting shared history can silently discard other people's commits. Confirm the branch isn't shared before proceeding.", match: s => /\bgit\s+push\s+[^\n]
|
|
20
|
-
{ id: "integrity.tls_bypass", title: "Certificate or signature verification disabled", severity: "medium", category: "integrity", explanation: "Disabling TLS/certificate verification removes protection against a tampered or impersonated destination.", match: s => /\bcurl\b[^\n]
|
|
49
|
+
{ id: "source_control.history_rewrite", title: "Git history rewrite", severity: "medium", category: "source_control", explanation: "Force-pushing or rewriting shared history can silently discard other people's commits. Confirm the branch isn't shared before proceeding.", match: s => /\bgit\s+push\s+[^\n]{0,1000}?(?:--force(?:-with-lease)?|-f\b)|\bgit\s+filter-(?:branch|repo)\b/i.test(s) },
|
|
50
|
+
{ id: "integrity.tls_bypass", title: "Certificate or signature verification disabled", severity: "medium", category: "integrity", explanation: "Disabling TLS/certificate verification removes protection against a tampered or impersonated destination.", match: s => /\bcurl\b[^\n]{0,1000}?(?:-k\b|--insecure)|\bwget\b[^\n]{0,1000}?--no-check-certificate|NODE_TLS_REJECT_UNAUTHORIZED\s*=\s*['"]?0|\bgit\b[^\n]{0,1000}?-c\s+http\.sslVerify=false/i.test(s) },
|
|
21
51
|
];
|
|
22
52
|
/** Built-in rules by id, for callers (like `beam monitor`) that reuse a subset of the catalog. */
|
|
23
53
|
export function builtinRulesById(ids) {
|
package/dist/rule-catalog.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rule-catalog.js","sourceRoot":"","sources":["../src/rule-catalog.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,GAAG,6HAA6H,CAAC;AAC7I,MAAM,MAAM,GAAG,mFAAmF,CAAC;
|
|
1
|
+
{"version":3,"file":"rule-catalog.js","sourceRoot":"","sources":["../src/rule-catalog.ts"],"names":[],"mappings":"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"}
|
package/dist/sdk.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { MonitorSeverity } from "./monitor-client.js";
|
|
1
2
|
export interface AppMonitorOptions {
|
|
2
3
|
/** The app's token from the dashboard (App monitoring > Apps). Default: BEAM_APP_TOKEN. */
|
|
3
4
|
token?: string;
|
|
@@ -7,6 +8,20 @@ export interface AppMonitorOptions {
|
|
|
7
8
|
flushIntervalMs?: number;
|
|
8
9
|
/** Diagnostics (misconfiguration, App monitoring turned off, revoked token). Silent by default. */
|
|
9
10
|
onError?: (message: string) => void;
|
|
11
|
+
/**
|
|
12
|
+
* Random strings planted in your system prompt (at least 8 characters, e.g. "canary-7f3a9c1e").
|
|
13
|
+
* One showing up in output() means the system prompt leaked: a critical finding.
|
|
14
|
+
*/
|
|
15
|
+
canaries?: string[];
|
|
16
|
+
/** False: findings from prompt() and output() carry the rule and sender but no text excerpt. Default true. */
|
|
17
|
+
excerpts?: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* The most of one CPU core detection may use, in percent (0.1 to 50): that much for request()
|
|
20
|
+
* and log(), and as much again for prompt() and output(). Past it, checks are skipped until the
|
|
21
|
+
* next minute: request() and log() quietly, prompt() and output() with `skipped: true` so the
|
|
22
|
+
* app can decide. Default 2.
|
|
23
|
+
*/
|
|
24
|
+
maxCpuPercent?: number;
|
|
10
25
|
}
|
|
11
26
|
export interface RequestInfo {
|
|
12
27
|
method: string;
|
|
@@ -16,11 +31,43 @@ export interface RequestInfo {
|
|
|
16
31
|
userAgent?: string | null;
|
|
17
32
|
status?: number | null;
|
|
18
33
|
}
|
|
34
|
+
export interface PromptInfo {
|
|
35
|
+
/** Who sent it, to group repeats and spot floods: the client address or an opaque user id (not an email). */
|
|
36
|
+
ip?: string | null;
|
|
37
|
+
user?: string | null;
|
|
38
|
+
/** Shown with the finding, e.g. "support chat" or "retrieved web page". Default "prompts" or "model output". */
|
|
39
|
+
label?: string;
|
|
40
|
+
}
|
|
41
|
+
/** What a local check found. Matches count whatever the dashboard's level; reporting follows the level. */
|
|
42
|
+
export interface TextCheck {
|
|
43
|
+
flagged: boolean;
|
|
44
|
+
/** True when the check didn't run because the CPU budget for this minute was spent. */
|
|
45
|
+
skipped?: boolean;
|
|
46
|
+
/** The most severe match, or null when nothing matched. */
|
|
47
|
+
severity: MonitorSeverity | null;
|
|
48
|
+
matches: {
|
|
49
|
+
ruleId: string;
|
|
50
|
+
title: string;
|
|
51
|
+
severity: MonitorSeverity;
|
|
52
|
+
}[];
|
|
53
|
+
}
|
|
19
54
|
export interface AppMonitor {
|
|
20
55
|
/** Check one incoming request. Cheap and synchronous; never throws. */
|
|
21
56
|
request(info: RequestInfo): void;
|
|
22
57
|
/** Check one application log line (errors, auth failures, anything the app prints). */
|
|
23
58
|
log(line: string): void;
|
|
59
|
+
/**
|
|
60
|
+
* Check text before it reaches your model: the user's message, or content the model will read
|
|
61
|
+
* (a retrieved document, web page, email or tool result). Flags prompt injection, hidden
|
|
62
|
+
* instructions, forged chat markers, jailbreaks and system prompt extraction, and floods from
|
|
63
|
+
* one sender. Synchronous and local; never throws.
|
|
64
|
+
*/
|
|
65
|
+
prompt(text: string, info?: PromptInfo): TextCheck;
|
|
66
|
+
/**
|
|
67
|
+
* Check model output before you show it or act on it: zero-click exfiltration links, credentials,
|
|
68
|
+
* script, a leaked canary, and injected instructions passed along to the next agent.
|
|
69
|
+
*/
|
|
70
|
+
output(text: string, info?: PromptInfo): TextCheck;
|
|
24
71
|
/**
|
|
25
72
|
* Send pending findings when the flush interval is due (or now, with `force`). Returns the
|
|
26
73
|
* in-flight send, so `event.waitUntil(beam.flush())` keeps it alive past the response; cheap to
|
|
@@ -29,7 +76,13 @@ export interface AppMonitor {
|
|
|
29
76
|
flush(options?: {
|
|
30
77
|
force?: boolean;
|
|
31
78
|
}): Promise<void>;
|
|
32
|
-
/** False when there's no valid token or it was revoked:
|
|
79
|
+
/** False when there's no valid token or it was revoked: nothing is reported, and prompt() and output() only check locally. */
|
|
33
80
|
readonly enabled: boolean;
|
|
34
81
|
}
|
|
82
|
+
/** Checks text bound for an LLM, locally, without reporting it anywhere. Never throws. */
|
|
83
|
+
export declare function checkPrompt(text: string): TextCheck;
|
|
84
|
+
/** Checks model output, locally, without reporting it anywhere. Pass your system prompt's canaries to catch leaks. */
|
|
85
|
+
export declare function checkOutput(text: string, options?: {
|
|
86
|
+
canaries?: string[];
|
|
87
|
+
}): TextCheck;
|
|
35
88
|
export declare function createAppMonitor(options?: AppMonitorOptions): AppMonitor;
|