@node9/policy-engine 1.36.0 → 1.38.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/index.d.mts CHANGED
@@ -86,6 +86,26 @@ interface RiskMetadata {
86
86
  ruleDescription?: string;
87
87
  }
88
88
 
89
+ type InjectionConfidence = 'low' | 'medium' | 'high';
90
+ interface InjectionMatch {
91
+ /** Names of the matched signals (+ 'untrusted-origin' when applicable). */
92
+ signals: string[];
93
+ confidence: InjectionConfidence;
94
+ }
95
+ interface InjectionContext {
96
+ /** Tool that produced the output. Untrusted origins (web/network) raise
97
+ * confidence — a fetched page is attacker-influenceable; a local read isn't. */
98
+ tool?: string;
99
+ }
100
+ /**
101
+ * Scan tool output for indirect prompt injection. Returns the matched signals +
102
+ * a confidence, or null when nothing matched. Scoring: +1 per matched signal,
103
+ * +1 booster when the origin is an untrusted tool (booster needs ≥1 real
104
+ * signal). score 1 → low (a single phrase, e.g. a doc discussing injection);
105
+ * 2 → medium; 3+ → high. Callers should act only on medium+.
106
+ */
107
+ declare function scanInjection(text: string, ctx?: InjectionContext): InjectionMatch | null;
108
+
89
109
  interface DlpPattern {
90
110
  name: string;
91
111
  regex: RegExp;
@@ -1009,4 +1029,4 @@ declare function previewArgs(input: Record<string, unknown>, max: number): strin
1009
1029
  /** Engine version stamped on audit entries for future drift detection. */
1010
1030
  declare const ENGINE_VERSION = "1.4.0";
1011
1031
 
1012
- 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, 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, computeArgsHash, computeBlendedSecurityScore, computeScanScore, computeSecurityScore, dedupeCanonicalFindings, detectArgsPii, detectDangerousEval, detectDangerousShellExec, detectPii, evaluateEgress, evaluateLoopWindow, evaluatePolicy, evaluateSmartConditions, extractAllSshHosts, extractCanonicalFindings, extractNetworkTargets, extractPositionalArgs, extractSessionLevelFindings, extractShellDestinations, getCompiledRegex, getNestedValue, hostMatches, isBashTool, isIgnoredTool, isPrivateHost, isProtectedHomePath, isShieldVerdict, matchSensitivePath, matchesPattern, narrativeRuleLabel, normalizeCommandForPolicy, parseAllSshHostsFromCommand, parseDestHost, previewArgs, redactText, scanArgs, scanText, sensitivePathMatch, summarizeBlast, summarizeScan, toScanFinding, truncateBlastPath, validateOverrides, validateRegex, validateShieldDefinition };
1032
+ 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, computeArgsHash, computeBlendedSecurityScore, computeScanScore, computeSecurityScore, dedupeCanonicalFindings, detectArgsPii, detectDangerousEval, detectDangerousShellExec, detectPii, evaluateEgress, evaluateLoopWindow, evaluatePolicy, evaluateSmartConditions, extractAllSshHosts, extractCanonicalFindings, extractNetworkTargets, extractPositionalArgs, extractSessionLevelFindings, extractShellDestinations, getCompiledRegex, getNestedValue, hostMatches, isBashTool, isIgnoredTool, isPrivateHost, isProtectedHomePath, isShieldVerdict, matchSensitivePath, matchesPattern, narrativeRuleLabel, normalizeCommandForPolicy, parseAllSshHostsFromCommand, parseDestHost, previewArgs, redactText, scanArgs, scanInjection, scanText, sensitivePathMatch, summarizeBlast, summarizeScan, toScanFinding, truncateBlastPath, validateOverrides, validateRegex, validateShieldDefinition };
package/dist/index.d.ts CHANGED
@@ -86,6 +86,26 @@ interface RiskMetadata {
86
86
  ruleDescription?: string;
87
87
  }
88
88
 
89
+ type InjectionConfidence = 'low' | 'medium' | 'high';
90
+ interface InjectionMatch {
91
+ /** Names of the matched signals (+ 'untrusted-origin' when applicable). */
92
+ signals: string[];
93
+ confidence: InjectionConfidence;
94
+ }
95
+ interface InjectionContext {
96
+ /** Tool that produced the output. Untrusted origins (web/network) raise
97
+ * confidence — a fetched page is attacker-influenceable; a local read isn't. */
98
+ tool?: string;
99
+ }
100
+ /**
101
+ * Scan tool output for indirect prompt injection. Returns the matched signals +
102
+ * a confidence, or null when nothing matched. Scoring: +1 per matched signal,
103
+ * +1 booster when the origin is an untrusted tool (booster needs ≥1 real
104
+ * signal). score 1 → low (a single phrase, e.g. a doc discussing injection);
105
+ * 2 → medium; 3+ → high. Callers should act only on medium+.
106
+ */
107
+ declare function scanInjection(text: string, ctx?: InjectionContext): InjectionMatch | null;
108
+
89
109
  interface DlpPattern {
90
110
  name: string;
91
111
  regex: RegExp;
@@ -1009,4 +1029,4 @@ declare function previewArgs(input: Record<string, unknown>, max: number): strin
1009
1029
  /** Engine version stamped on audit entries for future drift detection. */
1010
1030
  declare const ENGINE_VERSION = "1.4.0";
1011
1031
 
1012
- 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, 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, computeArgsHash, computeBlendedSecurityScore, computeScanScore, computeSecurityScore, dedupeCanonicalFindings, detectArgsPii, detectDangerousEval, detectDangerousShellExec, detectPii, evaluateEgress, evaluateLoopWindow, evaluatePolicy, evaluateSmartConditions, extractAllSshHosts, extractCanonicalFindings, extractNetworkTargets, extractPositionalArgs, extractSessionLevelFindings, extractShellDestinations, getCompiledRegex, getNestedValue, hostMatches, isBashTool, isIgnoredTool, isPrivateHost, isProtectedHomePath, isShieldVerdict, matchSensitivePath, matchesPattern, narrativeRuleLabel, normalizeCommandForPolicy, parseAllSshHostsFromCommand, parseDestHost, previewArgs, redactText, scanArgs, scanText, sensitivePathMatch, summarizeBlast, summarizeScan, toScanFinding, truncateBlastPath, validateOverrides, validateRegex, validateShieldDefinition };
1032
+ 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, computeArgsHash, computeBlendedSecurityScore, computeScanScore, computeSecurityScore, dedupeCanonicalFindings, detectArgsPii, detectDangerousEval, detectDangerousShellExec, detectPii, evaluateEgress, evaluateLoopWindow, evaluatePolicy, evaluateSmartConditions, extractAllSshHosts, extractCanonicalFindings, extractNetworkTargets, extractPositionalArgs, extractSessionLevelFindings, extractShellDestinations, getCompiledRegex, getNestedValue, hostMatches, isBashTool, isIgnoredTool, isPrivateHost, isProtectedHomePath, isShieldVerdict, matchSensitivePath, matchesPattern, narrativeRuleLabel, normalizeCommandForPolicy, parseAllSshHostsFromCommand, parseDestHost, previewArgs, redactText, scanArgs, scanInjection, scanText, sensitivePathMatch, summarizeBlast, summarizeScan, toScanFinding, truncateBlastPath, validateOverrides, validateRegex, validateShieldDefinition };
package/dist/index.js CHANGED
@@ -93,6 +93,7 @@ __export(src_exports, {
93
93
  previewArgs: () => previewArgs,
94
94
  redactText: () => redactText,
95
95
  scanArgs: () => scanArgs,
96
+ scanInjection: () => scanInjection,
96
97
  scanText: () => scanText,
97
98
  sensitivePathMatch: () => sensitivePathMatch,
98
99
  summarizeBlast: () => summarizeBlast,
@@ -107,6 +108,59 @@ module.exports = __toCommonJS(src_exports);
107
108
 
108
109
  // src/dlp/index.ts
109
110
  var import_safe_regex2 = __toESM(require("safe-regex2"));
111
+
112
+ // src/dlp/injection.ts
113
+ var MAX = 1e5;
114
+ var UNTRUSTED_TOOLS = /\b(web_?fetch|web_?search|fetch|curl|wget|browser|http_get|read_url|open_url)\b/i;
115
+ var SIGNALS = [
116
+ {
117
+ name: "override-instructions",
118
+ any: [
119
+ // "ignore/disregard/forget ... (previous|all|the|your) ... instructions/prompt/rules"
120
+ /\b(ignore|disregard|forget)\b[^.!?\n]{0,40}\b(previous|prior|earlier|above|all|the|your)\b[^.!?\n]{0,24}\b(instruction|instructions|prompt|context|rules?|directives?)\b/i,
121
+ /\byou are now\b/i,
122
+ /\bnew instructions?\s*:/i,
123
+ /\bdeveloper mode\b/i,
124
+ /\bignore (the )?system prompt\b/i,
125
+ /\b(do not|don'?t|never)\b[^.!?\n]{0,20}\btell the (user|human)\b/i,
126
+ /\boverride (your|the)\b[^.!?\n]{0,20}\b(instruction|instructions|programming|rules?|guardrails?)\b/i
127
+ ]
128
+ },
129
+ {
130
+ name: "fake-role-marker",
131
+ any: [
132
+ /^\s*(system|assistant)\s*:/im,
133
+ // a line impersonating a conversation turn
134
+ /<\/?system>/i,
135
+ /\[\/?INST\]/i,
136
+ /<\|im_(start|end)\|>/i
137
+ ]
138
+ },
139
+ {
140
+ name: "action-to-destination",
141
+ any: [
142
+ // exfil verb + to/at + a url / email / domain
143
+ /\b(send|post|upload|exfiltrate|email|curl|wget|leak)\b[^.\n]{0,40}\b(to|at)\b[^.\n]{0,24}(https?:\/\/|[\w.-]+@[\w.-]+|[\w-]+\.[a-z]{2,})/i,
144
+ /\brun (the )?following (command|code|script)\b/i,
145
+ /\bexecute (this|the following)\b/i
146
+ ]
147
+ }
148
+ ];
149
+ function scanInjection(text, ctx = {}) {
150
+ if (!text) return null;
151
+ const t = text.length > MAX ? text.slice(0, MAX) : text;
152
+ const matched = [];
153
+ for (const sig of SIGNALS) {
154
+ if (sig.any.some((re) => re.test(t))) matched.push(sig.name);
155
+ }
156
+ if (matched.length === 0) return null;
157
+ const untrusted = !!ctx.tool && UNTRUSTED_TOOLS.test(ctx.tool);
158
+ const score = matched.length + (untrusted ? 1 : 0);
159
+ const confidence = score >= 3 ? "high" : score === 2 ? "medium" : "low";
160
+ return { signals: untrusted ? [...matched, "untrusted-origin"] : matched, confidence };
161
+ }
162
+
163
+ // src/dlp/index.ts
110
164
  var ASSIGNMENT_CONTEXT_RE = /\b(?:password|passwd|secret|token|api[_-]?key|auth(?:_key|_token)?|credential|private[_-]?key|access[_-]?key|client[_-]?secret)\s*[=:]\s*/i;
111
165
  function isAssignmentContext(text) {
112
166
  return ASSIGNMENT_CONTEXT_RE.test(text);
@@ -3804,6 +3858,7 @@ var ENGINE_VERSION = "1.4.0";
3804
3858
  previewArgs,
3805
3859
  redactText,
3806
3860
  scanArgs,
3861
+ scanInjection,
3807
3862
  scanText,
3808
3863
  sensitivePathMatch,
3809
3864
  summarizeBlast,
package/dist/index.mjs CHANGED
@@ -1,5 +1,58 @@
1
1
  // src/dlp/index.ts
2
2
  import safeRegex from "safe-regex2";
3
+
4
+ // src/dlp/injection.ts
5
+ var MAX = 1e5;
6
+ var UNTRUSTED_TOOLS = /\b(web_?fetch|web_?search|fetch|curl|wget|browser|http_get|read_url|open_url)\b/i;
7
+ var SIGNALS = [
8
+ {
9
+ name: "override-instructions",
10
+ any: [
11
+ // "ignore/disregard/forget ... (previous|all|the|your) ... instructions/prompt/rules"
12
+ /\b(ignore|disregard|forget)\b[^.!?\n]{0,40}\b(previous|prior|earlier|above|all|the|your)\b[^.!?\n]{0,24}\b(instruction|instructions|prompt|context|rules?|directives?)\b/i,
13
+ /\byou are now\b/i,
14
+ /\bnew instructions?\s*:/i,
15
+ /\bdeveloper mode\b/i,
16
+ /\bignore (the )?system prompt\b/i,
17
+ /\b(do not|don'?t|never)\b[^.!?\n]{0,20}\btell the (user|human)\b/i,
18
+ /\boverride (your|the)\b[^.!?\n]{0,20}\b(instruction|instructions|programming|rules?|guardrails?)\b/i
19
+ ]
20
+ },
21
+ {
22
+ name: "fake-role-marker",
23
+ any: [
24
+ /^\s*(system|assistant)\s*:/im,
25
+ // a line impersonating a conversation turn
26
+ /<\/?system>/i,
27
+ /\[\/?INST\]/i,
28
+ /<\|im_(start|end)\|>/i
29
+ ]
30
+ },
31
+ {
32
+ name: "action-to-destination",
33
+ any: [
34
+ // exfil verb + to/at + a url / email / domain
35
+ /\b(send|post|upload|exfiltrate|email|curl|wget|leak)\b[^.\n]{0,40}\b(to|at)\b[^.\n]{0,24}(https?:\/\/|[\w.-]+@[\w.-]+|[\w-]+\.[a-z]{2,})/i,
36
+ /\brun (the )?following (command|code|script)\b/i,
37
+ /\bexecute (this|the following)\b/i
38
+ ]
39
+ }
40
+ ];
41
+ function scanInjection(text, ctx = {}) {
42
+ if (!text) return null;
43
+ const t = text.length > MAX ? text.slice(0, MAX) : text;
44
+ const matched = [];
45
+ for (const sig of SIGNALS) {
46
+ if (sig.any.some((re) => re.test(t))) matched.push(sig.name);
47
+ }
48
+ if (matched.length === 0) return null;
49
+ const untrusted = !!ctx.tool && UNTRUSTED_TOOLS.test(ctx.tool);
50
+ const score = matched.length + (untrusted ? 1 : 0);
51
+ const confidence = score >= 3 ? "high" : score === 2 ? "medium" : "low";
52
+ return { signals: untrusted ? [...matched, "untrusted-origin"] : matched, confidence };
53
+ }
54
+
55
+ // src/dlp/index.ts
3
56
  var ASSIGNMENT_CONTEXT_RE = /\b(?:password|passwd|secret|token|api[_-]?key|auth(?:_key|_token)?|credential|private[_-]?key|access[_-]?key|client[_-]?secret)\s*[=:]\s*/i;
4
57
  function isAssignmentContext(text) {
5
58
  return ASSIGNMENT_CONTEXT_RE.test(text);
@@ -3696,6 +3749,7 @@ export {
3696
3749
  previewArgs,
3697
3750
  redactText,
3698
3751
  scanArgs,
3752
+ scanInjection,
3699
3753
  scanText,
3700
3754
  sensitivePathMatch,
3701
3755
  summarizeBlast,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@node9/policy-engine",
3
- "version": "1.36.0",
3
+ "version": "1.38.0",
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",