@node9/proxy 2.48.1 → 2.48.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli-main.js +3507 -2984
- package/dist/dashboard.mjs +3510 -2987
- package/dist/hook.js +3500 -2977
- package/dist/index.js +3504 -2981
- package/dist/index.mjs +3508 -2985
- package/dist/scan-ink.mjs +52 -20
- package/package.json +1 -1
package/dist/scan-ink.mjs
CHANGED
|
@@ -238,10 +238,11 @@ import os from "os";
|
|
|
238
238
|
|
|
239
239
|
// packages/policy-engine/dist/index.mjs
|
|
240
240
|
import { fileURLToPath } from "url";
|
|
241
|
-
import
|
|
241
|
+
import picomatch2 from "picomatch";
|
|
242
242
|
import safeRegex from "safe-regex2";
|
|
243
243
|
import pm from "picomatch";
|
|
244
244
|
import { createRequire } from "module";
|
|
245
|
+
import picomatch from "picomatch";
|
|
245
246
|
import safeRegex2 from "safe-regex2";
|
|
246
247
|
import { createHash as createHash2 } from "crypto";
|
|
247
248
|
var getFilename = () => fileURLToPath(import.meta.url);
|
|
@@ -2234,6 +2235,11 @@ var CHECK_TEXT = {
|
|
|
2234
2235
|
example: "Copying ~/.npmrc into /tmp",
|
|
2235
2236
|
advice: "Fixed at Review for now."
|
|
2236
2237
|
},
|
|
2238
|
+
"data.credential-files-unknown": {
|
|
2239
|
+
plain: "The agent reads files whose names a listing produces only when the command runs, so node9 cannot tell in advance whether a credential file is among them.",
|
|
2240
|
+
example: "find . | xargs cat",
|
|
2241
|
+
advice: "Standard records it; Strict asks. Set Review if your agents should not read files they find this way."
|
|
2242
|
+
},
|
|
2237
2243
|
"data.pipe-chain": {
|
|
2238
2244
|
plain: "The agent reads a secret file and sends it over the network in the same command.",
|
|
2239
2245
|
example: "An SSH key file piped into curl",
|
|
@@ -2357,6 +2363,8 @@ var STRICT = {
|
|
|
2357
2363
|
"data.secrets-weak": "block",
|
|
2358
2364
|
"data.pipe-chain": "block",
|
|
2359
2365
|
"data.env-exfil": "block",
|
|
2366
|
+
// Names a listing produces at run time: Standard records, Strict asks.
|
|
2367
|
+
"data.credential-files-unknown": "review",
|
|
2360
2368
|
"loading.unknown-registry": "block",
|
|
2361
2369
|
"network.unknown-host": "review",
|
|
2362
2370
|
"network.internal-addresses": "block",
|
|
@@ -2651,6 +2659,14 @@ var PRODUCT_CHECKS = [
|
|
|
2651
2659
|
values: ALL,
|
|
2652
2660
|
defaultValue: "review"
|
|
2653
2661
|
},
|
|
2662
|
+
{
|
|
2663
|
+
id: "data.credential-files-unknown",
|
|
2664
|
+
group: "data",
|
|
2665
|
+
title: "Files read by names known only at run time",
|
|
2666
|
+
catches: "a reader fed names from a listing that can include credential files (find . | xargs cat)",
|
|
2667
|
+
values: ALL,
|
|
2668
|
+
defaultValue: "log"
|
|
2669
|
+
},
|
|
2654
2670
|
{
|
|
2655
2671
|
id: "data.pipe-chain",
|
|
2656
2672
|
group: "data",
|
|
@@ -3145,6 +3161,25 @@ var SYSTEM_DIRS = [
|
|
|
3145
3161
|
];
|
|
3146
3162
|
var UPLOAD_SYSTEM_DIRS = [...SYSTEM_DIRS, "/proc", "/sys", "/root"];
|
|
3147
3163
|
var LEGACY_SYSTEM_PATH_RE = /^(?:[a-zA-Z]:)?\/etc\/(?:passwd|shadow|sudoers)$/;
|
|
3164
|
+
function opOf(sample) {
|
|
3165
|
+
return parseShared(sample).Stmts[0].Redirs[0].Op;
|
|
3166
|
+
}
|
|
3167
|
+
var ops = lazy(() => ({
|
|
3168
|
+
WRITES: new Set([">x", ">>x", ">|x", "&>x", "&>>x", "<>x"].map(opOf)),
|
|
3169
|
+
APPENDS: new Set([">>x", "&>>x"].map(opOf)),
|
|
3170
|
+
READS: new Set(["<x", "<>x"].map(opOf)),
|
|
3171
|
+
/** `>&word` with a non-numeric word is `&>word` in bash. */
|
|
3172
|
+
DUP_OUT: opOf(">&x"),
|
|
3173
|
+
HERE_STRING: opOf("<<<x"),
|
|
3174
|
+
AND: parseShared("a && b").Stmts[0].Cmd.Op,
|
|
3175
|
+
OR: parseShared("a || b").Stmts[0].Cmd.Op,
|
|
3176
|
+
/** `${x:-d}` `${x-d}` `${x:=d}` `${x=d}`: the default is the value when x is unset. */
|
|
3177
|
+
DEFAULT_OPS: new Set(
|
|
3178
|
+
["${x:-y}", "${x-y}", "${x:=y}", "${x=y}"].map(
|
|
3179
|
+
(s) => parseShared(`echo ${s}`).Stmts[0].Cmd.Args[1].Parts[0].Exp.Op
|
|
3180
|
+
)
|
|
3181
|
+
)
|
|
3182
|
+
}));
|
|
3148
3183
|
var MAX_INLINE_CODE = 64 * 1024;
|
|
3149
3184
|
var OUTSIDE = String.raw`(?:~|\.\.[\\/]|/(?!(?:tmp|var/tmp)/(?![^'"\n]*\.\.)|dev/(?:null|stdout|stderr)\b))`;
|
|
3150
3185
|
var pyImport = (mods) => new RegExp(String.raw`\b(?:import\s+(?:[\w.]+(?:\s+as\s+\w+)?\s*,\s*)*|from\s+)(?:${mods})\b`);
|
|
@@ -3405,6 +3440,13 @@ var FS_READ_TOOLS = /* @__PURE__ */ new Set([
|
|
|
3405
3440
|
"tac",
|
|
3406
3441
|
"nl",
|
|
3407
3442
|
"dd",
|
|
3443
|
+
// Compare or merge files and print their lines (jail-indirect-reads,
|
|
3444
|
+
// 2026-11-02): `diff .env /dev/null` printed every line of the file.
|
|
3445
|
+
"diff",
|
|
3446
|
+
"cmp",
|
|
3447
|
+
"comm",
|
|
3448
|
+
"paste",
|
|
3449
|
+
"join",
|
|
3408
3450
|
// — PowerShell, absent until 2026-09-22 —
|
|
3409
3451
|
// Same membership test, "does it emit file contents": Get-Content/gc print
|
|
3410
3452
|
// the file (cat), Select-String/sls print matching lines (grep), Format-Hex
|
|
@@ -3882,6 +3924,14 @@ var REDIR_FILE_IN_OPS = lazy(
|
|
|
3882
3924
|
var REDIR_HEREDOC_OPS = lazy(
|
|
3883
3925
|
() => /* @__PURE__ */ new Set([deriveRedirOp("cat <<X\nX"), deriveRedirOp("cat <<-X\nX")])
|
|
3884
3926
|
);
|
|
3927
|
+
var pipeOps = lazy(
|
|
3928
|
+
() => new Set(
|
|
3929
|
+
["a | b", "a |& b"].map((t) => {
|
|
3930
|
+
const f = parseShared(t);
|
|
3931
|
+
return typeof f === "symbol" ? -1 : f.Stmts[0].Cmd.Op;
|
|
3932
|
+
})
|
|
3933
|
+
)
|
|
3934
|
+
);
|
|
3885
3935
|
var BASH_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
3886
3936
|
"bash",
|
|
3887
3937
|
"execute_bash",
|
|
@@ -3902,25 +3952,6 @@ var MCP_EXECUTORS = /* @__PURE__ */ new Set([
|
|
|
3902
3952
|
"run_terminal_command",
|
|
3903
3953
|
"start_process"
|
|
3904
3954
|
]);
|
|
3905
|
-
function opOf(sample) {
|
|
3906
|
-
return parseShared(sample).Stmts[0].Redirs[0].Op;
|
|
3907
|
-
}
|
|
3908
|
-
var ops = lazy(() => ({
|
|
3909
|
-
WRITES: new Set([">x", ">>x", ">|x", "&>x", "&>>x", "<>x"].map(opOf)),
|
|
3910
|
-
APPENDS: new Set([">>x", "&>>x"].map(opOf)),
|
|
3911
|
-
READS: new Set(["<x", "<>x"].map(opOf)),
|
|
3912
|
-
/** `>&word` with a non-numeric word is `&>word` in bash. */
|
|
3913
|
-
DUP_OUT: opOf(">&x"),
|
|
3914
|
-
HERE_STRING: opOf("<<<x"),
|
|
3915
|
-
AND: parseShared("a && b").Stmts[0].Cmd.Op,
|
|
3916
|
-
OR: parseShared("a || b").Stmts[0].Cmd.Op,
|
|
3917
|
-
/** `${x:-d}` `${x-d}` `${x:=d}` `${x=d}`: the default is the value when x is unset. */
|
|
3918
|
-
DEFAULT_OPS: new Set(
|
|
3919
|
-
["${x:-y}", "${x-y}", "${x:=y}", "${x=y}"].map(
|
|
3920
|
-
(s) => parseShared(`echo ${s}`).Stmts[0].Cmd.Args[1].Parts[0].Exp.Op
|
|
3921
|
-
)
|
|
3922
|
-
)
|
|
3923
|
-
}));
|
|
3924
3955
|
var SEQUENCE_OPS = lazy(() => {
|
|
3925
3956
|
const ops2 = /* @__PURE__ */ new Set();
|
|
3926
3957
|
for (const text of ["x && y", "x || y"]) {
|
|
@@ -7297,6 +7328,7 @@ var MAP_GOVERNED = /* @__PURE__ */ new Set([
|
|
|
7297
7328
|
"commands.reverse-shell",
|
|
7298
7329
|
"data.pipe-chain",
|
|
7299
7330
|
"data.env-exfil",
|
|
7331
|
+
"data.credential-files-unknown",
|
|
7300
7332
|
"loading.unknown-registry",
|
|
7301
7333
|
// The general action checks (node9Firewall#390): smart rules the map governs.
|
|
7302
7334
|
"actions.money",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@node9/proxy",
|
|
3
|
-
"version": "2.48.
|
|
3
|
+
"version": "2.48.2",
|
|
4
4
|
"description": "Access control for AI agents. Set what Claude Code, Codex, Gemini, Cursor and any MCP server are allowed to do, review risky actions before they run, and keep every action on the record.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|