@node9/policy-engine 1.67.2 → 1.67.4
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/index.d.mts +18 -3
- package/dist/index.d.ts +18 -3
- package/dist/index.js +69 -7
- package/dist/index.mjs +68 -7
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -153,6 +153,21 @@ declare function matchSensitivePath(resolvedPath: string, originalPath: string):
|
|
|
153
153
|
declare function sensitivePathMatch(originalPath: string): DlpMatch;
|
|
154
154
|
/** Exposed so the proxy can apply the same patterns directly if needed. */
|
|
155
155
|
declare const SENSITIVE_PATH_REGEXES: readonly RegExp[];
|
|
156
|
+
/**
|
|
157
|
+
* The bounds scanArgs works within, published so callers can tell "scanned
|
|
158
|
+
* clean" apart from "never looked". A caller that must FAIL CLOSED on an
|
|
159
|
+
* unscanned value (e.g. the audit writer, which would otherwise persist an
|
|
160
|
+
* unexamined credential in plaintext) needs these to decide whether the scan
|
|
161
|
+
* actually covered its input. Exported rather than duplicated at the call
|
|
162
|
+
* site so the two can never drift apart.
|
|
163
|
+
*/
|
|
164
|
+
declare const DLP_SCAN_LIMITS: {
|
|
165
|
+
/** Max characters examined per individual string field; the remainder of an
|
|
166
|
+
* oversized string is NOT scanned. */
|
|
167
|
+
readonly maxStringBytes: 100000;
|
|
168
|
+
/** Max nesting depth walked; anything deeper is NOT scanned. */
|
|
169
|
+
readonly maxDepth: 5;
|
|
170
|
+
};
|
|
156
171
|
/**
|
|
157
172
|
* Recursively scans an args value for known secret patterns.
|
|
158
173
|
* Handles nested objects, arrays, and JSON-encoded strings.
|
|
@@ -1117,7 +1132,7 @@ declare const LONG_OUTPUT_THRESHOLD_BYTES: number;
|
|
|
1117
1132
|
* and fails CI when the hash drifts without a version bump — forgetting
|
|
1118
1133
|
* is loud, not silent.
|
|
1119
1134
|
*/
|
|
1120
|
-
declare const CANONICAL_EXTRACTOR_VERSION = "canonical-
|
|
1135
|
+
declare const CANONICAL_EXTRACTOR_VERSION = "canonical-v9";
|
|
1121
1136
|
/**
|
|
1122
1137
|
* SHA-256 prefix of the detector-source files
|
|
1123
1138
|
* (canonical.ts + pii.ts + destructive-regex.ts).
|
|
@@ -1128,7 +1143,7 @@ declare const CANONICAL_EXTRACTOR_VERSION = "canonical-v8";
|
|
|
1128
1143
|
* files changed, this hash must change too, and you must consciously
|
|
1129
1144
|
* decide whether to bump CANONICAL_EXTRACTOR_VERSION."
|
|
1130
1145
|
*/
|
|
1131
|
-
declare const CANONICAL_EXTRACTOR_HASH = "
|
|
1146
|
+
declare const CANONICAL_EXTRACTOR_HASH = "4ebf40dfe1d7c0a1";
|
|
1132
1147
|
declare function extractCanonicalFindings(call: ToolCallEntry, ctx: ExtractContext): CanonicalFinding[];
|
|
1133
1148
|
declare function extractSessionLevelFindings(calls: ReadonlyArray<SessionToolCall>, ctx: SessionExtractContext): CanonicalFinding[];
|
|
1134
1149
|
/**
|
|
@@ -1155,4 +1170,4 @@ declare function previewArgs(input: Record<string, unknown>, max: number): strin
|
|
|
1155
1170
|
/** Engine version stamped on audit entries for future drift detection. */
|
|
1156
1171
|
declare const ENGINE_VERSION = "1.4.0";
|
|
1157
1172
|
|
|
1158
|
-
export { AST_FS_REGEX_RULES, type AuditEntryForClassify, BASH_TOOL_NAMES, BUILTIN_SHIELDS, type BlastEnvFinding, type BlastFinding, type BlastResult, type BlastSummary, CANONICAL_EXTRACTOR_HASH, CANONICAL_EXTRACTOR_VERSION, COST_PER_LOOP_ITER_USD, type CanonicalAgent, type CanonicalFinding, type CanonicalFindingType, type CanonicalSourceType, DEFAULT_EGRESS_ALLOWLIST, DESTRUCTIVE_OP_RE, DLP_PATTERNS, type DlpMatch, ENGINE_VERSION, type EgressPolicy, type EgressVerdict, type ExtractContext, FILE_TOOLS, FLAGS_WITH_VALUES, type FsOpVerdict, type InjectionConfidence, type InjectionContext, type InjectionMatch, LONG_OUTPUT_THRESHOLD_BYTES, LOOP_MAX_RECORDS, LOOP_THRESHOLD_FOR_WASTE, type LoopWindowEvaluation, PRIVILEGE_ESCALATION_RE, type PiiPattern, type PipeChainAnalysis, type PolicyConfig, type PolicyContext, type PolicyHostHooks, type PolicyVerdict, type ProvenanceLookup, type ProvenanceTrust, REALTIME_PII_PATTERNS, type RiskMetadata, SCAN_SIGNAL_WEIGHTS, SENSITIVE_PATH_RE, SENSITIVE_PATH_REGEXES, type ScanFinding, type ScanSignals, type ScanSummary, type ScoreTier, type SessionExtractContext, type SessionToolCall, type Severity, type ShellCommandAnalysis, type ShellDestination, type ShieldDefinition, type ShieldOverrides, type ShieldVerdict, type SmartCondition, type SmartRule, type ToolCallEntry, type ToolCallRecord, analyzeFsOperation, analyzePipeChain, analyzeShellCommand, checkDangerousSql, classifyAuditEntry, classifyRuleSeverity, classifyScanSignal, computeAgentDeviceScore, computeArgsHash, computeBlendedSecurityScore, computeScanScore, computeSecurityScore, dedupeCanonicalFindings, detectArgsPii, detectDangerousEval, detectDangerousShellExec, detectInlineExec, detectPii, evaluateEgress, evaluateLoopWindow, evaluatePolicy, evaluateSmartConditions, extractAllSshHosts, extractCanonicalFindings, extractNetworkTargets, extractPositionalArgs, extractSessionLevelFindings, extractShellDestinations, getCompiledRegex, getNestedValue, hostMatches, isBashTool, isIgnoredTool, isPrivateHost, isProtectedHomePath, isShellShapedTool, isShieldVerdict, matchSensitivePath, matchesPattern, narrativeRuleLabel, normalizeCommandForPolicy, parseAllSshHostsFromCommand, parseDestHost, previewArgs, redactText, resolvePinned, scanArgs, scanInjection, scanText, sensitivePathMatch, summarizeBlast, summarizeScan, toScanFinding, toolMatchesRule, truncateBlastPath, validateOverrides, validateRegex, validateShieldDefinition };
|
|
1173
|
+
export { AST_FS_REGEX_RULES, type AuditEntryForClassify, BASH_TOOL_NAMES, BUILTIN_SHIELDS, type BlastEnvFinding, type BlastFinding, type BlastResult, type BlastSummary, CANONICAL_EXTRACTOR_HASH, CANONICAL_EXTRACTOR_VERSION, COST_PER_LOOP_ITER_USD, type CanonicalAgent, type CanonicalFinding, type CanonicalFindingType, type CanonicalSourceType, DEFAULT_EGRESS_ALLOWLIST, DESTRUCTIVE_OP_RE, DLP_PATTERNS, DLP_SCAN_LIMITS, type DlpMatch, ENGINE_VERSION, type EgressPolicy, type EgressVerdict, type ExtractContext, FILE_TOOLS, FLAGS_WITH_VALUES, type FsOpVerdict, type InjectionConfidence, type InjectionContext, type InjectionMatch, LONG_OUTPUT_THRESHOLD_BYTES, LOOP_MAX_RECORDS, LOOP_THRESHOLD_FOR_WASTE, type LoopWindowEvaluation, PRIVILEGE_ESCALATION_RE, type PiiPattern, type PipeChainAnalysis, type PolicyConfig, type PolicyContext, type PolicyHostHooks, type PolicyVerdict, type ProvenanceLookup, type ProvenanceTrust, REALTIME_PII_PATTERNS, type RiskMetadata, SCAN_SIGNAL_WEIGHTS, SENSITIVE_PATH_RE, SENSITIVE_PATH_REGEXES, type ScanFinding, type ScanSignals, type ScanSummary, type ScoreTier, type SessionExtractContext, type SessionToolCall, type Severity, type ShellCommandAnalysis, type ShellDestination, type ShieldDefinition, type ShieldOverrides, type ShieldVerdict, type SmartCondition, type SmartRule, type ToolCallEntry, type ToolCallRecord, analyzeFsOperation, analyzePipeChain, analyzeShellCommand, checkDangerousSql, classifyAuditEntry, classifyRuleSeverity, classifyScanSignal, computeAgentDeviceScore, computeArgsHash, computeBlendedSecurityScore, computeScanScore, computeSecurityScore, dedupeCanonicalFindings, detectArgsPii, detectDangerousEval, detectDangerousShellExec, detectInlineExec, detectPii, evaluateEgress, evaluateLoopWindow, evaluatePolicy, evaluateSmartConditions, extractAllSshHosts, extractCanonicalFindings, extractNetworkTargets, extractPositionalArgs, extractSessionLevelFindings, extractShellDestinations, getCompiledRegex, getNestedValue, hostMatches, isBashTool, isIgnoredTool, isPrivateHost, isProtectedHomePath, isShellShapedTool, isShieldVerdict, matchSensitivePath, matchesPattern, narrativeRuleLabel, normalizeCommandForPolicy, parseAllSshHostsFromCommand, parseDestHost, previewArgs, redactText, resolvePinned, scanArgs, scanInjection, scanText, sensitivePathMatch, summarizeBlast, summarizeScan, toScanFinding, toolMatchesRule, truncateBlastPath, validateOverrides, validateRegex, validateShieldDefinition };
|
package/dist/index.d.ts
CHANGED
|
@@ -153,6 +153,21 @@ declare function matchSensitivePath(resolvedPath: string, originalPath: string):
|
|
|
153
153
|
declare function sensitivePathMatch(originalPath: string): DlpMatch;
|
|
154
154
|
/** Exposed so the proxy can apply the same patterns directly if needed. */
|
|
155
155
|
declare const SENSITIVE_PATH_REGEXES: readonly RegExp[];
|
|
156
|
+
/**
|
|
157
|
+
* The bounds scanArgs works within, published so callers can tell "scanned
|
|
158
|
+
* clean" apart from "never looked". A caller that must FAIL CLOSED on an
|
|
159
|
+
* unscanned value (e.g. the audit writer, which would otherwise persist an
|
|
160
|
+
* unexamined credential in plaintext) needs these to decide whether the scan
|
|
161
|
+
* actually covered its input. Exported rather than duplicated at the call
|
|
162
|
+
* site so the two can never drift apart.
|
|
163
|
+
*/
|
|
164
|
+
declare const DLP_SCAN_LIMITS: {
|
|
165
|
+
/** Max characters examined per individual string field; the remainder of an
|
|
166
|
+
* oversized string is NOT scanned. */
|
|
167
|
+
readonly maxStringBytes: 100000;
|
|
168
|
+
/** Max nesting depth walked; anything deeper is NOT scanned. */
|
|
169
|
+
readonly maxDepth: 5;
|
|
170
|
+
};
|
|
156
171
|
/**
|
|
157
172
|
* Recursively scans an args value for known secret patterns.
|
|
158
173
|
* Handles nested objects, arrays, and JSON-encoded strings.
|
|
@@ -1117,7 +1132,7 @@ declare const LONG_OUTPUT_THRESHOLD_BYTES: number;
|
|
|
1117
1132
|
* and fails CI when the hash drifts without a version bump — forgetting
|
|
1118
1133
|
* is loud, not silent.
|
|
1119
1134
|
*/
|
|
1120
|
-
declare const CANONICAL_EXTRACTOR_VERSION = "canonical-
|
|
1135
|
+
declare const CANONICAL_EXTRACTOR_VERSION = "canonical-v9";
|
|
1121
1136
|
/**
|
|
1122
1137
|
* SHA-256 prefix of the detector-source files
|
|
1123
1138
|
* (canonical.ts + pii.ts + destructive-regex.ts).
|
|
@@ -1128,7 +1143,7 @@ declare const CANONICAL_EXTRACTOR_VERSION = "canonical-v8";
|
|
|
1128
1143
|
* files changed, this hash must change too, and you must consciously
|
|
1129
1144
|
* decide whether to bump CANONICAL_EXTRACTOR_VERSION."
|
|
1130
1145
|
*/
|
|
1131
|
-
declare const CANONICAL_EXTRACTOR_HASH = "
|
|
1146
|
+
declare const CANONICAL_EXTRACTOR_HASH = "4ebf40dfe1d7c0a1";
|
|
1132
1147
|
declare function extractCanonicalFindings(call: ToolCallEntry, ctx: ExtractContext): CanonicalFinding[];
|
|
1133
1148
|
declare function extractSessionLevelFindings(calls: ReadonlyArray<SessionToolCall>, ctx: SessionExtractContext): CanonicalFinding[];
|
|
1134
1149
|
/**
|
|
@@ -1155,4 +1170,4 @@ declare function previewArgs(input: Record<string, unknown>, max: number): strin
|
|
|
1155
1170
|
/** Engine version stamped on audit entries for future drift detection. */
|
|
1156
1171
|
declare const ENGINE_VERSION = "1.4.0";
|
|
1157
1172
|
|
|
1158
|
-
export { AST_FS_REGEX_RULES, type AuditEntryForClassify, BASH_TOOL_NAMES, BUILTIN_SHIELDS, type BlastEnvFinding, type BlastFinding, type BlastResult, type BlastSummary, CANONICAL_EXTRACTOR_HASH, CANONICAL_EXTRACTOR_VERSION, COST_PER_LOOP_ITER_USD, type CanonicalAgent, type CanonicalFinding, type CanonicalFindingType, type CanonicalSourceType, DEFAULT_EGRESS_ALLOWLIST, DESTRUCTIVE_OP_RE, DLP_PATTERNS, type DlpMatch, ENGINE_VERSION, type EgressPolicy, type EgressVerdict, type ExtractContext, FILE_TOOLS, FLAGS_WITH_VALUES, type FsOpVerdict, type InjectionConfidence, type InjectionContext, type InjectionMatch, LONG_OUTPUT_THRESHOLD_BYTES, LOOP_MAX_RECORDS, LOOP_THRESHOLD_FOR_WASTE, type LoopWindowEvaluation, PRIVILEGE_ESCALATION_RE, type PiiPattern, type PipeChainAnalysis, type PolicyConfig, type PolicyContext, type PolicyHostHooks, type PolicyVerdict, type ProvenanceLookup, type ProvenanceTrust, REALTIME_PII_PATTERNS, type RiskMetadata, SCAN_SIGNAL_WEIGHTS, SENSITIVE_PATH_RE, SENSITIVE_PATH_REGEXES, type ScanFinding, type ScanSignals, type ScanSummary, type ScoreTier, type SessionExtractContext, type SessionToolCall, type Severity, type ShellCommandAnalysis, type ShellDestination, type ShieldDefinition, type ShieldOverrides, type ShieldVerdict, type SmartCondition, type SmartRule, type ToolCallEntry, type ToolCallRecord, analyzeFsOperation, analyzePipeChain, analyzeShellCommand, checkDangerousSql, classifyAuditEntry, classifyRuleSeverity, classifyScanSignal, computeAgentDeviceScore, computeArgsHash, computeBlendedSecurityScore, computeScanScore, computeSecurityScore, dedupeCanonicalFindings, detectArgsPii, detectDangerousEval, detectDangerousShellExec, detectInlineExec, detectPii, evaluateEgress, evaluateLoopWindow, evaluatePolicy, evaluateSmartConditions, extractAllSshHosts, extractCanonicalFindings, extractNetworkTargets, extractPositionalArgs, extractSessionLevelFindings, extractShellDestinations, getCompiledRegex, getNestedValue, hostMatches, isBashTool, isIgnoredTool, isPrivateHost, isProtectedHomePath, isShellShapedTool, isShieldVerdict, matchSensitivePath, matchesPattern, narrativeRuleLabel, normalizeCommandForPolicy, parseAllSshHostsFromCommand, parseDestHost, previewArgs, redactText, resolvePinned, scanArgs, scanInjection, scanText, sensitivePathMatch, summarizeBlast, summarizeScan, toScanFinding, toolMatchesRule, truncateBlastPath, validateOverrides, validateRegex, validateShieldDefinition };
|
|
1173
|
+
export { AST_FS_REGEX_RULES, type AuditEntryForClassify, BASH_TOOL_NAMES, BUILTIN_SHIELDS, type BlastEnvFinding, type BlastFinding, type BlastResult, type BlastSummary, CANONICAL_EXTRACTOR_HASH, CANONICAL_EXTRACTOR_VERSION, COST_PER_LOOP_ITER_USD, type CanonicalAgent, type CanonicalFinding, type CanonicalFindingType, type CanonicalSourceType, DEFAULT_EGRESS_ALLOWLIST, DESTRUCTIVE_OP_RE, DLP_PATTERNS, DLP_SCAN_LIMITS, type DlpMatch, ENGINE_VERSION, type EgressPolicy, type EgressVerdict, type ExtractContext, FILE_TOOLS, FLAGS_WITH_VALUES, type FsOpVerdict, type InjectionConfidence, type InjectionContext, type InjectionMatch, LONG_OUTPUT_THRESHOLD_BYTES, LOOP_MAX_RECORDS, LOOP_THRESHOLD_FOR_WASTE, type LoopWindowEvaluation, PRIVILEGE_ESCALATION_RE, type PiiPattern, type PipeChainAnalysis, type PolicyConfig, type PolicyContext, type PolicyHostHooks, type PolicyVerdict, type ProvenanceLookup, type ProvenanceTrust, REALTIME_PII_PATTERNS, type RiskMetadata, SCAN_SIGNAL_WEIGHTS, SENSITIVE_PATH_RE, SENSITIVE_PATH_REGEXES, type ScanFinding, type ScanSignals, type ScanSummary, type ScoreTier, type SessionExtractContext, type SessionToolCall, type Severity, type ShellCommandAnalysis, type ShellDestination, type ShieldDefinition, type ShieldOverrides, type ShieldVerdict, type SmartCondition, type SmartRule, type ToolCallEntry, type ToolCallRecord, analyzeFsOperation, analyzePipeChain, analyzeShellCommand, checkDangerousSql, classifyAuditEntry, classifyRuleSeverity, classifyScanSignal, computeAgentDeviceScore, computeArgsHash, computeBlendedSecurityScore, computeScanScore, computeSecurityScore, dedupeCanonicalFindings, detectArgsPii, detectDangerousEval, detectDangerousShellExec, detectInlineExec, detectPii, evaluateEgress, evaluateLoopWindow, evaluatePolicy, evaluateSmartConditions, extractAllSshHosts, extractCanonicalFindings, extractNetworkTargets, extractPositionalArgs, extractSessionLevelFindings, extractShellDestinations, getCompiledRegex, getNestedValue, hostMatches, isBashTool, isIgnoredTool, isPrivateHost, isProtectedHomePath, isShellShapedTool, isShieldVerdict, matchSensitivePath, matchesPattern, narrativeRuleLabel, normalizeCommandForPolicy, parseAllSshHostsFromCommand, parseDestHost, previewArgs, redactText, resolvePinned, scanArgs, scanInjection, scanText, sensitivePathMatch, summarizeBlast, summarizeScan, toScanFinding, toolMatchesRule, truncateBlastPath, validateOverrides, validateRegex, validateShieldDefinition };
|
package/dist/index.js
CHANGED
|
@@ -39,6 +39,7 @@ __export(src_exports, {
|
|
|
39
39
|
DEFAULT_EGRESS_ALLOWLIST: () => DEFAULT_EGRESS_ALLOWLIST,
|
|
40
40
|
DESTRUCTIVE_OP_RE: () => DESTRUCTIVE_OP_RE,
|
|
41
41
|
DLP_PATTERNS: () => DLP_PATTERNS,
|
|
42
|
+
DLP_SCAN_LIMITS: () => DLP_SCAN_LIMITS,
|
|
42
43
|
ENGINE_VERSION: () => ENGINE_VERSION,
|
|
43
44
|
FILE_TOOLS: () => FILE_TOOLS,
|
|
44
45
|
FLAGS_WITH_VALUES: () => FLAGS_WITH_VALUES,
|
|
@@ -715,6 +716,13 @@ function maskSecret(raw, pattern) {
|
|
|
715
716
|
var MAX_DEPTH = 5;
|
|
716
717
|
var MAX_STRING_BYTES = 1e5;
|
|
717
718
|
var MAX_JSON_PARSE_BYTES = 1e4;
|
|
719
|
+
var DLP_SCAN_LIMITS = {
|
|
720
|
+
/** Max characters examined per individual string field; the remainder of an
|
|
721
|
+
* oversized string is NOT scanned. */
|
|
722
|
+
maxStringBytes: MAX_STRING_BYTES,
|
|
723
|
+
/** Max nesting depth walked; anything deeper is NOT scanned. */
|
|
724
|
+
maxDepth: MAX_DEPTH
|
|
725
|
+
};
|
|
718
726
|
function scanArgs(args, depth = 0, fieldPath = "args") {
|
|
719
727
|
if (depth > MAX_DEPTH || args === null || args === void 0) return null;
|
|
720
728
|
if (Array.isArray(args)) {
|
|
@@ -1160,9 +1168,34 @@ var FS_READ_TOOLS = /* @__PURE__ */ new Set([
|
|
|
1160
1168
|
"vi",
|
|
1161
1169
|
"emacs",
|
|
1162
1170
|
"code",
|
|
1163
|
-
"type"
|
|
1171
|
+
"type",
|
|
1172
|
+
// — the 22 that were missing —
|
|
1173
|
+
"grep",
|
|
1174
|
+
"egrep",
|
|
1175
|
+
"fgrep",
|
|
1176
|
+
"rg",
|
|
1177
|
+
"ag",
|
|
1178
|
+
"ack",
|
|
1179
|
+
"awk",
|
|
1180
|
+
"gawk",
|
|
1181
|
+
"sed",
|
|
1182
|
+
"cut",
|
|
1183
|
+
"tr",
|
|
1184
|
+
"jq",
|
|
1185
|
+
"yq",
|
|
1186
|
+
"od",
|
|
1187
|
+
"xxd",
|
|
1188
|
+
"hexdump",
|
|
1189
|
+
"strings",
|
|
1190
|
+
"sort",
|
|
1191
|
+
"uniq",
|
|
1192
|
+
"tac",
|
|
1193
|
+
"nl",
|
|
1194
|
+
"dd"
|
|
1164
1195
|
]);
|
|
1165
|
-
var FS_OP_PRESCREEN_RE =
|
|
1196
|
+
var FS_OP_PRESCREEN_RE = new RegExp(
|
|
1197
|
+
`(?:^|[\\s|;&(\`\\n])(?:rm|${[...FS_READ_TOOLS].map((t) => t.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|")})\\b`
|
|
1198
|
+
);
|
|
1166
1199
|
var HOME_CACHE_ALLOWLIST = [
|
|
1167
1200
|
".cache",
|
|
1168
1201
|
".npm/_npx",
|
|
@@ -1201,9 +1234,37 @@ var SENSITIVE_PATH_RULES = [
|
|
|
1201
1234
|
// for the canonical test-asserted contract.
|
|
1202
1235
|
rule: "shield:project-jail:block-read-env",
|
|
1203
1236
|
reason: "Reading .env files is blocked by project-jail shield",
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1237
|
+
// Structural, not a list. The previous form enumerated seven suffixes and
|
|
1238
|
+
// anchored on `$`, so `.env.prod`, `.env.ci` and `.env.local.bak` — all
|
|
1239
|
+
// gitignored, all routinely holding real secrets — were never covered. A
|
|
1240
|
+
// hand-written list of what to protect is only ever as complete as the day
|
|
1241
|
+
// it was typed; this says "`.env` plus any suffix chain" and then names the
|
|
1242
|
+
// exceptions, which is the direction that fails safe.
|
|
1243
|
+
//
|
|
1244
|
+
// \.env the segment itself
|
|
1245
|
+
// (?![\w-]) a boundary, so `.environment` and `.envrc` are NOT .env
|
|
1246
|
+
// files. Without it a flat suffix class swallows both.
|
|
1247
|
+
// (?![\w-]) a boundary, so `.environment` and `.envrc` are NOT .env
|
|
1248
|
+
// [\w.-]*$ any suffix chain. Flat class, no nested quantifier —
|
|
1249
|
+
// `(\.[\w-]+)*` reads the same but is rejected by
|
|
1250
|
+
// safe-regex2, and this pattern runs on the hook hot path.
|
|
1251
|
+
//
|
|
1252
|
+
// The two exclusions are NOT the same shape, because the words do not mean
|
|
1253
|
+
// the same thing:
|
|
1254
|
+
//
|
|
1255
|
+
// (?!\.(?:example|sample|template)\b) — "this file is a fixture", and it
|
|
1256
|
+
// stays a fixture whatever follows, so `.env.example.md` is allowed too.
|
|
1257
|
+
// These are checked into git by convention: already public, so blocking
|
|
1258
|
+
// them buys nothing and costs the most common legitimate agent read.
|
|
1259
|
+
//
|
|
1260
|
+
// (?!\.test$) — anchored, because `test` names an ENVIRONMENT, not a
|
|
1261
|
+
// fixture. `.env.test` is the committed template and stays allowed, but
|
|
1262
|
+
// `.env.test.local` is gitignored by the `.env*.local` convention and
|
|
1263
|
+
// holds real values, so it must block. Using `\b` here — the obvious
|
|
1264
|
+
// symmetry — silently exempts every `.env.test.*` file.
|
|
1265
|
+
//
|
|
1266
|
+
// shields.test.ts:983-995 is the canonical contract; keep both in step.
|
|
1267
|
+
match: (p) => /(?:^|[\\/])\.env(?![\w-])(?!\.(?:example|sample|template)\b)(?!\.test$)[\w.-]*$/i.test(p)
|
|
1207
1268
|
},
|
|
1208
1269
|
{
|
|
1209
1270
|
// verdict: 'review' (not 'block') is a deliberate design choice
|
|
@@ -3917,8 +3978,8 @@ function detectArgsPii(args) {
|
|
|
3917
3978
|
|
|
3918
3979
|
// src/scan/canonical.ts
|
|
3919
3980
|
var LONG_OUTPUT_THRESHOLD_BYTES = 100 * 1024;
|
|
3920
|
-
var CANONICAL_EXTRACTOR_VERSION = "canonical-
|
|
3921
|
-
var CANONICAL_EXTRACTOR_HASH = "
|
|
3981
|
+
var CANONICAL_EXTRACTOR_VERSION = "canonical-v9";
|
|
3982
|
+
var CANONICAL_EXTRACTOR_HASH = "4ebf40dfe1d7c0a1";
|
|
3922
3983
|
var DEDUPE_PREVIEW_LEN = 120;
|
|
3923
3984
|
function extractCanonicalFindings(call, ctx) {
|
|
3924
3985
|
const out = [];
|
|
@@ -4276,6 +4337,7 @@ var ENGINE_VERSION = "1.4.0";
|
|
|
4276
4337
|
DEFAULT_EGRESS_ALLOWLIST,
|
|
4277
4338
|
DESTRUCTIVE_OP_RE,
|
|
4278
4339
|
DLP_PATTERNS,
|
|
4340
|
+
DLP_SCAN_LIMITS,
|
|
4279
4341
|
ENGINE_VERSION,
|
|
4280
4342
|
FILE_TOOLS,
|
|
4281
4343
|
FLAGS_WITH_VALUES,
|
package/dist/index.mjs
CHANGED
|
@@ -602,6 +602,13 @@ function maskSecret(raw, pattern) {
|
|
|
602
602
|
var MAX_DEPTH = 5;
|
|
603
603
|
var MAX_STRING_BYTES = 1e5;
|
|
604
604
|
var MAX_JSON_PARSE_BYTES = 1e4;
|
|
605
|
+
var DLP_SCAN_LIMITS = {
|
|
606
|
+
/** Max characters examined per individual string field; the remainder of an
|
|
607
|
+
* oversized string is NOT scanned. */
|
|
608
|
+
maxStringBytes: MAX_STRING_BYTES,
|
|
609
|
+
/** Max nesting depth walked; anything deeper is NOT scanned. */
|
|
610
|
+
maxDepth: MAX_DEPTH
|
|
611
|
+
};
|
|
605
612
|
function scanArgs(args, depth = 0, fieldPath = "args") {
|
|
606
613
|
if (depth > MAX_DEPTH || args === null || args === void 0) return null;
|
|
607
614
|
if (Array.isArray(args)) {
|
|
@@ -1047,9 +1054,34 @@ var FS_READ_TOOLS = /* @__PURE__ */ new Set([
|
|
|
1047
1054
|
"vi",
|
|
1048
1055
|
"emacs",
|
|
1049
1056
|
"code",
|
|
1050
|
-
"type"
|
|
1057
|
+
"type",
|
|
1058
|
+
// — the 22 that were missing —
|
|
1059
|
+
"grep",
|
|
1060
|
+
"egrep",
|
|
1061
|
+
"fgrep",
|
|
1062
|
+
"rg",
|
|
1063
|
+
"ag",
|
|
1064
|
+
"ack",
|
|
1065
|
+
"awk",
|
|
1066
|
+
"gawk",
|
|
1067
|
+
"sed",
|
|
1068
|
+
"cut",
|
|
1069
|
+
"tr",
|
|
1070
|
+
"jq",
|
|
1071
|
+
"yq",
|
|
1072
|
+
"od",
|
|
1073
|
+
"xxd",
|
|
1074
|
+
"hexdump",
|
|
1075
|
+
"strings",
|
|
1076
|
+
"sort",
|
|
1077
|
+
"uniq",
|
|
1078
|
+
"tac",
|
|
1079
|
+
"nl",
|
|
1080
|
+
"dd"
|
|
1051
1081
|
]);
|
|
1052
|
-
var FS_OP_PRESCREEN_RE =
|
|
1082
|
+
var FS_OP_PRESCREEN_RE = new RegExp(
|
|
1083
|
+
`(?:^|[\\s|;&(\`\\n])(?:rm|${[...FS_READ_TOOLS].map((t) => t.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|")})\\b`
|
|
1084
|
+
);
|
|
1053
1085
|
var HOME_CACHE_ALLOWLIST = [
|
|
1054
1086
|
".cache",
|
|
1055
1087
|
".npm/_npx",
|
|
@@ -1088,9 +1120,37 @@ var SENSITIVE_PATH_RULES = [
|
|
|
1088
1120
|
// for the canonical test-asserted contract.
|
|
1089
1121
|
rule: "shield:project-jail:block-read-env",
|
|
1090
1122
|
reason: "Reading .env files is blocked by project-jail shield",
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1123
|
+
// Structural, not a list. The previous form enumerated seven suffixes and
|
|
1124
|
+
// anchored on `$`, so `.env.prod`, `.env.ci` and `.env.local.bak` — all
|
|
1125
|
+
// gitignored, all routinely holding real secrets — were never covered. A
|
|
1126
|
+
// hand-written list of what to protect is only ever as complete as the day
|
|
1127
|
+
// it was typed; this says "`.env` plus any suffix chain" and then names the
|
|
1128
|
+
// exceptions, which is the direction that fails safe.
|
|
1129
|
+
//
|
|
1130
|
+
// \.env the segment itself
|
|
1131
|
+
// (?![\w-]) a boundary, so `.environment` and `.envrc` are NOT .env
|
|
1132
|
+
// files. Without it a flat suffix class swallows both.
|
|
1133
|
+
// (?![\w-]) a boundary, so `.environment` and `.envrc` are NOT .env
|
|
1134
|
+
// [\w.-]*$ any suffix chain. Flat class, no nested quantifier —
|
|
1135
|
+
// `(\.[\w-]+)*` reads the same but is rejected by
|
|
1136
|
+
// safe-regex2, and this pattern runs on the hook hot path.
|
|
1137
|
+
//
|
|
1138
|
+
// The two exclusions are NOT the same shape, because the words do not mean
|
|
1139
|
+
// the same thing:
|
|
1140
|
+
//
|
|
1141
|
+
// (?!\.(?:example|sample|template)\b) — "this file is a fixture", and it
|
|
1142
|
+
// stays a fixture whatever follows, so `.env.example.md` is allowed too.
|
|
1143
|
+
// These are checked into git by convention: already public, so blocking
|
|
1144
|
+
// them buys nothing and costs the most common legitimate agent read.
|
|
1145
|
+
//
|
|
1146
|
+
// (?!\.test$) — anchored, because `test` names an ENVIRONMENT, not a
|
|
1147
|
+
// fixture. `.env.test` is the committed template and stays allowed, but
|
|
1148
|
+
// `.env.test.local` is gitignored by the `.env*.local` convention and
|
|
1149
|
+
// holds real values, so it must block. Using `\b` here — the obvious
|
|
1150
|
+
// symmetry — silently exempts every `.env.test.*` file.
|
|
1151
|
+
//
|
|
1152
|
+
// shields.test.ts:983-995 is the canonical contract; keep both in step.
|
|
1153
|
+
match: (p) => /(?:^|[\\/])\.env(?![\w-])(?!\.(?:example|sample|template)\b)(?!\.test$)[\w.-]*$/i.test(p)
|
|
1094
1154
|
},
|
|
1095
1155
|
{
|
|
1096
1156
|
// verdict: 'review' (not 'block') is a deliberate design choice
|
|
@@ -3804,8 +3864,8 @@ function detectArgsPii(args) {
|
|
|
3804
3864
|
|
|
3805
3865
|
// src/scan/canonical.ts
|
|
3806
3866
|
var LONG_OUTPUT_THRESHOLD_BYTES = 100 * 1024;
|
|
3807
|
-
var CANONICAL_EXTRACTOR_VERSION = "canonical-
|
|
3808
|
-
var CANONICAL_EXTRACTOR_HASH = "
|
|
3867
|
+
var CANONICAL_EXTRACTOR_VERSION = "canonical-v9";
|
|
3868
|
+
var CANONICAL_EXTRACTOR_HASH = "4ebf40dfe1d7c0a1";
|
|
3809
3869
|
var DEDUPE_PREVIEW_LEN = 120;
|
|
3810
3870
|
function extractCanonicalFindings(call, ctx) {
|
|
3811
3871
|
const out = [];
|
|
@@ -4162,6 +4222,7 @@ export {
|
|
|
4162
4222
|
DEFAULT_EGRESS_ALLOWLIST,
|
|
4163
4223
|
DESTRUCTIVE_OP_RE,
|
|
4164
4224
|
DLP_PATTERNS,
|
|
4225
|
+
DLP_SCAN_LIMITS,
|
|
4165
4226
|
ENGINE_VERSION,
|
|
4166
4227
|
FILE_TOOLS,
|
|
4167
4228
|
FLAGS_WITH_VALUES,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@node9/policy-engine",
|
|
3
|
-
"version": "1.67.
|
|
3
|
+
"version": "1.67.4",
|
|
4
4
|
"description": "Shared policy evaluation engine for node9 — DLP, smart rules, AST shell parsing, shields, loop detection. Pure functions, no I/O. Used by both node9-proxy and the node9 SaaS firewall.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://node9.ai",
|