@roxy-agent/agents 0.1.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.
Files changed (49) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +306 -0
  3. package/dist/approvals.js +143 -0
  4. package/dist/approvals.js.map +1 -0
  5. package/dist/classifier.js +436 -0
  6. package/dist/classifier.js.map +1 -0
  7. package/dist/dashboard/client.js +2057 -0
  8. package/dist/dashboard/client.js.map +1 -0
  9. package/dist/dashboard/html.js +57 -0
  10. package/dist/dashboard/html.js.map +1 -0
  11. package/dist/dashboard/icons.js +18 -0
  12. package/dist/dashboard/icons.js.map +1 -0
  13. package/dist/dashboard/server.js +423 -0
  14. package/dist/dashboard/server.js.map +1 -0
  15. package/dist/dashboard/styles.js +1685 -0
  16. package/dist/dashboard/styles.js.map +1 -0
  17. package/dist/dashboard.js +2 -0
  18. package/dist/dashboard.js.map +1 -0
  19. package/dist/db.js +526 -0
  20. package/dist/db.js.map +1 -0
  21. package/dist/index.js +94 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/license.js +257 -0
  24. package/dist/license.js.map +1 -0
  25. package/dist/logger.js +44 -0
  26. package/dist/logger.js.map +1 -0
  27. package/dist/ml/bash-classifier.js +121 -0
  28. package/dist/ml/bash-classifier.js.map +1 -0
  29. package/dist/ml/embedder.js +79 -0
  30. package/dist/ml/embedder.js.map +1 -0
  31. package/dist/ml/prototypes.js +707 -0
  32. package/dist/ml/prototypes.js.map +1 -0
  33. package/dist/policies.js +289 -0
  34. package/dist/policies.js.map +1 -0
  35. package/dist/slack.js +149 -0
  36. package/dist/slack.js.map +1 -0
  37. package/dist/tools/bash.js +134 -0
  38. package/dist/tools/bash.js.map +1 -0
  39. package/dist/tools/conversation.js +36 -0
  40. package/dist/tools/conversation.js.map +1 -0
  41. package/dist/tools/filesystem.js +243 -0
  42. package/dist/tools/filesystem.js.map +1 -0
  43. package/dist/tools/introspect.js +187 -0
  44. package/dist/tools/introspect.js.map +1 -0
  45. package/dist/tools/network.js +152 -0
  46. package/dist/tools/network.js.map +1 -0
  47. package/dist/tools/policies.js +107 -0
  48. package/dist/tools/policies.js.map +1 -0
  49. package/package.json +61 -0
@@ -0,0 +1,436 @@
1
+ import os from "node:os";
2
+ import path from "node:path";
3
+ import { getBuiltinRuleOverrides, getAppSetting } from "./db.js";
4
+ // ---------------------------------------------------------------------------
5
+ // Built-in rule override map. Cached in memory; refreshed on every CRUD via
6
+ // the dashboard. Disabled rules are still listed but skipped at classify
7
+ // time.
8
+ // ---------------------------------------------------------------------------
9
+ let _overrideCache = null;
10
+ export function refreshBuiltinRuleOverrides() {
11
+ _overrideCache = getBuiltinRuleOverrides();
12
+ }
13
+ function isRuleEnabled(id) {
14
+ if (_overrideCache === null) {
15
+ try {
16
+ _overrideCache = getBuiltinRuleOverrides();
17
+ }
18
+ catch {
19
+ _overrideCache = new Map();
20
+ }
21
+ }
22
+ const v = _overrideCache.get(id);
23
+ return v === undefined ? true : v; // default: enabled
24
+ }
25
+ // Returns true when the high-risk regex tier should escalate to HITL approval
26
+ // instead of the legacy "flagged but allowed" verdict. Default: on.
27
+ function highRiskRequiresApproval() {
28
+ if (process.env.AGENT_PROXY_REQUIRE_APPROVAL_HIGH === "0")
29
+ return false;
30
+ if (process.env.AGENT_PROXY_REQUIRE_APPROVAL_HIGH === "1")
31
+ return true;
32
+ try {
33
+ const v = getAppSetting("require_approval_high_risk");
34
+ if (v === "0" || v === "false")
35
+ return false;
36
+ return true;
37
+ }
38
+ catch {
39
+ return true;
40
+ }
41
+ }
42
+ // ---------------------------------------------------------------------------
43
+ // Bash command classification
44
+ // ---------------------------------------------------------------------------
45
+ // Patterns that are always denied — no exceptions.
46
+ export const DENY_PATTERNS = [
47
+ { id: "deny.rm-rf-root", pattern: /\brm\s+-[rRfF]+\s+\/(?!\w)/, reason: "rm -rf /" },
48
+ { id: "deny.rm-rf-home", pattern: /\brm\s+-[rRfF]+\s+~\s*$/, reason: "rm -rf ~" },
49
+ { id: "deny.curl-pipe-shell", pattern: /\bcurl\b[^|]*\|\s*(bash|sh|zsh|ksh|fish)\b/, reason: "curl | shell (supply chain)" },
50
+ { id: "deny.wget-pipe-shell", pattern: /\bwget\b[^|]*\|\s*(bash|sh|zsh|ksh|fish)\b/, reason: "wget | shell (supply chain)" },
51
+ { id: "deny.mkfs", pattern: /\bmkfs\.[a-z0-9]+/i, reason: "filesystem format" },
52
+ { id: "deny.dd-raw-device", pattern: /\bdd\b[^|;&]*\bof=\/dev\//, reason: "dd to raw device" },
53
+ { id: "deny.fork-bomb", pattern: /:\s*\(\s*\)\s*\{\s*:\s*\|\s*:\s*&\s*\}\s*;?\s*:/, reason: "fork bomb" },
54
+ { id: "deny.shutdown", pattern: /\bshutdown\b\s+-/, reason: "system shutdown" },
55
+ { id: "deny.halt-reboot", pattern: /\b(halt|poweroff|reboot)\b\s*(-|$)/, reason: "system halt/reboot" },
56
+ { id: "deny.base64-pipe-shell", pattern: /\bbase64\s+(-d|--decode|-D)\b[^|]*\|\s*(bash|sh|zsh|ksh|fish|python\d?|perl|ruby)\b/, reason: "base64-decoded payload piped to shell" },
57
+ { id: "deny.eval-curl", pattern: /\beval\s+["']?\$\(\s*(curl|wget|fetch)\b/, reason: "eval $(curl/wget …) — remote code exec" },
58
+ { id: "deny.proc-sub-curl", pattern: /<\(\s*(curl|wget|fetch)\b[^)]*\)/, reason: "process-substitution from curl/wget" },
59
+ { id: "deny.raw-device-write", pattern: />\s*\/dev\/(sd[a-z]|nvme\d|hd[a-z]|disk\d|md\d)\b/i, reason: "writing to raw block device" },
60
+ ];
61
+ // Patterns that are flagged as high risk — allowed but surfaced.
62
+ export const HIGH_RISK_PATTERNS = [
63
+ { id: "high.rm-recursive", pattern: /\brm\s+-[rRfF]+/, reason: "recursive delete" },
64
+ { id: "high.sudo", pattern: /\bsudo\b/, reason: "privilege escalation" },
65
+ { id: "high.chmod-world-writable", pattern: /\bchmod\s+(-R\s+)?[0-7]*7{2,3}\b/, reason: "world-writable permissions" },
66
+ { id: "high.chmod-setuid", pattern: /\bchmod\s+[ugoa]*\+s\b/, reason: "setuid/setgid bit" },
67
+ { id: "high.write-etc", pattern: /(>|>>)\s*\/etc\//, reason: "writing under /etc" },
68
+ { id: "high.write-system-path", pattern: /(>|>>)\s*\/(usr|bin|sbin|boot|var)\//, reason: "writing under system path" },
69
+ { id: "high.write-shell-rc", pattern: /(>|>>)\s*\S*\.(bashrc|zshrc|bash_profile|zprofile|zshenv|profile|inputrc)(?=$|\s|;|&|\||#)/, reason: "writing to shell rc/profile (persistence)" },
70
+ { id: "high.outbound-ssh", pattern: /\bssh\s+\S+@/, reason: "outbound ssh" },
71
+ { id: "high.outbound-scp", pattern: /\bscp\s+/, reason: "outbound scp" },
72
+ { id: "high.git-push", pattern: /\bgit\s+push\b/, reason: "git push" },
73
+ { id: "high.npm-publish", pattern: /\bnpm\s+publish\b/, reason: "npm publish" },
74
+ { id: "high.yarn-pnpm-publish", pattern: /\b(yarn|pnpm)\s+publish\b/, reason: "yarn/pnpm publish" },
75
+ { id: "high.aws-cli", pattern: /\baws\s+/, reason: "AWS CLI" },
76
+ { id: "high.gcloud-cli", pattern: /\bgcloud\s+/, reason: "gcloud CLI" },
77
+ { id: "high.kubectl-mutating", pattern: /\bkubectl\s+(delete|apply|patch|replace)\b/, reason: "kubectl mutating op" },
78
+ { id: "high.docker-destructive", pattern: /\bdocker\s+(rm|rmi|system\s+prune)\b/, reason: "docker destructive op" },
79
+ { id: "high.download-remote-file", pattern: /\b(curl|wget)\b.+\b(--output|-o|-O)\b/, reason: "downloading remote file" },
80
+ // Reverse-shell signatures
81
+ { id: "high.dev-tcp-socket", pattern: /\/dev\/tcp\/[\w.-]+\/\d+/, reason: "/dev/tcp socket (reverse shell)" },
82
+ { id: "high.nc-e-shell", pattern: /\b(nc|ncat|netcat)\b[^;|&]*\s-[a-zA-Z]*e[a-zA-Z]*\b\s*\/?\w*\/?(bash|sh|zsh)/, reason: "netcat -e shell (reverse shell)" },
83
+ { id: "high.nc-exec", pattern: /\b(nc|ncat|netcat)\b[^;|&]*\s--exec\b/, reason: "netcat --exec (reverse shell)" },
84
+ // Credential / secret reads
85
+ { id: "high.read-ssh-key", pattern: /\b(cat|less|more|head|tail|bat)\b[^|;&]*~?\/?\.ssh\/(id_[a-z0-9]+|authorized_keys|known_hosts)\b/, reason: "reading SSH key/secret" },
86
+ { id: "high.read-aws-credentials", pattern: /\b(cat|less|more|head|tail|bat)\b[^|;&]*~?\/?\.aws\/credentials\b/, reason: "reading AWS credentials" },
87
+ { id: "high.read-system-secret", pattern: /\b(cat|less|more|head|tail|bat)\b[^|;&]*\/etc\/(shadow|sudoers|passwd)\b/, reason: "reading sensitive system file" },
88
+ { id: "high.upload-credential-form", pattern: /\b(curl|wget)\b[^;|&]*\s-[A-Za-z]*[FT]\s*[\S]*@~?\/?\.(ssh|aws|gnupg|kube|config\/gcloud)\//, reason: "uploading credential file via curl/wget" },
89
+ { id: "high.upload-credential-data", pattern: /\b(curl|wget)\b[^;|&]*\s--(data-binary|upload-file)\b[^;|&]*@~?\/?\.(ssh|aws|gnupg|kube|config\/gcloud)\//, reason: "uploading credential file via curl/wget (data)" },
90
+ // Persistence
91
+ { id: "high.crontab-pipe", pattern: /\|\s*crontab\s+-/, reason: "modifying crontab via pipe" },
92
+ { id: "high.crontab-modify", pattern: /\bcrontab\s+(-e|-r|-l\s*$)/, reason: "modifying crontab" },
93
+ { id: "high.launchctl-persistence", pattern: /\blaunchctl\s+(load|bootstrap|enable|kickstart|asuser)\b/, reason: "launchd persistence" },
94
+ // Database destruction (via CLI eval flags)
95
+ { id: "high.mongo-destructive", pattern: /\bmongo(sh)?\b[^;|&]*--eval\b[^;|&]*\b(drop|remove|deleteMany)\b/i, reason: "destructive mongo eval" },
96
+ // Cryptominer binaries
97
+ { id: "high.cryptominer", pattern: /\b(xmrig|cgminer|ccminer|ethminer|nbminer|t-rex|nanominer|phoenixminer|lolminer)\b/i, reason: "cryptominer binary" },
98
+ // Mass file encryption (ransomware-shaped)
99
+ { id: "high.mass-file-encrypt", pattern: /\bfind\s+\S+[^;|&]*-exec\s+(openssl\s+enc|gpg\s+(-c|--symmetric|-e|--encrypt))\b/, reason: "mass file encryption (ransomware-shaped)" },
100
+ // Disk wipe via shred
101
+ { id: "high.shred-block-device", pattern: /\bshred\s+(-[a-zA-Z]+\s+)*\/dev\/(sd[a-z]|nvme\d|hd[a-z]|disk\d|md\d)\b/i, reason: "shred raw block device" },
102
+ // History / log evasion
103
+ { id: "high.history-clear", pattern: /\bhistory\s+-c\b/, reason: "clearing shell history" },
104
+ { id: "high.history-truncate", pattern: /(^|[\s;&|])>\s*~?\/?\.\w*_history\b/, reason: "truncating shell history file" },
105
+ { id: "high.histfile-unset", pattern: /\bunset\s+HISTFILE\b/, reason: "disabling shell history (HISTFILE)" },
106
+ { id: "high.histsize-zero", pattern: /\bexport\s+HISTSIZE=0\b/, reason: "disabling shell history (HISTSIZE)" },
107
+ // Browser / app data theft
108
+ { id: "high.browser-sql", pattern: /\bsqlite3\b[^;|&]*~?\/?(Library\/(Application Support|Cookies)|\.config\/(google-chrome|chromium|BraveSoftware)|AppData\/Local\/(Google|Microsoft|BraveSoftware))/i, reason: "browser/app data SQL access" },
109
+ { id: "high.browser-profile-copy", pattern: /\bcp\s+-[rR][^;|&]*~?\/?(Library\/Application\\?\s*Support|\.config)\/(Google|Mozilla|BraveSoftware|Microsoft|Slack|Signal)/i, reason: "copying browser/app profile data" },
110
+ ];
111
+ export const MEDIUM_RISK_PATTERNS = [
112
+ { id: "medium.git-destructive", pattern: /\bgit\s+(reset\s+--hard|clean\s+-[fF])/, reason: "git destructive op" },
113
+ { id: "medium.package-install", pattern: /\b(npm|yarn|pnpm)\s+install\b/, reason: "package install" },
114
+ { id: "medium.outbound-network", pattern: /\b(curl|wget)\b/, reason: "outbound network call" },
115
+ { id: "medium.absolute-cd", pattern: /\bcd\s+\//, reason: "absolute directory change" },
116
+ { id: "medium.parent-traversal", pattern: /\.\.\//, reason: "parent directory traversal" },
117
+ ];
118
+ // Hard-deny pre-filter. Always runs first, never depends on the ML model.
119
+ function checkBashDeny(command) {
120
+ for (const rule of DENY_PATTERNS) {
121
+ if (!isRuleEnabled(rule.id))
122
+ continue;
123
+ if (rule.pattern.test(command)) {
124
+ return {
125
+ risk_level: "high",
126
+ decision: "denied",
127
+ reason: `denied: ${rule.reason}`,
128
+ };
129
+ }
130
+ }
131
+ return null;
132
+ }
133
+ // Synchronous, regex-only classifier. Kept as the deterministic fallback
134
+ // when the ML model is loading, disabled, or low-confidence.
135
+ export function classifyBashCommand(command) {
136
+ const normalized = command.trim();
137
+ const deny = checkBashDeny(normalized);
138
+ if (deny)
139
+ return deny;
140
+ for (const rule of HIGH_RISK_PATTERNS) {
141
+ if (!isRuleEnabled(rule.id))
142
+ continue;
143
+ if (rule.pattern.test(normalized)) {
144
+ const decision = highRiskRequiresApproval()
145
+ ? "pending_approval"
146
+ : "flagged";
147
+ return { risk_level: "high", decision, reason: rule.reason };
148
+ }
149
+ }
150
+ for (const rule of MEDIUM_RISK_PATTERNS) {
151
+ if (!isRuleEnabled(rule.id))
152
+ continue;
153
+ if (rule.pattern.test(normalized)) {
154
+ return { risk_level: "medium", decision: "allowed", reason: rule.reason };
155
+ }
156
+ }
157
+ return { risk_level: "low", decision: "allowed", reason: "passed all checks" };
158
+ }
159
+ // Risk ordering for "most conservative wins" combination. We never want the
160
+ // ML model to silently downgrade a command that the rule-based classifier
161
+ // thought was risky.
162
+ const RISK_RANK = { low: 0, medium: 1, high: 2 };
163
+ const DECISION_RANK = {
164
+ allowed: 0,
165
+ flagged: 1,
166
+ pending_approval: 2,
167
+ denied: 3,
168
+ };
169
+ function moreConservative(a, b) {
170
+ // Pick whichever has the stricter decision; tiebreak on risk level.
171
+ if (DECISION_RANK[a.decision] !== DECISION_RANK[b.decision]) {
172
+ return DECISION_RANK[a.decision] > DECISION_RANK[b.decision] ? a : b;
173
+ }
174
+ if (RISK_RANK[a.risk_level] !== RISK_RANK[b.risk_level]) {
175
+ return RISK_RANK[a.risk_level] > RISK_RANK[b.risk_level] ? a : b;
176
+ }
177
+ return a;
178
+ }
179
+ // Async classifier that uses the ML model when ready and falls back to the
180
+ // rule-based classifier otherwise. Hard-deny patterns short-circuit before
181
+ // any ML call.
182
+ //
183
+ // Imported lazily so this module can still be loaded in environments where
184
+ // the ML deps aren't installed (e.g. minimal builds, tests).
185
+ export async function classifyBashCommandAsync(command) {
186
+ const normalized = command.trim();
187
+ const deny = checkBashDeny(normalized);
188
+ if (deny)
189
+ return deny;
190
+ // 2. User-defined natural-language policies (allow / block).
191
+ const policy = await applyPolicies(normalized, "bash");
192
+ if (policy)
193
+ return policy;
194
+ // ML disabled? Skip straight to rules.
195
+ if (process.env.AGENT_PROXY_ML === "0") {
196
+ return classifyBashCommand(normalized);
197
+ }
198
+ const ruleResult = classifyBashCommand(normalized);
199
+ try {
200
+ const { classifyBashML } = await import("./ml/bash-classifier.js");
201
+ const mlResult = await classifyBashML(normalized);
202
+ if (!mlResult)
203
+ return ruleResult;
204
+ return moreConservative(ruleResult, mlResult);
205
+ }
206
+ catch {
207
+ return ruleResult;
208
+ }
209
+ }
210
+ // Run user-defined policies for a given tool. Returns a Classification when
211
+ // a policy matches, or null when no policy applies and the rule/ML chain
212
+ // should run normally.
213
+ async function applyPolicies(description, tool) {
214
+ if (process.env.AGENT_PROXY_POLICIES === "0")
215
+ return null;
216
+ try {
217
+ const { matchPolicy } = await import("./policies.js");
218
+ const { block, approve, allow } = await matchPolicy(description, tool);
219
+ if (block) {
220
+ return {
221
+ risk_level: "high",
222
+ decision: "denied",
223
+ reason: `denied: policy #${block.policy.id} "${block.policy.description}" (sim=${block.similarity.toFixed(2)})`,
224
+ };
225
+ }
226
+ if (approve) {
227
+ return {
228
+ risk_level: "high",
229
+ decision: "pending_approval",
230
+ reason: `approval required: policy #${approve.policy.id} "${approve.policy.description}" (sim=${approve.similarity.toFixed(2)})`,
231
+ };
232
+ }
233
+ if (allow) {
234
+ return {
235
+ risk_level: "low",
236
+ decision: "allowed",
237
+ reason: `allowed by policy #${allow.policy.id} "${allow.policy.description}" (sim=${allow.similarity.toFixed(2)})`,
238
+ };
239
+ }
240
+ return null;
241
+ }
242
+ catch {
243
+ return null;
244
+ }
245
+ }
246
+ // Async wrappers for filesystem and network. These don't have an ML model
247
+ // yet, but they DO benefit from natural-language policies.
248
+ export async function classifyFilePathAsync(filePath, operation) {
249
+ // Hard structural checks (sensitive paths) run first via the sync rules.
250
+ const op = operation === "list" ? "read" : operation;
251
+ const ruleResult = classifyFilePath(filePath, op);
252
+ if (ruleResult.decision === "denied")
253
+ return ruleResult;
254
+ const policy = await applyPolicies(`${operation} file ${filePath}`, "filesystem");
255
+ if (policy) {
256
+ if (policy.decision === "denied")
257
+ return policy;
258
+ if (policy.decision === "pending_approval")
259
+ return policy;
260
+ // Allow policies de-escalate, but never below an explicit denied rule
261
+ // (already returned). Take the more conservative of (rules, allow) when
262
+ // rules are stricter — i.e. allow can downgrade flagged → allowed but
263
+ // not silently un-deny.
264
+ if (policy.decision === "allowed")
265
+ return policy;
266
+ }
267
+ return ruleResult;
268
+ }
269
+ export async function classifyNetworkRequestAsync(url, method = "GET") {
270
+ const ruleResult = classifyNetworkRequest(url, method);
271
+ if (ruleResult.decision === "denied")
272
+ return ruleResult;
273
+ const policy = await applyPolicies(`${method.toUpperCase()} ${url}`, "network");
274
+ if (policy) {
275
+ if (policy.decision === "denied")
276
+ return policy;
277
+ if (policy.decision === "pending_approval")
278
+ return policy;
279
+ if (policy.decision === "allowed")
280
+ return policy;
281
+ }
282
+ return ruleResult;
283
+ }
284
+ // ---------------------------------------------------------------------------
285
+ // Filesystem classification
286
+ // ---------------------------------------------------------------------------
287
+ const HOME = os.homedir();
288
+ // Sensitive locations. Stored as already-expanded paths so `path.includes`
289
+ // matches reliably regardless of how the agent expressed the path.
290
+ const SENSITIVE_PATH_FRAGMENTS = [
291
+ "/etc/",
292
+ "/root/",
293
+ "/var/log/",
294
+ "/private/etc/",
295
+ path.join(HOME, ".ssh"),
296
+ path.join(HOME, ".aws"),
297
+ path.join(HOME, ".gcp"),
298
+ path.join(HOME, ".config", "gcloud"),
299
+ path.join(HOME, ".kube"),
300
+ path.join(HOME, ".docker"),
301
+ path.join(HOME, ".npmrc"),
302
+ path.join(HOME, ".netrc"),
303
+ path.join(HOME, ".gitconfig"),
304
+ ];
305
+ const SENSITIVE_NAME_FRAGMENTS = [
306
+ ".env",
307
+ "id_rsa",
308
+ "id_ed25519",
309
+ "id_ecdsa",
310
+ "credentials",
311
+ "secret",
312
+ "secrets",
313
+ "private_key",
314
+ ".pem",
315
+ ".pfx",
316
+ ".keystore",
317
+ ];
318
+ function expandPath(p) {
319
+ if (p.startsWith("~/"))
320
+ return path.join(HOME, p.slice(2));
321
+ if (p === "~")
322
+ return HOME;
323
+ return p;
324
+ }
325
+ function isSensitivePath(filePath) {
326
+ const expanded = expandPath(filePath);
327
+ const normalized = path.resolve(expanded).toLowerCase();
328
+ for (const frag of SENSITIVE_PATH_FRAGMENTS) {
329
+ if (normalized.includes(frag.toLowerCase()))
330
+ return frag;
331
+ }
332
+ const base = path.basename(normalized);
333
+ for (const frag of SENSITIVE_NAME_FRAGMENTS) {
334
+ if (base.includes(frag.toLowerCase()))
335
+ return frag;
336
+ }
337
+ return null;
338
+ }
339
+ export function classifyFilePath(filePath, operation) {
340
+ const sensitiveHit = isSensitivePath(filePath);
341
+ if (operation === "delete") {
342
+ return {
343
+ risk_level: "high",
344
+ decision: "flagged",
345
+ reason: sensitiveHit
346
+ ? `delete on sensitive path (${sensitiveHit})`
347
+ : "file deletion",
348
+ };
349
+ }
350
+ if (sensitiveHit) {
351
+ // Writing to a sensitive path is denied; reading is flagged so the user
352
+ // is aware but the agent can still proceed.
353
+ if (operation === "write") {
354
+ return {
355
+ risk_level: "high",
356
+ decision: "denied",
357
+ reason: `denied: write to sensitive path (${sensitiveHit})`,
358
+ };
359
+ }
360
+ return {
361
+ risk_level: "high",
362
+ decision: "flagged",
363
+ reason: `read of sensitive path (${sensitiveHit})`,
364
+ };
365
+ }
366
+ if (operation === "write") {
367
+ return {
368
+ risk_level: "medium",
369
+ decision: "allowed",
370
+ reason: "file write",
371
+ };
372
+ }
373
+ return { risk_level: "low", decision: "allowed", reason: "safe file read" };
374
+ }
375
+ // ---------------------------------------------------------------------------
376
+ // Network classification
377
+ // ---------------------------------------------------------------------------
378
+ const LOCAL_HOSTS = new Set(["localhost", "127.0.0.1", "::1", "0.0.0.0"]);
379
+ const SCRIPT_EXT_RE = /\.(sh|bash|zsh|fish|py|rb|pl|ps1|psm1)(\?|#|$)/i;
380
+ const PRIVATE_RANGES = [
381
+ /^10\./,
382
+ /^192\.168\./,
383
+ /^172\.(1[6-9]|2[0-9]|3[01])\./,
384
+ /^169\.254\./,
385
+ ];
386
+ export function classifyNetworkRequest(url, method = "GET") {
387
+ let parsed;
388
+ try {
389
+ parsed = new URL(url);
390
+ }
391
+ catch {
392
+ return {
393
+ risk_level: "high",
394
+ decision: "denied",
395
+ reason: "denied: invalid URL",
396
+ };
397
+ }
398
+ if (SCRIPT_EXT_RE.test(parsed.pathname)) {
399
+ return {
400
+ risk_level: "high",
401
+ decision: "denied",
402
+ reason: "denied: fetching executable script",
403
+ };
404
+ }
405
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
406
+ return {
407
+ risk_level: "high",
408
+ decision: "denied",
409
+ reason: `denied: unsupported protocol ${parsed.protocol}`,
410
+ };
411
+ }
412
+ const host = parsed.hostname;
413
+ const isLocal = LOCAL_HOSTS.has(host) || PRIVATE_RANGES.some((re) => re.test(host));
414
+ const upperMethod = method.toUpperCase();
415
+ const isMutating = upperMethod !== "GET" && upperMethod !== "HEAD";
416
+ if (isLocal) {
417
+ return {
418
+ risk_level: "low",
419
+ decision: "allowed",
420
+ reason: "local network request",
421
+ };
422
+ }
423
+ if (isMutating) {
424
+ return {
425
+ risk_level: "high",
426
+ decision: "flagged",
427
+ reason: `external ${upperMethod} request`,
428
+ };
429
+ }
430
+ return {
431
+ risk_level: "medium",
432
+ decision: "flagged",
433
+ reason: "external network request",
434
+ };
435
+ }
436
+ //# sourceMappingURL=classifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classifier.js","sourceRoot":"","sources":["../src/classifier.ts"],"names":[],"mappings":"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"}