@node9/proxy 2.52.0 → 2.54.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/dist/scan-ink.mjs CHANGED
@@ -211,6 +211,8 @@ var ConfigFileSchema = z.object({
211
211
  registrySignals: z.boolean().optional(),
212
212
  newPackage: z.enum(["review", "off"]).optional(),
213
213
  installScript: z.enum(["review", "off"]).optional(),
214
+ lookalike: z.enum(["review", "off"]).optional(),
215
+ establishedAge: z.enum(["review", "off"]).optional(),
214
216
  maxAgeHours: z.number().min(0).optional(),
215
217
  onlineFallback: z.boolean().optional(),
216
218
  allow: z.array(z.string()).optional()
@@ -2335,7 +2337,7 @@ var CHECK_TEXT = {
2335
2337
  advice: "Fixed at Block. A person accepts the change on the machine (node9 mcp pin update)."
2336
2338
  },
2337
2339
  "loading.malicious-package": {
2338
- plain: "The agent installs a package that the public malicious-package database (OSV) lists, or one published minutes ago. Covers npm, PyPI, RubyGems, crates.io, Go, NuGet, Maven, Packagist and VS Code extensions; the publish-age and install-script signals are npm and PyPI only. A new release built from the same repository as the one before it (registry provenance) and an install script the package has always run do not stop; a release that lost the provenance its previous release had does.",
2340
+ plain: "The agent installs a package that the public malicious-package database (OSV) lists, or one published minutes ago. Covers npm, PyPI, RubyGems, crates.io, Go, NuGet, Maven, Packagist and VS Code extensions; the publish-age and install-script signals are npm and PyPI only. A new release built from the same repository as the one before it (registry provenance) and an install script the package has always run do not stop; a release that lost the provenance its previous release had does. A name that looks like a popular package and has no standing of its own, a name no package on npm or PyPI has, or a package npm removed as malicious also stops for review (the lookalike tuning). A fresh release of a package over a year old that released within the last six months is its normal cadence: Standard lets it through, Strict asks (the establishedAge tuning).",
2339
2341
  example: "npm install of a package flagged as malware",
2340
2342
  advice: "Keep Block for known-malicious packages; brand-new packages already stop for Review."
2341
2343
  },
@@ -3432,6 +3434,46 @@ var PHP = [
3432
3434
  ],
3433
3435
  ["permissions", /\b(?:chmod|chown|chgrp|lchown|lchgrp)\s*\(/]
3434
3436
  ];
3437
+ var READ_CALL = {
3438
+ python: String.raw`(?:\b(?:io|codecs)\.)?\bopen|\b(?:dotenv_values|load_dotenv|get_key|read_file|loadtxt|read_csv)`,
3439
+ node: String.raw`\b(?:readFileSync|readFile|createReadStream|readTextFile(?:Sync)?|readFileStr|openSync|file)`,
3440
+ perl: String.raw`\b(?:open|sysopen|read_file|slurp)`,
3441
+ ruby: String.raw`\b(?:File|IO)\.(?:read|binread|readlines|foreach|open)|\bDotenv\.(?:load|parse|overload)`,
3442
+ php: String.raw`\b(?:file_get_contents|fopen|file|readfile|parse_ini_file|highlight_file|show_source)`
3443
+ };
3444
+ var ARG = String.raw`(?:(?:(?:my|our|local)\s+)?[\w.$]+(?:\s*\(\s*\))?|'[^'\n]{0,8}'|"[^"\n]{0,8}")\s*,\s*`;
3445
+ var WRAP = String.raw`(?:(?:new\s+)?[\w.$]+\s*\(\s*(?:${ARG}){0,3}){0,3}`;
3446
+ var STR_PREFIX = String.raw`[rRbBuUfF]{0,2}`;
3447
+ var WRITE_MODE_LITERAL = String.raw`['"](?=[rbtU+]*w|(?![^'"]*\+)[rbtU]*[ax])[rwaxbtU+]{1,4}['"]`;
3448
+ var WRITE_MODE = String.raw`\s*,\s*(?:mode\s*=\s*)?${WRITE_MODE_LITERAL}`;
3449
+ var WRITE_MODE_AFTER = new RegExp(`^(?:\\s*\\)){0,3}${WRITE_MODE}`);
3450
+ var readCallBefore = (language) => new RegExp(
3451
+ String.raw`(?:${READ_CALL[language]})(?![\w$])\s*\(?\s*(?:${ARG}){0,3}${WRAP}${STR_PREFIX}$`
3452
+ );
3453
+ var READ_BEFORE = {
3454
+ python: readCallBefore("python"),
3455
+ node: readCallBefore("node"),
3456
+ perl: readCallBefore("perl"),
3457
+ ruby: readCallBefore("ruby"),
3458
+ php: readCallBefore("php")
3459
+ };
3460
+ var READ_AFTER = {
3461
+ python: new RegExp(
3462
+ String.raw`^\s*\)\s*\.\s*(?:read_text|read_bytes|open)\s*\((?!\s*(?:mode\s*=\s*)?${WRITE_MODE_LITERAL})`
3463
+ )
3464
+ };
3465
+ var ASSIGNED = new RegExp(String.raw`([$\w]+)\s*=\s*${WRAP}${STR_PREFIX}$`);
3466
+ var openedName = (language) => new RegExp(
3467
+ String.raw`(?:${READ_CALL[language]})(?![\w$])\s*\(?\s*(?:${ARG}){0,3}${WRAP}([$\w]+)(?!${WRITE_MODE})\s*[),]` + (language === "python" ? String.raw`|\bPath\s*\(\s*([$\w]+)\s*\)\s*\.\s*(?:read_text|read_bytes|open)\s*\(` : ""),
3468
+ "g"
3469
+ );
3470
+ var OPENED_NAME = {
3471
+ python: openedName("python"),
3472
+ node: openedName("node"),
3473
+ perl: openedName("perl"),
3474
+ ruby: openedName("ruby"),
3475
+ php: openedName("php")
3476
+ };
3435
3477
  var sharedParser = lazy(() => getSyntax().NewParser());
3436
3478
  var SHELL_INTERPRETERS = /* @__PURE__ */ new Set([
3437
3479
  "bash",
@@ -7380,6 +7422,16 @@ var TUNING_FIELDS = [
7380
7422
  name: "installScript",
7381
7423
  legacy: ["packageCheck", "installScript"]
7382
7424
  },
7425
+ {
7426
+ checkId: "loading.malicious-package",
7427
+ name: "lookalike",
7428
+ legacy: ["packageCheck", "lookalike"]
7429
+ },
7430
+ {
7431
+ checkId: "loading.malicious-package",
7432
+ name: "establishedAge",
7433
+ legacy: ["packageCheck", "establishedAge"]
7434
+ },
7383
7435
  {
7384
7436
  checkId: "loading.malicious-package",
7385
7437
  name: "onlineFallback",
@@ -7827,6 +7879,8 @@ var DEFAULT_CONFIG = {
7827
7879
  newPackage: "review",
7828
7880
  maxAgeHours: 48,
7829
7881
  installScript: "review",
7882
+ lookalike: "review",
7883
+ establishedAge: "off",
7830
7884
  onlineFallback: true,
7831
7885
  allow: []
7832
7886
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@node9/proxy",
3
- "version": "2.52.0",
3
+ "version": "2.54.0",
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",