@node9/proxy 2.38.0 → 2.40.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/cli.js +1122 -972
- package/dist/cli.mjs +1121 -971
- package/dist/dashboard.mjs +166 -16
- package/dist/index.js +190 -47
- package/dist/index.mjs +190 -47
- package/dist/scan-ink.mjs +32 -4
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -438,6 +438,32 @@ function ssrfFloorDecision(m, asWritten, opts) {
|
|
|
438
438
|
}
|
|
439
439
|
return "block";
|
|
440
440
|
}
|
|
441
|
+
function isModeValue(v) {
|
|
442
|
+
return typeof v === "string" && MODE_VALUES.includes(v);
|
|
443
|
+
}
|
|
444
|
+
function levelOf(mode) {
|
|
445
|
+
if (mode === "observe") return "audit";
|
|
446
|
+
return LEVELS.includes(mode ?? "") ? mode : "standard";
|
|
447
|
+
}
|
|
448
|
+
function isRecordOnly(mode) {
|
|
449
|
+
return levelOf(mode) === "audit";
|
|
450
|
+
}
|
|
451
|
+
function reviewsEveryInline(mode) {
|
|
452
|
+
const level = levelOf(mode);
|
|
453
|
+
return level === "strict" || level === "block-all";
|
|
454
|
+
}
|
|
455
|
+
function isBlockAll(mode) {
|
|
456
|
+
return levelOf(mode) === "block-all";
|
|
457
|
+
}
|
|
458
|
+
function levelCheckValue(mode, id) {
|
|
459
|
+
return LEVEL_CHECKS[levelOf(mode)][id];
|
|
460
|
+
}
|
|
461
|
+
function levelChecks(mode) {
|
|
462
|
+
return LEVEL_CHECKS[levelOf(mode)];
|
|
463
|
+
}
|
|
464
|
+
function levelPackageSignals(mode) {
|
|
465
|
+
return levelOf(mode) === "soft" ? { newPackage: "off", installScript: "off" } : void 0;
|
|
466
|
+
}
|
|
441
467
|
function isVerdict(v) {
|
|
442
468
|
return v === "off" || v === "log" || v === "review" || v === "block";
|
|
443
469
|
}
|
|
@@ -583,19 +609,21 @@ function resolveCheck(settings, id) {
|
|
|
583
609
|
if (!def) return void 0;
|
|
584
610
|
if (isLockedCheck(def)) return { id, value: "block", source: "locked" };
|
|
585
611
|
const floor = def.floor ? CHECK_VERDICT_RANK[def.floor] : 0;
|
|
612
|
+
const levelDefault = levelCheckValue(settings.mode, id) ?? def.defaultValue;
|
|
613
|
+
const sourceOf = (value2) => value2 === levelDefault ? "default" : "configured";
|
|
586
614
|
const explicit = settings.checks?.[id];
|
|
587
615
|
if (isVerdict(explicit)) {
|
|
588
616
|
const value2 = CHECK_VERDICT_RANK[explicit] < floor ? def.floor : explicit;
|
|
589
|
-
return { id, value: value2, source: value2
|
|
617
|
+
return { id, value: value2, source: sourceOf(value2) };
|
|
590
618
|
}
|
|
591
619
|
if (def.pack) {
|
|
592
620
|
const on = settings.appliedShields?.includes(def.pack) ?? false;
|
|
593
621
|
return { id, value: on ? def.defaultValue : "off", source: "default" };
|
|
594
622
|
}
|
|
595
623
|
const read2 = LEGACY_READERS[id]?.(settings);
|
|
596
|
-
if (read2 === void 0) return { id, value:
|
|
624
|
+
if (read2 === void 0) return { id, value: levelDefault, source: "default" };
|
|
597
625
|
const value = CHECK_VERDICT_RANK[read2] < floor ? def.floor : read2;
|
|
598
|
-
return { id, value, source: value
|
|
626
|
+
return { id, value, source: sourceOf(value) };
|
|
599
627
|
}
|
|
600
628
|
function checkValue(settings, id) {
|
|
601
629
|
return resolveCheck(settings, id)?.value ?? "off";
|
|
@@ -5345,6 +5373,20 @@ function extractPackageInstalls(command) {
|
|
|
5345
5373
|
return true;
|
|
5346
5374
|
});
|
|
5347
5375
|
}
|
|
5376
|
+
function tuningFromLegacyPolicy(policy) {
|
|
5377
|
+
const out = {};
|
|
5378
|
+
const p = policy;
|
|
5379
|
+
if (policy.packageCheck?.registrySignals === false) {
|
|
5380
|
+
out["loading.malicious-package"] = { newPackage: "off", installScript: "off" };
|
|
5381
|
+
}
|
|
5382
|
+
for (const f of TUNING_FIELDS) {
|
|
5383
|
+
const [block, key] = f.legacy;
|
|
5384
|
+
const value = p[block]?.[key];
|
|
5385
|
+
if (value === void 0) continue;
|
|
5386
|
+
(out[f.checkId] ??= {})[f.name] = value;
|
|
5387
|
+
}
|
|
5388
|
+
return out;
|
|
5389
|
+
}
|
|
5348
5390
|
function tuningToLegacyPolicy(policy, tuning) {
|
|
5349
5391
|
const unknown = [];
|
|
5350
5392
|
for (const [id, fields] of Object.entries(tuning)) {
|
|
@@ -5459,6 +5501,25 @@ function checkToLegacyPolicy(policy, id, v) {
|
|
|
5459
5501
|
return false;
|
|
5460
5502
|
}
|
|
5461
5503
|
}
|
|
5504
|
+
function knobStatedChecks(policy) {
|
|
5505
|
+
const out = /* @__PURE__ */ new Set();
|
|
5506
|
+
const has = (o, key) => !!o && typeof o === "object" && o[key] !== void 0;
|
|
5507
|
+
const { dlp, egress, loopDetection, injectionScan, skillPinning, packageCheck } = policy;
|
|
5508
|
+
const uc = policy.untrustedContent;
|
|
5509
|
+
if (has(dlp, "enabled")) out.add("data.secrets");
|
|
5510
|
+
if (has(dlp, "reviewAction") || dlp?.enabled === false) out.add("data.secrets-weak");
|
|
5511
|
+
if (has(dlp, "pii")) out.add("data.pii");
|
|
5512
|
+
if (has(egress, "enabled") || has(egress, "mode")) out.add("network.unknown-host");
|
|
5513
|
+
if (has(egress, "ssrfStrict")) out.add("network.internal-addresses");
|
|
5514
|
+
if (has(loopDetection, "enabled")) out.add("behavior.loops");
|
|
5515
|
+
if (has(injectionScan, "enabled")) out.add("behavior.prompt-injection");
|
|
5516
|
+
if (has(skillPinning, "enabled") || has(skillPinning, "mode")) out.add("loading.skill-tamper");
|
|
5517
|
+
if (has(packageCheck, "enabled") || has(packageCheck, "onMalicious"))
|
|
5518
|
+
out.add("loading.malicious-package");
|
|
5519
|
+
if (uc && typeof uc === "object" && (uc.enabled === false || has(uc, "afterExposure")))
|
|
5520
|
+
out.add("behavior.untrusted-content");
|
|
5521
|
+
return out;
|
|
5522
|
+
}
|
|
5462
5523
|
function isKnobGoverned(id) {
|
|
5463
5524
|
return id in KNOB_GOVERNED;
|
|
5464
5525
|
}
|
|
@@ -6269,7 +6330,7 @@ async function evaluatePolicyCore(config, toolName, args, context = {}, hooks =
|
|
|
6269
6330
|
if (v?.logged) noteLogged(v);
|
|
6270
6331
|
else if (v) candidates.push(v);
|
|
6271
6332
|
};
|
|
6272
|
-
const inline = config.settings.mode
|
|
6333
|
+
const inline = reviewsEveryInline(config.settings.mode) ? detectInlineExec(shellCommand) ? void 0 : null : inlineExecReview(shellCommand);
|
|
6273
6334
|
if (inline !== null) {
|
|
6274
6335
|
consider("commands.inline-exec", {
|
|
6275
6336
|
decision: "review",
|
|
@@ -6329,21 +6390,17 @@ async function evaluatePolicyCore(config, toolName, args, context = {}, hooks =
|
|
|
6329
6390
|
if (firstToken && firstToken.startsWith("/") && checkProvenance2) {
|
|
6330
6391
|
const prov = checkProvenance2(firstToken, cwd);
|
|
6331
6392
|
if (prov.trustLevel === "suspect") {
|
|
6332
|
-
const
|
|
6333
|
-
|
|
6334
|
-
|
|
6335
|
-
{
|
|
6336
|
-
|
|
6337
|
-
|
|
6338
|
-
|
|
6339
|
-
tier: 3,
|
|
6340
|
-
checkId: "commands.temp-binary"
|
|
6341
|
-
}
|
|
6342
|
-
);
|
|
6393
|
+
const v = applyCheckValue(cv("commands.temp-binary"), {
|
|
6394
|
+
decision: "review",
|
|
6395
|
+
blockedByLabel: "Node9: Suspect Binary",
|
|
6396
|
+
reason: `Binary "${firstToken}" resolved to ${prov.resolvedPath} \u2014 ${prov.reason}`,
|
|
6397
|
+
tier: 3,
|
|
6398
|
+
checkId: "commands.temp-binary"
|
|
6399
|
+
});
|
|
6343
6400
|
if (v?.logged) noteLogged(v);
|
|
6344
6401
|
else if (v) return v;
|
|
6345
6402
|
}
|
|
6346
|
-
if (prov.trustLevel === "unknown" && config.settings.mode
|
|
6403
|
+
if (prov.trustLevel === "unknown" && isBlockAll(config.settings.mode)) {
|
|
6347
6404
|
return {
|
|
6348
6405
|
decision: "review",
|
|
6349
6406
|
blockedByLabel: "Node9: Unknown Binary (strict mode)",
|
|
@@ -6434,7 +6491,7 @@ async function evaluatePolicyCore(config, toolName, args, context = {}, hooks =
|
|
|
6434
6491
|
if (v?.logged) noteLogged(v);
|
|
6435
6492
|
else if (v) return v;
|
|
6436
6493
|
}
|
|
6437
|
-
if (config.settings.mode
|
|
6494
|
+
if (isBlockAll(config.settings.mode)) {
|
|
6438
6495
|
if (activeEnvironment?.requireApproval === false) return allowed();
|
|
6439
6496
|
return {
|
|
6440
6497
|
decision: "review",
|
|
@@ -7365,7 +7422,7 @@ function matchCanaryArgs(args, values) {
|
|
|
7365
7422
|
return null;
|
|
7366
7423
|
}
|
|
7367
7424
|
}
|
|
7368
|
-
var MAX_REGEX_LENGTH, REGEX_CACHE_MAX, regexCache, aws_default, bash_safe_default, docker_default, filesystem_default, github_default, k8s_default, mongodb_default, postgres_default, project_jail_default, redis_default, finance_default, identity_default, publishing_default, ACTION_TEMPLATES, ACTION_CHECKS, GAP, prog, httpTo, httpWrite, HTTP_WRITE, HTTP_WRITE_ANY, NOT_STRIPE_TEST, postTo, STRIPE_OBJECTS, APP_SHIELD_SPECS, APP_SHIELDS, APP_SHIELD_NAMES, APP_SERVER_GLOB, GENERAL_ACTION_RULES, BUILTIN_SHIELDS, SSRF_MAX_HOST, METADATA_ADDRESSES, STRICT_TIERS, METADATA_HOSTNAMES, v4Octets, TIER_REASON, CHECK_TEXT, VERDICTS, CHECK_VERDICT_RANK, ALL, BUILTIN_DANGEROUS_WORDS, PRODUCT_CHECKS, SHIELD_RULE_NAME, SHIELD_RULES_FOLDED_INTO_PRODUCT, CHECKS, CHECK_BY_ID, LEGACY_TO_ID, PROJECT_JAIL_BLOCK_READ, OVERRIDE_PREFIX, LABEL_WRAPPERS, LEGACY_READERS, INVISIBLE_RE, INVISIBLE_ONE, HOMOGLYPHS, HOMOGLYPH_RE, MAX_BLOBS, MIN_DECODED, BASE64_RUN_RE, HEX_RUN_RE, HEX_ESCAPE_RUN_RE, SYSTEM_AUTH_FILES, SYSTEM_AUTH_DIRS, PASSWORD_HASH_FILES, STARTUP_NAMES, SYSTEM_DIRS, SYSTEM_DIRS_EXEMPT, UPLOAD_SYSTEM_DIRS, AGENT_INSTRUCTION_FILES, AGENT_INSTRUCTION_DIRS, LEGACY_SYSTEM_PATH_RE, MAX_INLINE_CODE, WHAT, OUTSIDE, pyImport, either, PYTHON, NODE, PERL, RUBY, PHP, TABLES, STRING_LITERAL, syntax, sharedParser, MESSAGE_FLAGS, SHELL_INTERPRETERS, DOWNLOAD_CMDS, NORMALIZE_CACHE_MAX, normalizeCache, AST_CACHE_MAX, astCache, PARSE_FAIL, INTERPRETER_LINE, PROGRAM_DIR, ACCESS_VIEW_CACHE_MAX, accessViewCache, MAX_READING_PAYLOADS, defaultExpansionOps, VARIABLE_READERS, FS_READ_TOOLS, GREP_SHAPE, PATTERN_VERBS, PATTERN_VERB_NAMES, GREP_FILE_OPERANDS, READER_VALUE_LETTERS, FILE_OPERAND_FLAGS, SCP_VALUE_FLAGS, CURL_SOURCE_FLAGS, CURL_VALUE_LETTERS, WGET_VALUE_LETTERS, TAR_VALUE_LETTERS, ZIP_VALUE_LETTERS, RSYNC_VALUE_LETTERS, RSYNC_SKIP, CP_VALUE_LETTERS, INSTALL_VALUE_LETTERS, COPY_VERBS, TAR_MODE_WORD, COPY_VERB_HEADS, FS_OP_PRESCREEN_RE, HOME_CACHE_ALLOWLIST, SENSITIVE_PATH_RULES, AST_FS_REGEX_RULES, SQL_DB_CLIS, SQL_DDL_RE, CHMOD_OPEN_PERM_TOKENS, COMMAND_WRAPPERS, INLINE_INTERPRETER, RUNNER_WRAPPERS, _redirStdinOps, _listOps, WRAPPER_TAKES_TARGET, FIND_EXEC_FLAGS, FS_MUTATION_TOOLS, INTERP_LEADING_TARGET, MAX_PAYLOAD_NESTING, payloadNesting, MAX_INLINE_CALLS, INLINE_EXEC_FALLBACK, UNREADABLE_SOURCE, SCRIPT_RUNNERS, SCRIPT_RUNNER_VALUE_FLAGS, MAX_SCRIPT_OPERANDS, NET_BINARIES, VALUE_FLAGS, HOME_VARIABLES, assignmentTable, currentStmtOffset, PAYLOAD_BUDGET, payloadBudget, seenPayloads, UNANALYSABLE_NESTING, ASSIGNMENT_HEADS, AND_OP, OR_OP, AND_OR_OPS, MAX_CALL_DEPTH, MAX_CALL_WALKS, callDepth, callWalks, FS_OP_CACHE_MAX, fsOpCache, stripDotSlash, REDIR_TRUNCATE_OPS, REDIR_FILE_IN_OPS, REDIR_HEREDOC_OPS, FIND_OPTIONS, COPY_RULE_OF, isReaderWord, positionalAfter, NONE, UNKNOWN, FORBIDDEN_PATH_SEGMENTS, BASH_TOOL_NAMES, MCP_EXECUTORS, BUILTIN_FIELDS, ARGV_FIELDS, BARE_WORD, MAX_ARGV_CHARACTERS, syntax2, MAX_ALTERNATIVES, MAX_CALL_DEPTH2, MAX_CALL_WALKS2, POSITIONAL, MAX_DEPTH, MAX_PAYLOAD_DEPTH, unique, clone, SENDING_STDIN, DOWNLOAD_SHORT_VALUE, DOWNLOAD_LONG_VALUE, DOWNLOAD_OUTPUT_FLAGS, DOWNLOAD_DIR_FLAGS, base, quoteGlob, asWord, WRITES, READS, DUP_OUT, HERE_STRING, AND, OR, DEFAULT_OPS, exempt, RANK, BIP39_ENGLISH, BIP39_PUBLIC_VECTORS, indices, lengths, hash, MAX_MNEMONIC_HASHES, SECRET_VIEW_LIMITS, IBAN_LENGTH, IBAN_BBAN_SHAPE, B58, B58_INDEX, XPRV_VERSIONS, B62, CRC32_TABLE, GITHUB_TOKEN_RE, B64URL, B64URL_INDEX, CASK_TWO_ZERO_SUFFIX, CASK_FOUR_ZERO_SUFFIX, CF_ODD, CF_EVEN, SPANISH_LETTERS, HETU_CHARS, MAX, UNTRUSTED_TOOLS, SIGNALS, MENTION_QUOTE_RE, MENTION_WORD_RE, ASSIGNMENT_CONTEXT_RE, DLP_STOPWORDS, REFERENCE_VALUE_RE, IDENTIFIER_VALUE_RE, PATH_VALUE_RE, DOTTED_REFERENCE_RE, CONCATENATION_RE, EMAIL_VALUE_RE, FIXTURE_NAME_RE, DERIVATIVE_NAME_RE, QUERY_CREDENTIAL_VALUE_RE, OTP_SECRET_RE, OTP_DOC_SECRETS, ASSIGNED_SECRET_VALUE_RE, ASSIGNED_SECRET_NAME_RE, NAME_KEYWORD_RE, ARN_CONTEXT_RE, CIPHER_KEY_NAME_RE, CIPHER_NAME_PARTS, CIPHER_KEY_VALUE_RE, LARAVEL_KEY_VALUE_RE, SQL_PASSWORD_VALUE_RE, GRAFANA_KEY_VALUE_RE, BASIC_VALUE_RE, BASIC_PAIR_RE, OTP_CAPTURE_RE, DB_URL_PASSWORD_RE, DLP_PATTERNS, DLP_PATTERNS_GLOBAL, SENSITIVE_PATH_PATTERNS, SENSITIVE_PATH_REGEXES, MAX_DEPTH2, MAX_STRING_BYTES, MAX_JSON_PARSE_BYTES, BATCH_SEPARATOR, syntax3, NPM_INSTALL_VERBS, NPM_EXEC_VERBS, PNPM_INSTALL_VERBS, YARN_INSTALL_VERBS, BUN_INSTALL_VERBS, DLX_VERBS, NON_REGISTRY_RE, NPM_NAME_RE, EXACT_SEMVER_RE, NPM_VALUE_FLAGS, PNPM_VALUE_FLAGS, YARN_VALUE_FLAGS, BUN_VALUE_FLAGS, PIP_VALUE_FLAGS, UV_VALUE_FLAGS, POETRY_VALUE_FLAGS, PIPENV_VALUE_FLAGS, PIPX_VALUE_FLAGS, PY_SPEC_RE, PY_EXACT_RE, EXACT_VERSION_RE, GEM_NAME_RE, GEM_VALUE_FLAGS, BUNDLE_VALUE_FLAGS, CRATE_NAME_RE, CARGO_ADD_VALUE_FLAGS, CARGO_INSTALL_VALUE_FLAGS, GO_VALUE_FLAGS, GO_PATH_RE, NUGET_NAME_RE, DOTNET_ADD_VALUE_FLAGS, DOTNET_TOOL_VALUE_FLAGS, NUGET_VALUE_FLAGS, MAVEN_COORD_RE, COMPOSER_NAME_RE, COMPOSER_VALUE_FLAGS, EDITOR_HEADS, EXTENSION_ID_RE, MANAGER_HEADS, SHELLS, MAX_NESTING, SHELL_VALUE_FLAGS, TUNING_FIELDS, MAP_GOVERNED, KNOB_GOVERNED, CONFIGURABLE_CHECK_IDS, DEFAULT_EGRESS_ALLOWLIST, PRIVATE_HOST_SUFFIXES, SOURCE_COMMANDS, SINK_COMMANDS, OBFUSCATORS, SENSITIVE_PATTERNS, FLAGS_WITH_VALUES, DESTINATION_ARGS, MCP_DESTINATION_KEYS, ARGUMENT_SCAN_LIMITS, RUN_CHAR, runChar, VERDICT_RANK, SQL_DML_KEYWORDS, MAX_DESTINATIONS, MAX_SCAN_CHARS, EMAIL_RE, URL_RE, IBAN_RE, RECIPIENT_KEYS, DESTRUCTIVE_VERB_RE, PII_EMAIL_RE, PII_SSN_RE, PII_PHONE_RE, PII_CC16_RE, PII_CC15_RE, PII_CC14_RE, PII_CC13_RE, PII_CC19_RE, CARD_PATTERNS, PII_ROUTING_RE, ROUTING_LABEL_RE, ROUTING_LABEL_WINDOW, NATIONAL_ID_SHAPES, NATIONAL_ID_LABEL_RE, NATIONAL_ID_LABEL_WINDOW, NATIONAL_ID_GUARD_RE, PII_IBAN_RE, REALTIME_PII_PATTERNS, MAX_PII_SCAN_BYTES, IBAN_DESTINATION_KEYS, WHOLE_IBAN_RE, JSON_ESCAPE_RE, JSON_ESCAPES, MASKED_KINDS, ENTRY_RE, IBAN_TEXT_RE, EMAIL_TEXT_RE, ACCOUNT_KEY_RE, ACCOUNT_VALUE_RE, MAX_MASK_DEPTH, syntax4, EMPTY, CURL_SEND_FLAGS, WGET_SEND_FLAGS, IWR_SEND_FLAGS, WRITE_METHODS, GH_READ, GH_WRITE, GH_HOSTNAME_FLAGS, GH_REPO_VALUE_FLAGS, GH_API_VALUE_FLAGS, GIT_FETCH, PUBLISH, SHELLS2, OWN_HEADS, MAX_DEPTH3, CWD_CHANGERS, TERMINAL_ESCAPE_RE, LOOP_MAX_RECORDS, CANARY_MIN_LENGTH, MAX_TEXT, MAX_DEPTH4, MAX_JSON_PARSE, URL_DEPTH, B64_DEPTH, MIN_SEGMENT, SEPARATORS, stripSeparators, looksText, CANARY_DECODERS, VIEWS, LONG_OUTPUT_THRESHOLD_BYTES;
|
|
7425
|
+
var MAX_REGEX_LENGTH, REGEX_CACHE_MAX, regexCache, aws_default, bash_safe_default, docker_default, filesystem_default, github_default, k8s_default, mongodb_default, postgres_default, project_jail_default, redis_default, finance_default, identity_default, publishing_default, ACTION_TEMPLATES, ACTION_CHECKS, GAP, prog, httpTo, httpWrite, HTTP_WRITE, HTTP_WRITE_ANY, NOT_STRIPE_TEST, postTo, STRIPE_OBJECTS, APP_SHIELD_SPECS, APP_SHIELDS, APP_SHIELD_NAMES, APP_SERVER_GLOB, GENERAL_ACTION_RULES, BUILTIN_SHIELDS, SSRF_MAX_HOST, METADATA_ADDRESSES, STRICT_TIERS, METADATA_HOSTNAMES, v4Octets, TIER_REASON, CHECK_TEXT, LEVELS, MODE_VALUES, SOFT, STRICT, BLOCK_ALL, LEVEL_CHECKS, VERDICTS, CHECK_VERDICT_RANK, ALL, BUILTIN_DANGEROUS_WORDS, PRODUCT_CHECKS, SHIELD_RULE_NAME, SHIELD_RULES_FOLDED_INTO_PRODUCT, CHECKS, CHECK_BY_ID, LEGACY_TO_ID, PROJECT_JAIL_BLOCK_READ, OVERRIDE_PREFIX, LABEL_WRAPPERS, LEGACY_READERS, INVISIBLE_RE, INVISIBLE_ONE, HOMOGLYPHS, HOMOGLYPH_RE, MAX_BLOBS, MIN_DECODED, BASE64_RUN_RE, HEX_RUN_RE, HEX_ESCAPE_RUN_RE, SYSTEM_AUTH_FILES, SYSTEM_AUTH_DIRS, PASSWORD_HASH_FILES, STARTUP_NAMES, SYSTEM_DIRS, SYSTEM_DIRS_EXEMPT, UPLOAD_SYSTEM_DIRS, AGENT_INSTRUCTION_FILES, AGENT_INSTRUCTION_DIRS, LEGACY_SYSTEM_PATH_RE, MAX_INLINE_CODE, WHAT, OUTSIDE, pyImport, either, PYTHON, NODE, PERL, RUBY, PHP, TABLES, STRING_LITERAL, syntax, sharedParser, MESSAGE_FLAGS, SHELL_INTERPRETERS, DOWNLOAD_CMDS, NORMALIZE_CACHE_MAX, normalizeCache, AST_CACHE_MAX, astCache, PARSE_FAIL, INTERPRETER_LINE, PROGRAM_DIR, ACCESS_VIEW_CACHE_MAX, accessViewCache, MAX_READING_PAYLOADS, defaultExpansionOps, VARIABLE_READERS, FS_READ_TOOLS, GREP_SHAPE, PATTERN_VERBS, PATTERN_VERB_NAMES, GREP_FILE_OPERANDS, READER_VALUE_LETTERS, FILE_OPERAND_FLAGS, SCP_VALUE_FLAGS, CURL_SOURCE_FLAGS, CURL_VALUE_LETTERS, WGET_VALUE_LETTERS, TAR_VALUE_LETTERS, ZIP_VALUE_LETTERS, RSYNC_VALUE_LETTERS, RSYNC_SKIP, CP_VALUE_LETTERS, INSTALL_VALUE_LETTERS, COPY_VERBS, TAR_MODE_WORD, COPY_VERB_HEADS, FS_OP_PRESCREEN_RE, HOME_CACHE_ALLOWLIST, SENSITIVE_PATH_RULES, AST_FS_REGEX_RULES, SQL_DB_CLIS, SQL_DDL_RE, CHMOD_OPEN_PERM_TOKENS, COMMAND_WRAPPERS, INLINE_INTERPRETER, RUNNER_WRAPPERS, _redirStdinOps, _listOps, WRAPPER_TAKES_TARGET, FIND_EXEC_FLAGS, FS_MUTATION_TOOLS, INTERP_LEADING_TARGET, MAX_PAYLOAD_NESTING, payloadNesting, MAX_INLINE_CALLS, INLINE_EXEC_FALLBACK, UNREADABLE_SOURCE, SCRIPT_RUNNERS, SCRIPT_RUNNER_VALUE_FLAGS, MAX_SCRIPT_OPERANDS, NET_BINARIES, VALUE_FLAGS, HOME_VARIABLES, assignmentTable, currentStmtOffset, PAYLOAD_BUDGET, payloadBudget, seenPayloads, UNANALYSABLE_NESTING, ASSIGNMENT_HEADS, AND_OP, OR_OP, AND_OR_OPS, MAX_CALL_DEPTH, MAX_CALL_WALKS, callDepth, callWalks, FS_OP_CACHE_MAX, fsOpCache, stripDotSlash, REDIR_TRUNCATE_OPS, REDIR_FILE_IN_OPS, REDIR_HEREDOC_OPS, FIND_OPTIONS, COPY_RULE_OF, isReaderWord, positionalAfter, NONE, UNKNOWN, FORBIDDEN_PATH_SEGMENTS, BASH_TOOL_NAMES, MCP_EXECUTORS, BUILTIN_FIELDS, ARGV_FIELDS, BARE_WORD, MAX_ARGV_CHARACTERS, syntax2, MAX_ALTERNATIVES, MAX_CALL_DEPTH2, MAX_CALL_WALKS2, POSITIONAL, MAX_DEPTH, MAX_PAYLOAD_DEPTH, unique, clone, SENDING_STDIN, DOWNLOAD_SHORT_VALUE, DOWNLOAD_LONG_VALUE, DOWNLOAD_OUTPUT_FLAGS, DOWNLOAD_DIR_FLAGS, base, quoteGlob, asWord, WRITES, READS, DUP_OUT, HERE_STRING, AND, OR, DEFAULT_OPS, exempt, RANK, BIP39_ENGLISH, BIP39_PUBLIC_VECTORS, indices, lengths, hash, MAX_MNEMONIC_HASHES, SECRET_VIEW_LIMITS, IBAN_LENGTH, IBAN_BBAN_SHAPE, B58, B58_INDEX, XPRV_VERSIONS, B62, CRC32_TABLE, GITHUB_TOKEN_RE, B64URL, B64URL_INDEX, CASK_TWO_ZERO_SUFFIX, CASK_FOUR_ZERO_SUFFIX, CF_ODD, CF_EVEN, SPANISH_LETTERS, HETU_CHARS, MAX, UNTRUSTED_TOOLS, SIGNALS, MENTION_QUOTE_RE, MENTION_WORD_RE, ASSIGNMENT_CONTEXT_RE, DLP_STOPWORDS, REFERENCE_VALUE_RE, IDENTIFIER_VALUE_RE, PATH_VALUE_RE, DOTTED_REFERENCE_RE, CONCATENATION_RE, EMAIL_VALUE_RE, FIXTURE_NAME_RE, DERIVATIVE_NAME_RE, QUERY_CREDENTIAL_VALUE_RE, OTP_SECRET_RE, OTP_DOC_SECRETS, ASSIGNED_SECRET_VALUE_RE, ASSIGNED_SECRET_NAME_RE, NAME_KEYWORD_RE, ARN_CONTEXT_RE, CIPHER_KEY_NAME_RE, CIPHER_NAME_PARTS, CIPHER_KEY_VALUE_RE, LARAVEL_KEY_VALUE_RE, SQL_PASSWORD_VALUE_RE, GRAFANA_KEY_VALUE_RE, BASIC_VALUE_RE, BASIC_PAIR_RE, OTP_CAPTURE_RE, DB_URL_PASSWORD_RE, DLP_PATTERNS, DLP_PATTERNS_GLOBAL, SENSITIVE_PATH_PATTERNS, SENSITIVE_PATH_REGEXES, MAX_DEPTH2, MAX_STRING_BYTES, MAX_JSON_PARSE_BYTES, BATCH_SEPARATOR, syntax3, NPM_INSTALL_VERBS, NPM_EXEC_VERBS, PNPM_INSTALL_VERBS, YARN_INSTALL_VERBS, BUN_INSTALL_VERBS, DLX_VERBS, NON_REGISTRY_RE, NPM_NAME_RE, EXACT_SEMVER_RE, NPM_VALUE_FLAGS, PNPM_VALUE_FLAGS, YARN_VALUE_FLAGS, BUN_VALUE_FLAGS, PIP_VALUE_FLAGS, UV_VALUE_FLAGS, POETRY_VALUE_FLAGS, PIPENV_VALUE_FLAGS, PIPX_VALUE_FLAGS, PY_SPEC_RE, PY_EXACT_RE, EXACT_VERSION_RE, GEM_NAME_RE, GEM_VALUE_FLAGS, BUNDLE_VALUE_FLAGS, CRATE_NAME_RE, CARGO_ADD_VALUE_FLAGS, CARGO_INSTALL_VALUE_FLAGS, GO_VALUE_FLAGS, GO_PATH_RE, NUGET_NAME_RE, DOTNET_ADD_VALUE_FLAGS, DOTNET_TOOL_VALUE_FLAGS, NUGET_VALUE_FLAGS, MAVEN_COORD_RE, COMPOSER_NAME_RE, COMPOSER_VALUE_FLAGS, EDITOR_HEADS, EXTENSION_ID_RE, MANAGER_HEADS, SHELLS, MAX_NESTING, SHELL_VALUE_FLAGS, TUNING_FIELDS, MAP_GOVERNED, KNOB_GOVERNED, CONFIGURABLE_CHECK_IDS, DEFAULT_EGRESS_ALLOWLIST, PRIVATE_HOST_SUFFIXES, SOURCE_COMMANDS, SINK_COMMANDS, OBFUSCATORS, SENSITIVE_PATTERNS, FLAGS_WITH_VALUES, DESTINATION_ARGS, MCP_DESTINATION_KEYS, ARGUMENT_SCAN_LIMITS, RUN_CHAR, runChar, VERDICT_RANK, SQL_DML_KEYWORDS, MAX_DESTINATIONS, MAX_SCAN_CHARS, EMAIL_RE, URL_RE, IBAN_RE, RECIPIENT_KEYS, DESTRUCTIVE_VERB_RE, PII_EMAIL_RE, PII_SSN_RE, PII_PHONE_RE, PII_CC16_RE, PII_CC15_RE, PII_CC14_RE, PII_CC13_RE, PII_CC19_RE, CARD_PATTERNS, PII_ROUTING_RE, ROUTING_LABEL_RE, ROUTING_LABEL_WINDOW, NATIONAL_ID_SHAPES, NATIONAL_ID_LABEL_RE, NATIONAL_ID_LABEL_WINDOW, NATIONAL_ID_GUARD_RE, PII_IBAN_RE, REALTIME_PII_PATTERNS, MAX_PII_SCAN_BYTES, IBAN_DESTINATION_KEYS, WHOLE_IBAN_RE, JSON_ESCAPE_RE, JSON_ESCAPES, MASKED_KINDS, ENTRY_RE, IBAN_TEXT_RE, EMAIL_TEXT_RE, ACCOUNT_KEY_RE, ACCOUNT_VALUE_RE, MAX_MASK_DEPTH, syntax4, EMPTY, CURL_SEND_FLAGS, WGET_SEND_FLAGS, IWR_SEND_FLAGS, WRITE_METHODS, GH_READ, GH_WRITE, GH_HOSTNAME_FLAGS, GH_REPO_VALUE_FLAGS, GH_API_VALUE_FLAGS, GIT_FETCH, PUBLISH, SHELLS2, OWN_HEADS, MAX_DEPTH3, CWD_CHANGERS, TERMINAL_ESCAPE_RE, LOOP_MAX_RECORDS, CANARY_MIN_LENGTH, MAX_TEXT, MAX_DEPTH4, MAX_JSON_PARSE, URL_DEPTH, B64_DEPTH, MIN_SEGMENT, SEPARATORS, stripSeparators, looksText, CANARY_DECODERS, VIEWS, LONG_OUTPUT_THRESHOLD_BYTES;
|
|
7369
7426
|
var init_dist = __esm({
|
|
7370
7427
|
"packages/policy-engine/dist/index.mjs"() {
|
|
7371
7428
|
"use strict";
|
|
@@ -8996,7 +9053,7 @@ var init_dist = __esm({
|
|
|
8996
9053
|
"actions.money": {
|
|
8997
9054
|
plain: "The agent moves money (a refund, a payout, a transfer, a charge) through an app node9 has no protection for, such as an internal billing server.",
|
|
8998
9055
|
example: "refund_order on a server called acme-billing",
|
|
8999
|
-
advice: "
|
|
9056
|
+
advice: "Standard records these and Strict asks. Set Review to be asked before every money move at any level. When the app is Stripe or PayPal, turn on its own protection instead: it covers the CLI, the API and scripts too, and a call from it no longer comes here."
|
|
9000
9057
|
},
|
|
9001
9058
|
"actions.access": {
|
|
9002
9059
|
plain: "The agent changes a password, a key, a role or who belongs to a team, through an app node9 has no protection for.",
|
|
@@ -9173,6 +9230,54 @@ var init_dist = __esm({
|
|
|
9173
9230
|
advice: "Keep Block for known-malicious packages; brand-new packages already stop for Review."
|
|
9174
9231
|
}
|
|
9175
9232
|
};
|
|
9233
|
+
LEVELS = ["audit", "soft", "standard", "strict", "block-all"];
|
|
9234
|
+
MODE_VALUES = ["observe", ...LEVELS];
|
|
9235
|
+
SOFT = {
|
|
9236
|
+
"commands.inline-exec": "log",
|
|
9237
|
+
"commands.eval-dynamic": "log",
|
|
9238
|
+
"commands.rm": "log",
|
|
9239
|
+
"commands.chmod": "log",
|
|
9240
|
+
"commands.sudo": "log",
|
|
9241
|
+
"commands.git-destructive": "log",
|
|
9242
|
+
"commands.sql-ddl": "log",
|
|
9243
|
+
"commands.sql-no-where": "log",
|
|
9244
|
+
"commands.temp-binary": "log",
|
|
9245
|
+
"commands.disk-destroy": "log",
|
|
9246
|
+
"commands.dangerous-word": "log",
|
|
9247
|
+
"files.system-dirs": "log",
|
|
9248
|
+
"files.shell-startup": "log",
|
|
9249
|
+
"files.password-hashes": "log",
|
|
9250
|
+
"data.pipe-chain": "log",
|
|
9251
|
+
"behavior.untrusted-content": "log"
|
|
9252
|
+
};
|
|
9253
|
+
STRICT = {
|
|
9254
|
+
"commands.sql-ddl": "block",
|
|
9255
|
+
"commands.disk-destroy": "block",
|
|
9256
|
+
"commands.node9-disarm": "block",
|
|
9257
|
+
"files.system-dirs": "block",
|
|
9258
|
+
"files.shell-startup": "block",
|
|
9259
|
+
"files.password-hashes": "block",
|
|
9260
|
+
"data.secrets-weak": "block",
|
|
9261
|
+
"data.pipe-chain": "block",
|
|
9262
|
+
"network.unknown-host": "review",
|
|
9263
|
+
"network.internal-addresses": "block",
|
|
9264
|
+
"behavior.prompt-injection": "log",
|
|
9265
|
+
"loading.skill-tamper": "block",
|
|
9266
|
+
// Standard records money moves (catalog default log); Strict asks.
|
|
9267
|
+
"actions.money": "review"
|
|
9268
|
+
};
|
|
9269
|
+
BLOCK_ALL = {
|
|
9270
|
+
...STRICT,
|
|
9271
|
+
"commands.unknown": "review",
|
|
9272
|
+
"commands.temp-binary": "block"
|
|
9273
|
+
};
|
|
9274
|
+
LEVEL_CHECKS = {
|
|
9275
|
+
audit: {},
|
|
9276
|
+
soft: SOFT,
|
|
9277
|
+
standard: {},
|
|
9278
|
+
strict: STRICT,
|
|
9279
|
+
"block-all": BLOCK_ALL
|
|
9280
|
+
};
|
|
9176
9281
|
VERDICTS = ["off", "log", "review", "block"];
|
|
9177
9282
|
CHECK_VERDICT_RANK = { off: 0, log: 1, review: 2, block: 3 };
|
|
9178
9283
|
ALL = VERDICTS;
|
|
@@ -9589,7 +9694,10 @@ var init_dist = __esm({
|
|
|
9589
9694
|
title: "Money moves",
|
|
9590
9695
|
catches: "a refund, payout, transfer, charge or withdrawal through an app with no protection of its own",
|
|
9591
9696
|
values: ALL,
|
|
9592
|
-
|
|
9697
|
+
// Founder decision 2026-10-25: a transfer the user asked for is ordinary
|
|
9698
|
+
// work. Standard records it; Strict asks (levels.ts); a user who wants to
|
|
9699
|
+
// be asked states review.
|
|
9700
|
+
defaultValue: "log",
|
|
9593
9701
|
legacy: generalActionRuleNames("finance")
|
|
9594
9702
|
},
|
|
9595
9703
|
{
|
|
@@ -9629,7 +9737,7 @@ var init_dist = __esm({
|
|
|
9629
9737
|
"commands.rm": (s) => knob(s.commandChecks?.rmAdvisory),
|
|
9630
9738
|
"commands.chmod": (s) => knob(s.commandChecks?.chmod),
|
|
9631
9739
|
"commands.sql-ddl": (s) => knob(s.commandChecks?.sqlDdl),
|
|
9632
|
-
"commands.unknown": (s) => s.mode === void 0 ? void 0 : s.mode
|
|
9740
|
+
"commands.unknown": (s) => s.mode === void 0 ? void 0 : isBlockAll(s.mode) ? "review" : "off",
|
|
9633
9741
|
"data.secrets": (s) => enabledOr(s.dlp?.enabled, "block"),
|
|
9634
9742
|
"data.secrets-weak": (s) => {
|
|
9635
9743
|
if (s.dlp?.enabled === false) return "off";
|
|
@@ -15258,7 +15366,8 @@ var SmartRuleSchema = z.object({
|
|
|
15258
15366
|
var ConfigFileSchema = z.object({
|
|
15259
15367
|
version: z.string().optional(),
|
|
15260
15368
|
settings: z.object({
|
|
15261
|
-
|
|
15369
|
+
// The protection level (levels.ts in the engine); `observe` is Audit's older name.
|
|
15370
|
+
mode: z.enum(["observe", "audit", "soft", "standard", "strict", "block-all"]).optional(),
|
|
15262
15371
|
autoStartDaemon: z.boolean().optional(),
|
|
15263
15372
|
// enableUndo / policy.snapshot: removed with the undo feature. The
|
|
15264
15373
|
// schema strips undeclared keys silently (plain zod object — no
|
|
@@ -15633,7 +15742,7 @@ function readShieldOverrides() {
|
|
|
15633
15742
|
}
|
|
15634
15743
|
|
|
15635
15744
|
// src/config/managed.ts
|
|
15636
|
-
var MODE_ORDER = ["observe", "audit", "standard", "strict"];
|
|
15745
|
+
var MODE_ORDER = ["observe", "audit", "soft", "standard", "strict", "block-all"];
|
|
15637
15746
|
var EGRESS_MODE_ORDER = ["off", "review", "block"];
|
|
15638
15747
|
function rankIn(order, value) {
|
|
15639
15748
|
return value === void 0 ? -1 : order.indexOf(value);
|
|
@@ -15896,7 +16005,7 @@ function v2ToLegacy(raw, options = {}) {
|
|
|
15896
16005
|
continue;
|
|
15897
16006
|
}
|
|
15898
16007
|
if (id === "commands.unknown") {
|
|
15899
|
-
warnings.push(`checks.${id}: set "mode": "
|
|
16008
|
+
warnings.push(`checks.${id}: set "mode": "block-all" instead`);
|
|
15900
16009
|
continue;
|
|
15901
16010
|
}
|
|
15902
16011
|
const allowed = configurableValues(id);
|
|
@@ -16217,7 +16326,8 @@ var DEFAULT_CONFIG = {
|
|
|
16217
16326
|
// ── Actions in apps (node9Firewall#390) ───────────────────────────────
|
|
16218
16327
|
// actions.money / actions.access / actions.publish: the action templates
|
|
16219
16328
|
// on every MCP server no app shield claims, plus the shell publishing
|
|
16220
|
-
// rules. Review
|
|
16329
|
+
// rules. Review on the rule; the check value governs them (money is
|
|
16330
|
+
// recorded at Standard, asked at Strict).
|
|
16221
16331
|
...GENERAL_ACTION_RULES
|
|
16222
16332
|
],
|
|
16223
16333
|
dlp: { enabled: true, scanIgnoredTools: true, pii: "block" },
|
|
@@ -16435,6 +16545,11 @@ var KNOB_TO_CHECK = {
|
|
|
16435
16545
|
evalDynamic: "commands.eval-dynamic",
|
|
16436
16546
|
pipeChainHigh: "data.pipe-chain"
|
|
16437
16547
|
};
|
|
16548
|
+
function statedSignalFields(policy) {
|
|
16549
|
+
return Object.keys(tuningFromLegacyPolicy(policy)["loading.malicious-package"] ?? {}).filter(
|
|
16550
|
+
(k) => k === "newPackage" || k === "installScript"
|
|
16551
|
+
);
|
|
16552
|
+
}
|
|
16438
16553
|
function catalogSettingsFrom(settings, policy) {
|
|
16439
16554
|
return catalogSettingsFromConfig(settings, policy);
|
|
16440
16555
|
}
|
|
@@ -16502,6 +16617,8 @@ function getConfig(cwd) {
|
|
|
16502
16617
|
const keyed = !!pr2Creds?.apiKey && pr2Creds.localOnly !== true;
|
|
16503
16618
|
let ssrfStrictSource = "default";
|
|
16504
16619
|
const workspaceChecks = {};
|
|
16620
|
+
const managedStatedChecks = /* @__PURE__ */ new Set();
|
|
16621
|
+
const managedStatedSignals = /* @__PURE__ */ new Set();
|
|
16505
16622
|
const applyLayer = (source, isProject = false, isCloud = false) => {
|
|
16506
16623
|
if (!source) return;
|
|
16507
16624
|
const s = source.settings || {};
|
|
@@ -16709,9 +16826,11 @@ function getConfig(cwd) {
|
|
|
16709
16826
|
if (raw.managedConfig && typeof raw.managedConfig === "object") {
|
|
16710
16827
|
const mc = raw.managedConfig;
|
|
16711
16828
|
const locked = Array.isArray(mc.locked) ? mc.locked.filter((f) => typeof f === "string") : [];
|
|
16829
|
+
for (const id of knobStatedChecks(mc)) managedStatedChecks.add(id);
|
|
16830
|
+
for (const k of statedSignalFields(mc)) managedStatedSignals.add(k);
|
|
16712
16831
|
if (typeof mc.mode === "string") {
|
|
16713
16832
|
if (keyed) {
|
|
16714
|
-
if (
|
|
16833
|
+
if (isModeValue(mc.mode)) {
|
|
16715
16834
|
mergedSettings.mode = mc.mode;
|
|
16716
16835
|
}
|
|
16717
16836
|
} else {
|
|
@@ -16993,14 +17112,15 @@ function getConfig(cwd) {
|
|
|
16993
17112
|
const envMode = process.env.NODE9_MODE;
|
|
16994
17113
|
if (envMode && !modeCloudControlled && // PR-2: one listening point includes the env var — a keyed machine's
|
|
16995
17114
|
// mode comes from the workspace (or the shipped default), never the shell.
|
|
16996
|
-
!keyed &&
|
|
17115
|
+
!keyed && isModeValue(envMode)) {
|
|
16997
17116
|
mergedSettings.mode = envMode;
|
|
16998
17117
|
}
|
|
16999
|
-
if ((cloudManagedShields.length > 0 || cloudMandatesEnforcement) && !modeCloudControlled && !modeCloudStaged && (mergedSettings.mode
|
|
17118
|
+
if ((cloudManagedShields.length > 0 || cloudMandatesEnforcement) && !modeCloudControlled && !modeCloudStaged && isRecordOnly(mergedSettings.mode)) {
|
|
17000
17119
|
mergedSettings.mode = "standard";
|
|
17001
17120
|
}
|
|
17002
|
-
const
|
|
17003
|
-
|
|
17121
|
+
const cloudStrictLevel = levelOf(mergedSettings.mode) === "strict" || levelOf(mergedSettings.mode) === "block-all";
|
|
17122
|
+
const managedFloorActive = cloudManagedShields.length > 0 || cloudMandatesEnforcement || modeCloudControlled && cloudStrictLevel;
|
|
17123
|
+
if (modeCloudControlled && cloudStrictLevel) {
|
|
17004
17124
|
for (const name of Object.keys(mergedEnvironments)) {
|
|
17005
17125
|
if (mergedEnvironments[name]?.requireApproval === false) {
|
|
17006
17126
|
const cleaned = { ...mergedEnvironments[name] };
|
|
@@ -17018,6 +17138,35 @@ function getConfig(cwd) {
|
|
|
17018
17138
|
mergedPolicy.ignoredTools = [...new Set(mergedPolicy.ignoredTools)];
|
|
17019
17139
|
mergedPolicy.skillPinning.roots = [...new Set(mergedPolicy.skillPinning.roots)];
|
|
17020
17140
|
const resolvedSsrfStrictSource = keyed && ssrfStrictSource === "local" ? "default" : ssrfStrictSource;
|
|
17141
|
+
const level = levelOf(mergedSettings.mode);
|
|
17142
|
+
const levelKnobChecks = Object.entries(levelChecks(level)).filter(([id]) => isKnobGoverned(id));
|
|
17143
|
+
const signals = levelPackageSignals(level);
|
|
17144
|
+
if (levelKnobChecks.length > 0 || signals) {
|
|
17145
|
+
const policyOf = (layer) => layer?.policy ?? {};
|
|
17146
|
+
const trusted = /* @__PURE__ */ new Set([...managedStatedChecks, ...Object.keys(workspaceChecks)]);
|
|
17147
|
+
const trustedSignals = new Set(managedStatedSignals);
|
|
17148
|
+
const project = /* @__PURE__ */ new Set();
|
|
17149
|
+
const projectSignals = /* @__PURE__ */ new Set();
|
|
17150
|
+
if (!keyed) {
|
|
17151
|
+
for (const id of knobStatedChecks(policyOf(globalConfig))) trusted.add(id);
|
|
17152
|
+
for (const k of statedSignalFields(policyOf(globalConfig))) trustedSignals.add(k);
|
|
17153
|
+
for (const id of knobStatedChecks(policyOf(projectConfig))) project.add(id);
|
|
17154
|
+
for (const k of statedSignalFields(policyOf(projectConfig))) projectSignals.add(k);
|
|
17155
|
+
}
|
|
17156
|
+
const before = resolveCheckMap(catalogSettingsFromConfig({}, mergedPolicy));
|
|
17157
|
+
for (const [id, v] of levelKnobChecks) {
|
|
17158
|
+
if (trusted.has(id)) continue;
|
|
17159
|
+
if (project.has(id) && CHECK_VERDICT_RANK[v] <= CHECK_VERDICT_RANK[before[id] ?? "off"])
|
|
17160
|
+
continue;
|
|
17161
|
+
checkToLegacyPolicy(mergedPolicy, id, v);
|
|
17162
|
+
}
|
|
17163
|
+
if (signals) {
|
|
17164
|
+
for (const key of ["newPackage", "installScript"]) {
|
|
17165
|
+
if (trustedSignals.has(key) || projectSignals.has(key)) continue;
|
|
17166
|
+
mergedPolicy.packageCheck[key] = signals[key];
|
|
17167
|
+
}
|
|
17168
|
+
}
|
|
17169
|
+
}
|
|
17021
17170
|
const explicit = {};
|
|
17022
17171
|
const checkSources = {};
|
|
17023
17172
|
if (keyed) {
|
|
@@ -17189,6 +17338,9 @@ function applyUntrustedContent(cur, raw, replaceLists = false, isProject = false
|
|
|
17189
17338
|
// src/utils/regex.ts
|
|
17190
17339
|
init_dist();
|
|
17191
17340
|
|
|
17341
|
+
// src/policy/index.ts
|
|
17342
|
+
init_dist();
|
|
17343
|
+
|
|
17192
17344
|
// src/dlp.ts
|
|
17193
17345
|
init_dist();
|
|
17194
17346
|
init_dist();
|
|
@@ -20117,11 +20269,11 @@ async function checkOne(p, cfg, misses, networkCapped, cwd) {
|
|
|
20117
20269
|
}
|
|
20118
20270
|
return findings;
|
|
20119
20271
|
}
|
|
20120
|
-
var
|
|
20272
|
+
var SOFT2 = /* @__PURE__ */ new Set(["new", "install-script"]);
|
|
20121
20273
|
async function byHistory(p, version, info, findings, misses) {
|
|
20122
20274
|
let out = findings;
|
|
20123
20275
|
let h = info.history;
|
|
20124
|
-
if (!h && p.ecosystem === "PyPI" && out.some((f) =>
|
|
20276
|
+
if (!h && p.ecosystem === "PyPI" && out.some((f) => SOFT2.has(f.kind))) {
|
|
20125
20277
|
try {
|
|
20126
20278
|
h = await pypiHistory(p.name, version) ?? void 0;
|
|
20127
20279
|
} catch (err) {
|
|
@@ -20141,7 +20293,7 @@ async function byHistory(p, version, info, findings, misses) {
|
|
|
20141
20293
|
});
|
|
20142
20294
|
if (p.ecosystem === "npm") {
|
|
20143
20295
|
if (h.previousProvenance && h.provenance === false) return [...out, drop()];
|
|
20144
|
-
if (!out.some((f) =>
|
|
20296
|
+
if (!out.some((f) => SOFT2.has(f.kind)) || !h.provenance || !h.previousProvenance) return out;
|
|
20145
20297
|
const [now, before] = await Promise.all([
|
|
20146
20298
|
npmSourceRepo(p.name, version),
|
|
20147
20299
|
npmSourceRepo(p.name, previous)
|
|
@@ -20149,7 +20301,7 @@ async function byHistory(p, version, info, findings, misses) {
|
|
|
20149
20301
|
return vouched(p, version, now, before, out, misses);
|
|
20150
20302
|
}
|
|
20151
20303
|
if (p.ecosystem === "PyPI") {
|
|
20152
|
-
if (!out.some((f) =>
|
|
20304
|
+
if (!out.some((f) => SOFT2.has(f.kind)) || !info.file || !h.previousFile) return out;
|
|
20153
20305
|
const [now, before] = await Promise.all([
|
|
20154
20306
|
pypiSourceRepo(p.name, version, info.file),
|
|
20155
20307
|
pypiSourceRepo(p.name, previous, h.previousFile)
|
|
@@ -20165,7 +20317,7 @@ function vouched(p, version, now, before, findings, misses) {
|
|
|
20165
20317
|
return findings;
|
|
20166
20318
|
}
|
|
20167
20319
|
if (now === "none" || before === "none" || now !== before) return findings;
|
|
20168
|
-
return findings.filter((f) => !
|
|
20320
|
+
return findings.filter((f) => !SOFT2.has(f.kind));
|
|
20169
20321
|
}
|
|
20170
20322
|
async function runPackageCheck(toolName, args, cfg, cwd) {
|
|
20171
20323
|
if (!cfg.enabled) return ALLOW;
|
|
@@ -20485,7 +20637,7 @@ async function _authorizeHeadlessCore(toolName, args, metaArg, options) {
|
|
|
20485
20637
|
appendHookDebug(toolName, args, meta, hashAuditArgs);
|
|
20486
20638
|
}
|
|
20487
20639
|
const isManual = meta?.agent === "Terminal";
|
|
20488
|
-
const isObserveMode = config.settings.mode
|
|
20640
|
+
const isObserveMode = isRecordOnly(config.settings.mode);
|
|
20489
20641
|
let explainableLabel = "Local Config";
|
|
20490
20642
|
let dlpReviewFlagged = false;
|
|
20491
20643
|
let packageReview = null;
|
|
@@ -20543,7 +20695,7 @@ async function _authorizeHeadlessCore(toolName, args, metaArg, options) {
|
|
|
20543
20695
|
explainableLabel = "Shell inspection incomplete";
|
|
20544
20696
|
policyRuleDescription = "The executable command could not be inspected. Approve this call explicitly.";
|
|
20545
20697
|
}
|
|
20546
|
-
const fileReview = !isObserveMode &&
|
|
20698
|
+
const fileReview = !isObserveMode && fileFinding?.decision === "review";
|
|
20547
20699
|
const evaluateCurrentPolicy = async (skipIgnoredFastPath = false) => {
|
|
20548
20700
|
const own = await evaluatePolicy2(toolName, args, meta?.agent, options?.cwd, {
|
|
20549
20701
|
fileAccess,
|
|
@@ -20570,7 +20722,7 @@ async function _authorizeHeadlessCore(toolName, args, metaArg, options) {
|
|
|
20570
20722
|
if (fileFinding) {
|
|
20571
20723
|
meta = { ...meta, ruleName: fileFinding.ruleName };
|
|
20572
20724
|
hashAuditArgs = true;
|
|
20573
|
-
const observing = isObserveMode
|
|
20725
|
+
const observing = isObserveMode;
|
|
20574
20726
|
const blocked = !observing && (fileFinding.decision === "block" || fileReview && config.settings.panicMode);
|
|
20575
20727
|
appendLocalAudit(
|
|
20576
20728
|
toolName,
|
|
@@ -21052,15 +21204,6 @@ async function _authorizeHeadlessCore(toolName, args, metaArg, options) {
|
|
|
21052
21204
|
}
|
|
21053
21205
|
return { approved: true, checkedBy: "audit" };
|
|
21054
21206
|
}
|
|
21055
|
-
if (config.settings.mode === "audit") {
|
|
21056
|
-
if (judge) {
|
|
21057
|
-
const policyResult = await evaluateCurrentPolicy();
|
|
21058
|
-
if (policyResult.decision === "review") {
|
|
21059
|
-
appendLocalAudit(toolName, args, "allow", "audit-mode", ownRowMeta(true), hashAuditArgs);
|
|
21060
|
-
}
|
|
21061
|
-
}
|
|
21062
|
-
return { approved: true, checkedBy: "audit" };
|
|
21063
|
-
}
|
|
21064
21207
|
let appPermReview = null;
|
|
21065
21208
|
let appPermReviewTool = null;
|
|
21066
21209
|
const callSpecificReview = () => fileReview || shellReview || dlpReviewFlagged || !!appPermReview || !!taintWarning || !!exposureReview || !!packageReview;
|
package/dist/scan-ink.mjs
CHANGED
|
@@ -102,7 +102,8 @@ var SmartRuleSchema = z.object({
|
|
|
102
102
|
var ConfigFileSchema = z.object({
|
|
103
103
|
version: z.string().optional(),
|
|
104
104
|
settings: z.object({
|
|
105
|
-
|
|
105
|
+
// The protection level (levels.ts in the engine); `observe` is Audit's older name.
|
|
106
|
+
mode: z.enum(["observe", "audit", "soft", "standard", "strict", "block-all"]).optional(),
|
|
106
107
|
autoStartDaemon: z.boolean().optional(),
|
|
107
108
|
// enableUndo / policy.snapshot: removed with the undo feature. The
|
|
108
109
|
// schema strips undeclared keys silently (plain zod object — no
|
|
@@ -1944,7 +1945,7 @@ var CHECK_TEXT = {
|
|
|
1944
1945
|
"actions.money": {
|
|
1945
1946
|
plain: "The agent moves money (a refund, a payout, a transfer, a charge) through an app node9 has no protection for, such as an internal billing server.",
|
|
1946
1947
|
example: "refund_order on a server called acme-billing",
|
|
1947
|
-
advice: "
|
|
1948
|
+
advice: "Standard records these and Strict asks. Set Review to be asked before every money move at any level. When the app is Stripe or PayPal, turn on its own protection instead: it covers the CLI, the API and scripts too, and a call from it no longer comes here."
|
|
1948
1949
|
},
|
|
1949
1950
|
"actions.access": {
|
|
1950
1951
|
plain: "The agent changes a password, a key, a role or who belongs to a team, through an app node9 has no protection for.",
|
|
@@ -2121,6 +2122,29 @@ var CHECK_TEXT = {
|
|
|
2121
2122
|
advice: "Keep Block for known-malicious packages; brand-new packages already stop for Review."
|
|
2122
2123
|
}
|
|
2123
2124
|
};
|
|
2125
|
+
var LEVELS = ["audit", "soft", "standard", "strict", "block-all"];
|
|
2126
|
+
var MODE_VALUES = ["observe", ...LEVELS];
|
|
2127
|
+
var STRICT = {
|
|
2128
|
+
"commands.sql-ddl": "block",
|
|
2129
|
+
"commands.disk-destroy": "block",
|
|
2130
|
+
"commands.node9-disarm": "block",
|
|
2131
|
+
"files.system-dirs": "block",
|
|
2132
|
+
"files.shell-startup": "block",
|
|
2133
|
+
"files.password-hashes": "block",
|
|
2134
|
+
"data.secrets-weak": "block",
|
|
2135
|
+
"data.pipe-chain": "block",
|
|
2136
|
+
"network.unknown-host": "review",
|
|
2137
|
+
"network.internal-addresses": "block",
|
|
2138
|
+
"behavior.prompt-injection": "log",
|
|
2139
|
+
"loading.skill-tamper": "block",
|
|
2140
|
+
// Standard records money moves (catalog default log); Strict asks.
|
|
2141
|
+
"actions.money": "review"
|
|
2142
|
+
};
|
|
2143
|
+
var BLOCK_ALL = {
|
|
2144
|
+
...STRICT,
|
|
2145
|
+
"commands.unknown": "review",
|
|
2146
|
+
"commands.temp-binary": "block"
|
|
2147
|
+
};
|
|
2124
2148
|
var VERDICTS = ["off", "log", "review", "block"];
|
|
2125
2149
|
var ALL = VERDICTS;
|
|
2126
2150
|
var BUILTIN_DANGEROUS_WORDS = ["mkfs", "shred"];
|
|
@@ -2536,7 +2560,10 @@ var PRODUCT_CHECKS = [
|
|
|
2536
2560
|
title: "Money moves",
|
|
2537
2561
|
catches: "a refund, payout, transfer, charge or withdrawal through an app with no protection of its own",
|
|
2538
2562
|
values: ALL,
|
|
2539
|
-
|
|
2563
|
+
// Founder decision 2026-10-25: a transfer the user asked for is ordinary
|
|
2564
|
+
// work. Standard records it; Strict asks (levels.ts); a user who wants to
|
|
2565
|
+
// be asked states review.
|
|
2566
|
+
defaultValue: "log",
|
|
2540
2567
|
legacy: generalActionRuleNames("finance")
|
|
2541
2568
|
},
|
|
2542
2569
|
{
|
|
@@ -6917,7 +6944,8 @@ var DEFAULT_CONFIG = {
|
|
|
6917
6944
|
// ── Actions in apps (node9Firewall#390) ───────────────────────────────
|
|
6918
6945
|
// actions.money / actions.access / actions.publish: the action templates
|
|
6919
6946
|
// on every MCP server no app shield claims, plus the shell publishing
|
|
6920
|
-
// rules. Review
|
|
6947
|
+
// rules. Review on the rule; the check value governs them (money is
|
|
6948
|
+
// recorded at Standard, asked at Strict).
|
|
6921
6949
|
...GENERAL_ACTION_RULES
|
|
6922
6950
|
],
|
|
6923
6951
|
dlp: { enabled: true, scanIgnoredTools: true, pii: "block" },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@node9/proxy",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.40.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",
|