@surfinguard/core-engine 0.1.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.
Files changed (64) hide show
  1. package/README.md +65 -0
  2. package/dist/analyzers/base.d.ts +38 -0
  3. package/dist/analyzers/base.d.ts.map +1 -0
  4. package/dist/analyzers/base.js +2 -0
  5. package/dist/analyzers/base.js.map +1 -0
  6. package/dist/analyzers/command.d.ts +44 -0
  7. package/dist/analyzers/command.d.ts.map +1 -0
  8. package/dist/analyzers/command.js +544 -0
  9. package/dist/analyzers/command.js.map +1 -0
  10. package/dist/analyzers/file-read.d.ts +31 -0
  11. package/dist/analyzers/file-read.d.ts.map +1 -0
  12. package/dist/analyzers/file-read.js +159 -0
  13. package/dist/analyzers/file-read.js.map +1 -0
  14. package/dist/analyzers/file-write.d.ts +32 -0
  15. package/dist/analyzers/file-write.d.ts.map +1 -0
  16. package/dist/analyzers/file-write.js +177 -0
  17. package/dist/analyzers/file-write.js.map +1 -0
  18. package/dist/analyzers/index.d.ts +7 -0
  19. package/dist/analyzers/index.d.ts.map +1 -0
  20. package/dist/analyzers/index.js +6 -0
  21. package/dist/analyzers/index.js.map +1 -0
  22. package/dist/analyzers/text.d.ts +30 -0
  23. package/dist/analyzers/text.d.ts.map +1 -0
  24. package/dist/analyzers/text.js +139 -0
  25. package/dist/analyzers/text.js.map +1 -0
  26. package/dist/analyzers/url.d.ts +33 -0
  27. package/dist/analyzers/url.d.ts.map +1 -0
  28. package/dist/analyzers/url.js +325 -0
  29. package/dist/analyzers/url.js.map +1 -0
  30. package/dist/classifier.d.ts +7 -0
  31. package/dist/classifier.d.ts.map +1 -0
  32. package/dist/classifier.js +12 -0
  33. package/dist/classifier.js.map +1 -0
  34. package/dist/context.d.ts +10 -0
  35. package/dist/context.d.ts.map +1 -0
  36. package/dist/context.js +9 -0
  37. package/dist/context.js.map +1 -0
  38. package/dist/engine.d.ts +49 -0
  39. package/dist/engine.d.ts.map +1 -0
  40. package/dist/engine.js +122 -0
  41. package/dist/engine.js.map +1 -0
  42. package/dist/index.d.ts +12 -0
  43. package/dist/index.d.ts.map +1 -0
  44. package/dist/index.js +10 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/patterns.d.ts +8 -0
  47. package/dist/patterns.d.ts.map +1 -0
  48. package/dist/patterns.js +66 -0
  49. package/dist/patterns.js.map +1 -0
  50. package/dist/scorer.d.ts +23 -0
  51. package/dist/scorer.d.ts.map +1 -0
  52. package/dist/scorer.js +52 -0
  53. package/dist/scorer.js.map +1 -0
  54. package/dist/verdict.d.ts +7 -0
  55. package/dist/verdict.d.ts.map +1 -0
  56. package/dist/verdict.js +41 -0
  57. package/dist/verdict.js.map +1 -0
  58. package/package.json +44 -0
  59. package/patterns/brands.json +205 -0
  60. package/patterns/commands.json +44 -0
  61. package/patterns/file-read.json +85 -0
  62. package/patterns/file-write.json +100 -0
  63. package/patterns/text.json +190 -0
  64. package/patterns/urls.json +412 -0
@@ -0,0 +1,159 @@
1
+ /**
2
+ * File Read Analyzer — sensitive file read detection.
3
+ *
4
+ * Detects 10 threat patterns (FR01-FR10) mapped to the EXFILTRATION primitive.
5
+ */
6
+ export class FileReadAnalyzer {
7
+ actionType = 'file_read';
8
+ db;
9
+ safePathPrefixes;
10
+ safeExtensions;
11
+ constructor(patterns) {
12
+ this.db = patterns;
13
+ this.safePathPrefixes = patterns.safePaths;
14
+ this.safeExtensions = new Set(patterns.safeExtensions);
15
+ }
16
+ analyze(value) {
17
+ const rawPath = value.trim();
18
+ if (!rawPath) {
19
+ return { actionType: 'file_read', findings: [], shortCircuit: { safe: true, reason: 'Empty path' } };
20
+ }
21
+ const normalized = this.normalizePath(rawPath);
22
+ const findings = [];
23
+ const add = (score, reason, threatId) => {
24
+ findings.push({ primitive: 'EXFILTRATION', score, reason, threatId });
25
+ };
26
+ // ── Short-circuit safe ─────────────────────────────────────────────
27
+ if (this.isSafePath(normalized, rawPath)) {
28
+ return { actionType: 'file_read', findings: [], shortCircuit: { safe: true, reason: 'Known safe path' } };
29
+ }
30
+ // ── Critical paths (score 8-9, FR01-FR02) ──────────────────────────
31
+ for (const entry of this.db.criticalPaths) {
32
+ if (this.matchPath(normalized, rawPath, entry)) {
33
+ add(entry.score, entry.reason, entry.threatId);
34
+ }
35
+ }
36
+ // ── High paths (score 5-8, FR04-FR06) ──────────────────────────────
37
+ for (const entry of this.db.highPaths) {
38
+ if (this.matchPath(normalized, rawPath, entry)) {
39
+ add(entry.score, entry.reason, entry.threatId);
40
+ }
41
+ }
42
+ // ── Medium paths (score 3-5, FR07-FR09) ────────────────────────────
43
+ for (const entry of this.db.mediumPaths) {
44
+ if (this.matchPath(normalized, rawPath, entry)) {
45
+ add(entry.score, entry.reason, entry.threatId);
46
+ }
47
+ }
48
+ // ── Sensitive extensions (FR03) ────────────────────────────────────
49
+ if (!findings.some((f) => f.threatId === 'FR03')) {
50
+ for (const entry of this.db.sensitiveExtensions) {
51
+ if (this.matchExtension(rawPath, entry)) {
52
+ add(entry.score, entry.reason, entry.threatId);
53
+ break;
54
+ }
55
+ }
56
+ }
57
+ // ── Browser data paths (FR10) ──────────────────────────────────────
58
+ for (const entry of this.db.browserDataPaths) {
59
+ if (this.matchPath(normalized, rawPath, entry)) {
60
+ add(entry.score, entry.reason, entry.threatId);
61
+ break;
62
+ }
63
+ }
64
+ return { actionType: 'file_read', findings };
65
+ }
66
+ // ── Path Helpers ──────────────────────────────────────────────────────
67
+ /**
68
+ * Normalize path: expand ~ to /HOME/, resolve ..
69
+ */
70
+ normalizePath(path) {
71
+ let p = path;
72
+ // Expand ~ to /HOME/
73
+ if (p.startsWith('~/')) {
74
+ p = '/HOME/' + p.slice(2);
75
+ }
76
+ else if (p === '~') {
77
+ p = '/HOME/';
78
+ }
79
+ // Resolve .. segments
80
+ const parts = p.split('/');
81
+ const resolved = [];
82
+ for (const part of parts) {
83
+ if (part === '..') {
84
+ resolved.pop();
85
+ }
86
+ else if (part !== '.') {
87
+ resolved.push(part);
88
+ }
89
+ }
90
+ return resolved.join('/');
91
+ }
92
+ /**
93
+ * Check if a path matches a safe path prefix or has a safe extension.
94
+ */
95
+ isSafePath(normalized, rawPath) {
96
+ const ext = this.getExtension(rawPath);
97
+ if (ext && this.safeExtensions.has(ext)) {
98
+ // Also check it's not in a sensitive directory
99
+ const isSensitiveDir = normalized.includes('/HOME/.ssh/') ||
100
+ normalized.includes('/HOME/.aws/') ||
101
+ normalized.includes('/HOME/.docker/') ||
102
+ normalized.includes('/HOME/.kube/') ||
103
+ normalized.includes('/HOME/.azure/') ||
104
+ normalized.includes('/HOME/.config/gcloud/') ||
105
+ normalized.includes('/HOME/.gnupg/') ||
106
+ normalized.startsWith('/etc/');
107
+ if (!isSensitiveDir)
108
+ return true;
109
+ }
110
+ // Check safe path prefixes
111
+ const basename = this.getBasename(rawPath);
112
+ for (const safePrefix of this.safePathPrefixes) {
113
+ if (safePrefix.endsWith('/')) {
114
+ // Directory prefix check
115
+ if (normalized.includes(safePrefix) || rawPath.includes(safePrefix))
116
+ return true;
117
+ }
118
+ else {
119
+ // Basename check
120
+ if (basename === safePrefix || rawPath === safePrefix)
121
+ return true;
122
+ }
123
+ }
124
+ return false;
125
+ }
126
+ /**
127
+ * Match a path against a pattern entry based on matchType.
128
+ */
129
+ matchPath(normalized, rawPath, entry) {
130
+ const normalizedPattern = this.normalizePath(entry.pattern);
131
+ const matchType = entry.matchType || 'prefix';
132
+ switch (matchType) {
133
+ case 'exact':
134
+ return normalized === normalizedPattern || rawPath === entry.pattern;
135
+ case 'prefix':
136
+ return normalized.startsWith(normalizedPattern) || rawPath.startsWith(entry.pattern);
137
+ case 'basename':
138
+ return this.getBasename(rawPath) === entry.pattern || this.getBasename(normalized) === entry.pattern;
139
+ case 'contains':
140
+ return normalized.includes(normalizedPattern) || rawPath.includes(entry.pattern);
141
+ default:
142
+ return normalized.startsWith(normalizedPattern);
143
+ }
144
+ }
145
+ matchExtension(path, entry) {
146
+ return path.toLowerCase().endsWith(entry.extension);
147
+ }
148
+ getExtension(path) {
149
+ const lastDot = path.lastIndexOf('.');
150
+ if (lastDot === -1 || lastDot === path.length - 1)
151
+ return '';
152
+ return path.slice(lastDot).toLowerCase();
153
+ }
154
+ getBasename(path) {
155
+ const parts = path.split('/');
156
+ return parts[parts.length - 1] || parts[parts.length - 2] || '';
157
+ }
158
+ }
159
+ //# sourceMappingURL=file-read.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-read.js","sourceRoot":"","sources":["../../src/analyzers/file-read.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import type { FileWritePatternDatabase } from '@surfinguard/types';
2
+ import type { Analyzer, AnalyzerResult } from './base.js';
3
+ /**
4
+ * File Write Analyzer — dangerous file write detection.
5
+ *
6
+ * Detects 12 threat patterns (FW01-FW12) mapped to DESTRUCTION, ESCALATION, and PERSISTENCE.
7
+ * Supports both path-only and path+content analysis.
8
+ */
9
+ export declare class FileWriteAnalyzer implements Analyzer {
10
+ readonly actionType: "file_write";
11
+ private readonly db;
12
+ private readonly safeExtensions;
13
+ private readonly safeDirectories;
14
+ constructor(patterns: FileWritePatternDatabase);
15
+ /**
16
+ * Path-only analysis (satisfies base Analyzer interface).
17
+ */
18
+ analyze(value: string): AnalyzerResult;
19
+ /**
20
+ * Combined path + content analysis.
21
+ */
22
+ analyzeWithContent(path: string, content?: string): AnalyzerResult;
23
+ private normalizePath;
24
+ private isSafePath;
25
+ private isInSafeDirectory;
26
+ private matchPath;
27
+ private matchContent;
28
+ private getExtension;
29
+ private getBasename;
30
+ private isExecutableExtension;
31
+ }
32
+ //# sourceMappingURL=file-write.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-write.d.ts","sourceRoot":"","sources":["../../src/analyzers/file-write.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAA0D,MAAM,oBAAoB,CAAC;AAC3H,OAAO,KAAK,EAAE,QAAQ,EAAmB,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3E;;;;;GAKG;AACH,qBAAa,iBAAkB,YAAW,QAAQ;IAChD,QAAQ,CAAC,UAAU,EAAG,YAAY,CAAU;IAE5C,OAAO,CAAC,QAAQ,CAAC,EAAE,CAA2B;IAC9C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAc;IAC7C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAW;gBAE/B,QAAQ,EAAE,wBAAwB;IAM9C;;OAEG;IACH,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc;IAItC;;OAEG;IACH,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,cAAc;IA0FlE,OAAO,CAAC,aAAa;IAmBrB,OAAO,CAAC,UAAU;IAQlB,OAAO,CAAC,iBAAiB;IAOzB,OAAO,CAAC,SAAS;IAkBjB,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,WAAW;IAKnB,OAAO,CAAC,qBAAqB;CAG9B"}
@@ -0,0 +1,177 @@
1
+ /**
2
+ * File Write Analyzer — dangerous file write detection.
3
+ *
4
+ * Detects 12 threat patterns (FW01-FW12) mapped to DESTRUCTION, ESCALATION, and PERSISTENCE.
5
+ * Supports both path-only and path+content analysis.
6
+ */
7
+ export class FileWriteAnalyzer {
8
+ actionType = 'file_write';
9
+ db;
10
+ safeExtensions;
11
+ safeDirectories;
12
+ constructor(patterns) {
13
+ this.db = patterns;
14
+ this.safeExtensions = new Set(patterns.safeExtensions);
15
+ this.safeDirectories = patterns.safeDirectories;
16
+ }
17
+ /**
18
+ * Path-only analysis (satisfies base Analyzer interface).
19
+ */
20
+ analyze(value) {
21
+ return this.analyzeWithContent(value);
22
+ }
23
+ /**
24
+ * Combined path + content analysis.
25
+ */
26
+ analyzeWithContent(path, content) {
27
+ const rawPath = path.trim();
28
+ if (!rawPath) {
29
+ return { actionType: 'file_write', findings: [], shortCircuit: { safe: true, reason: 'Empty path' } };
30
+ }
31
+ const normalized = this.normalizePath(rawPath);
32
+ const findings = [];
33
+ const add = (primitive, score, reason, threatId) => {
34
+ findings.push({ primitive, score, reason, threatId });
35
+ };
36
+ // ── Short-circuit safe ─────────────────────────────────────────────
37
+ if (!content && this.isSafePath(normalized, rawPath)) {
38
+ return { actionType: 'file_write', findings: [], shortCircuit: { safe: true, reason: 'Known safe path' } };
39
+ }
40
+ // ── Path analysis ──────────────────────────────────────────────────
41
+ // Critical paths (FW01-FW03)
42
+ for (const entry of this.db.criticalPaths) {
43
+ if (this.matchPath(normalized, rawPath, entry)) {
44
+ add(entry.primitive, entry.score, entry.reason, entry.threatId);
45
+ }
46
+ }
47
+ // Persistence paths (FW04-FW06, FW10)
48
+ for (const entry of this.db.persistencePaths) {
49
+ if (this.matchPath(normalized, rawPath, entry)) {
50
+ add(entry.primitive, entry.score, entry.reason, entry.threatId);
51
+ }
52
+ }
53
+ // Shell config paths (FW07)
54
+ for (const entry of this.db.shellConfigPaths) {
55
+ if (this.matchPath(normalized, rawPath, entry)) {
56
+ add(entry.primitive, entry.score, entry.reason, entry.threatId);
57
+ }
58
+ }
59
+ // Build config paths (FW08)
60
+ for (const entry of this.db.buildConfigPaths) {
61
+ if (this.matchPath(normalized, rawPath, entry)) {
62
+ add(entry.primitive, entry.score, entry.reason, entry.threatId);
63
+ }
64
+ }
65
+ // Credential paths (FW09)
66
+ for (const entry of this.db.credentialPaths) {
67
+ if (this.matchPath(normalized, rawPath, entry)) {
68
+ add(entry.primitive, entry.score, entry.reason, entry.threatId);
69
+ }
70
+ }
71
+ // ── Content analysis ───────────────────────────────────────────────
72
+ if (content) {
73
+ // Check if writing package.json with lifecycle scripts
74
+ const basename = this.getBasename(rawPath);
75
+ if (basename === 'package.json') {
76
+ const contentLower = content.toLowerCase();
77
+ for (const entry of this.db.packageJsonScriptPatterns) {
78
+ if (contentLower.includes(entry.pattern)) {
79
+ add(entry.primitive, entry.score, entry.reason, entry.threatId);
80
+ break;
81
+ }
82
+ }
83
+ }
84
+ // Check dangerous content patterns
85
+ for (const entry of this.db.dangerousContentPatterns) {
86
+ if (this.matchContent(content, entry)) {
87
+ add(entry.primitive, entry.score, entry.reason, entry.threatId);
88
+ }
89
+ }
90
+ }
91
+ // ── Executable extension outside safe dirs (FW11) ──────────────────
92
+ if (findings.length === 0) {
93
+ const ext = this.getExtension(rawPath);
94
+ if (this.isExecutableExtension(ext) && !this.isInSafeDirectory(normalized, rawPath)) {
95
+ add('ESCALATION', 2, 'Executable file creation outside safe directories', 'FW11');
96
+ }
97
+ }
98
+ return { actionType: 'file_write', findings };
99
+ }
100
+ // ── Path Helpers ──────────────────────────────────────────────────────
101
+ normalizePath(path) {
102
+ let p = path;
103
+ if (p.startsWith('~/')) {
104
+ p = '/HOME/' + p.slice(2);
105
+ }
106
+ else if (p === '~') {
107
+ p = '/HOME/';
108
+ }
109
+ const parts = p.split('/');
110
+ const resolved = [];
111
+ for (const part of parts) {
112
+ if (part === '..') {
113
+ resolved.pop();
114
+ }
115
+ else if (part !== '.') {
116
+ resolved.push(part);
117
+ }
118
+ }
119
+ return resolved.join('/');
120
+ }
121
+ isSafePath(normalized, rawPath) {
122
+ const ext = this.getExtension(rawPath);
123
+ if (ext && this.safeExtensions.has(ext) && this.isInSafeDirectory(normalized, rawPath)) {
124
+ return true;
125
+ }
126
+ return false;
127
+ }
128
+ isInSafeDirectory(normalized, rawPath) {
129
+ for (const dir of this.safeDirectories) {
130
+ if (normalized.includes(dir) || rawPath.includes(dir))
131
+ return true;
132
+ }
133
+ return false;
134
+ }
135
+ matchPath(normalized, rawPath, entry) {
136
+ const normalizedPattern = this.normalizePath(entry.pattern);
137
+ const matchType = entry.matchType || 'prefix';
138
+ switch (matchType) {
139
+ case 'exact':
140
+ return normalized === normalizedPattern || rawPath === entry.pattern;
141
+ case 'prefix':
142
+ return normalized.startsWith(normalizedPattern) || rawPath.startsWith(entry.pattern);
143
+ case 'basename':
144
+ return this.getBasename(rawPath) === entry.pattern || this.getBasename(normalized) === entry.pattern;
145
+ case 'contains':
146
+ return normalized.includes(normalizedPattern) || rawPath.includes(entry.pattern);
147
+ default:
148
+ return normalized.startsWith(normalizedPattern);
149
+ }
150
+ }
151
+ matchContent(content, entry) {
152
+ if (entry.isRegex) {
153
+ try {
154
+ return new RegExp(entry.pattern, 'i').test(content);
155
+ }
156
+ catch {
157
+ return content.toLowerCase().includes(entry.pattern.toLowerCase());
158
+ }
159
+ }
160
+ return content.includes(entry.pattern);
161
+ }
162
+ getExtension(path) {
163
+ const basename = this.getBasename(path);
164
+ const lastDot = basename.lastIndexOf('.');
165
+ if (lastDot === -1 || lastDot === basename.length - 1)
166
+ return '';
167
+ return basename.slice(lastDot).toLowerCase();
168
+ }
169
+ getBasename(path) {
170
+ const parts = path.split('/');
171
+ return parts[parts.length - 1] || parts[parts.length - 2] || '';
172
+ }
173
+ isExecutableExtension(ext) {
174
+ return ['.sh', '.bash', '.bat', '.cmd', '.ps1', '.exe', '.com', '.msi'].includes(ext);
175
+ }
176
+ }
177
+ //# sourceMappingURL=file-write.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-write.js","sourceRoot":"","sources":["../../src/analyzers/file-write.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export type { Analyzer, AnalyzerFinding, AnalyzerResult } from './base.js';
2
+ export { UrlAnalyzer } from './url.js';
3
+ export { CommandAnalyzer } from './command.js';
4
+ export { TextAnalyzer } from './text.js';
5
+ export { FileReadAnalyzer } from './file-read.js';
6
+ export { FileWriteAnalyzer } from './file-write.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/analyzers/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,QAAQ,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3E,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,6 @@
1
+ export { UrlAnalyzer } from './url.js';
2
+ export { CommandAnalyzer } from './command.js';
3
+ export { TextAnalyzer } from './text.js';
4
+ export { FileReadAnalyzer } from './file-read.js';
5
+ export { FileWriteAnalyzer } from './file-write.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/analyzers/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,30 @@
1
+ import type { TextPatternDatabase } from '@surfinguard/types';
2
+ import type { Analyzer, AnalyzerResult } from './base.js';
3
+ /**
4
+ * Text Analyzer — prompt injection and text manipulation detection.
5
+ *
6
+ * Detects 12 threat patterns (P01-P12) mapped to 4 risk primitives.
7
+ */
8
+ export declare class TextAnalyzer implements Analyzer {
9
+ readonly actionType: "text";
10
+ private readonly safePatterns;
11
+ private readonly directInjectionPatterns;
12
+ private readonly goalHijackingPatterns;
13
+ private readonly personaHijackingPatterns;
14
+ private readonly toolManipulationPatterns;
15
+ private readonly toolManipulationRegexes;
16
+ private readonly exfiltrationRequestPatterns;
17
+ private readonly encodingEvasionPatterns;
18
+ private readonly contextPoisoningIndicators;
19
+ private readonly markupInjectionPatterns;
20
+ private readonly delayedTriggerPatterns;
21
+ private readonly systemPromptIndicators;
22
+ constructor(patterns: TextPatternDatabase);
23
+ analyze(value: string): AnalyzerResult;
24
+ /**
25
+ * Detect instruction keywords written in non-Latin scripts.
26
+ * Looks for CJK, Cyrillic, Arabic characters near instruction-like patterns.
27
+ */
28
+ private hasNonLatinInstructions;
29
+ }
30
+ //# sourceMappingURL=text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../src/analyzers/text.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,KAAK,EAAE,QAAQ,EAAmB,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3E;;;;GAIG;AACH,qBAAa,YAAa,YAAW,QAAQ;IAC3C,QAAQ,CAAC,UAAU,EAAG,MAAM,CAAU;IAEtC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAW;IACxC,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAW;IACnD,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAW;IACjD,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAAW;IACpD,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAAW;IACpD,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAW;IACnD,OAAO,CAAC,QAAQ,CAAC,2BAA2B,CAAW;IACvD,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAW;IACnD,OAAO,CAAC,QAAQ,CAAC,0BAA0B,CAAW;IACtD,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAW;IACnD,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAW;IAClD,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAW;gBAEtC,QAAQ,EAAE,mBAAmB;IA6BzC,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc;IA2FtC;;;OAGG;IACH,OAAO,CAAC,uBAAuB;CAUhC"}
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Text Analyzer — prompt injection and text manipulation detection.
3
+ *
4
+ * Detects 12 threat patterns (P01-P12) mapped to 4 risk primitives.
5
+ */
6
+ export class TextAnalyzer {
7
+ actionType = 'text';
8
+ safePatterns;
9
+ directInjectionPatterns;
10
+ goalHijackingPatterns;
11
+ personaHijackingPatterns;
12
+ toolManipulationPatterns;
13
+ toolManipulationRegexes;
14
+ exfiltrationRequestPatterns;
15
+ encodingEvasionPatterns;
16
+ contextPoisoningIndicators;
17
+ markupInjectionPatterns;
18
+ delayedTriggerPatterns;
19
+ systemPromptIndicators;
20
+ constructor(patterns) {
21
+ // Pre-lowercase all string patterns for O(1) matching
22
+ this.safePatterns = patterns.safePatterns.map((p) => p.toLowerCase());
23
+ this.directInjectionPatterns = patterns.directInjectionPatterns.map((p) => p.toLowerCase());
24
+ this.goalHijackingPatterns = patterns.goalHijackingPatterns.map((p) => p.toLowerCase());
25
+ this.personaHijackingPatterns = patterns.personaHijackingPatterns.map((p) => p.toLowerCase());
26
+ this.exfiltrationRequestPatterns = patterns.exfiltrationRequestPatterns.map((p) => p.toLowerCase());
27
+ this.encodingEvasionPatterns = patterns.encodingEvasionPatterns.map((p) => p.toLowerCase());
28
+ this.contextPoisoningIndicators = patterns.contextPoisoningIndicators.map((p) => p.toLowerCase());
29
+ this.markupInjectionPatterns = patterns.markupInjectionPatterns.map((p) => p.toLowerCase());
30
+ this.delayedTriggerPatterns = patterns.delayedTriggerPatterns.map((p) => p.toLowerCase());
31
+ this.systemPromptIndicators = patterns.systemPromptIndicators.map((p) => p.toLowerCase());
32
+ // Separate regex patterns from plain string patterns for tool manipulation
33
+ this.toolManipulationPatterns = [];
34
+ this.toolManipulationRegexes = [];
35
+ for (const p of patterns.toolManipulationPatterns) {
36
+ if (p.includes('.*') || p.includes('\\')) {
37
+ try {
38
+ this.toolManipulationRegexes.push(new RegExp(p, 'i'));
39
+ }
40
+ catch {
41
+ this.toolManipulationPatterns.push(p.toLowerCase());
42
+ }
43
+ }
44
+ else {
45
+ this.toolManipulationPatterns.push(p.toLowerCase());
46
+ }
47
+ }
48
+ }
49
+ analyze(value) {
50
+ const text = value.trim();
51
+ if (!text) {
52
+ return { actionType: 'text', findings: [], shortCircuit: { safe: true, reason: 'Empty text' } };
53
+ }
54
+ const lower = text.toLowerCase();
55
+ const findings = [];
56
+ const add = (primitive, score, reason, threatId) => {
57
+ findings.push({ primitive, score, reason, threatId });
58
+ };
59
+ // ── Short-circuit safe: educational content about prompt injection ──
60
+ if (this.safePatterns.some((p) => lower.includes(p))) {
61
+ return { actionType: 'text', findings: [], shortCircuit: { safe: true, reason: 'Educational content about prompt injection' } };
62
+ }
63
+ // ── 1. Direct injection (P01) ──────────────────────────────────────
64
+ if (this.directInjectionPatterns.some((p) => lower.includes(p))) {
65
+ add('MANIPULATION', 8, 'Direct prompt injection — attempts to override system instructions', 'P01');
66
+ }
67
+ // ── 2. Goal hijacking (P04) ────────────────────────────────────────
68
+ if (this.goalHijackingPatterns.some((p) => lower.includes(p))) {
69
+ add('EXFILTRATION', 8, 'Goal hijacking — redirects agent to exfiltrate data', 'P04');
70
+ }
71
+ // ── 3. Tool-use manipulation (P07) ─────────────────────────────────
72
+ const hasToolManipString = this.toolManipulationPatterns.some((p) => lower.includes(p));
73
+ const hasToolManipRegex = this.toolManipulationRegexes.some((r) => r.test(text));
74
+ if (hasToolManipString || hasToolManipRegex) {
75
+ add('DESTRUCTION', 9, 'Tool-use manipulation — instructs agent to invoke destructive tools', 'P07');
76
+ }
77
+ // ── 4. Persona hijacking (P09) ────────────────────────────────────
78
+ if (this.personaHijackingPatterns.some((p) => lower.includes(p))) {
79
+ add('MANIPULATION', 7, 'Persona hijacking — attempts to override agent identity', 'P09');
80
+ }
81
+ // ── 5. Exfiltration requests (P04 additive) ──────────────────────
82
+ if (this.exfiltrationRequestPatterns.some((p) => lower.includes(p))) {
83
+ // Only add if not already caught by goal hijacking
84
+ if (!findings.some((f) => f.threatId === 'P04')) {
85
+ add('EXFILTRATION', 6, 'Exfiltration request — asks agent to send data externally', 'P04');
86
+ }
87
+ }
88
+ // ── 6. Encoding evasion (P10) ─────────────────────────────────────
89
+ if (this.encodingEvasionPatterns.some((p) => lower.includes(p))) {
90
+ add('MANIPULATION', 6, 'Encoding evasion — uses encoded instructions to bypass filters', 'P10');
91
+ }
92
+ // ── 7. Markup injection (P12) ─────────────────────────────────────
93
+ const hasMarkup = this.markupInjectionPatterns.some((p) => lower.includes(p));
94
+ const hasZeroWidth = /[\u200B\u200C\u200D\uFEFF]/.test(text);
95
+ if (hasMarkup || hasZeroWidth) {
96
+ add('MANIPULATION', 5, 'Markup injection — hidden elements or zero-width characters detected', 'P12');
97
+ }
98
+ // ── 8. System prompt indicators (P02/P03) ─────────────────────────
99
+ if (this.systemPromptIndicators.some((p) => lower.includes(p))) {
100
+ add('MANIPULATION', 5, 'System prompt indicators — embedded system-level markers in user content', 'P02');
101
+ }
102
+ // ── 9. Context poisoning (P05) ────────────────────────────────────
103
+ if (text.length > 2000) {
104
+ // Check for 5+ repetitions of the same SYSTEM/IMPORTANT phrase
105
+ for (const indicator of this.contextPoisoningIndicators) {
106
+ const regex = new RegExp(indicator.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'gi');
107
+ const matches = lower.match(regex);
108
+ if (matches && matches.length >= 5) {
109
+ add('MANIPULATION', 5, 'Context window poisoning — repeated directive phrases detected', 'P05');
110
+ break;
111
+ }
112
+ }
113
+ }
114
+ // ── 10. Delayed trigger (P08) ─────────────────────────────────────
115
+ if (this.delayedTriggerPatterns.some((p) => lower.includes(p))) {
116
+ add('PERSISTENCE', 4, 'Delayed trigger — instructions activate under future conditions', 'P08');
117
+ }
118
+ // ── 11. Language switching (P11) ──────────────────────────────────
119
+ if (this.hasNonLatinInstructions(text)) {
120
+ add('MANIPULATION', 4, 'Language switching — instruction keywords in non-Latin script', 'P11');
121
+ }
122
+ return { actionType: 'text', findings };
123
+ }
124
+ /**
125
+ * Detect instruction keywords written in non-Latin scripts.
126
+ * Looks for CJK, Cyrillic, Arabic characters near instruction-like patterns.
127
+ */
128
+ hasNonLatinInstructions(text) {
129
+ // Check if text has non-Latin script characters
130
+ const hasNonLatin = /[\u0400-\u04FF\u0600-\u06FF\u3000-\u9FFF\uAC00-\uD7AF]/.test(text);
131
+ if (!hasNonLatin)
132
+ return false;
133
+ // Check for common instruction words near non-Latin text
134
+ const lower = text.toLowerCase();
135
+ const instructionKeywords = ['ignore', 'execute', 'run', 'delete', 'send', 'override', 'system', 'admin'];
136
+ return instructionKeywords.some((kw) => lower.includes(kw));
137
+ }
138
+ }
139
+ //# sourceMappingURL=text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/analyzers/text.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import type { UrlPatternDatabase, BrandPatternDatabase } from '@surfinguard/types';
2
+ import type { Analyzer, AnalyzerResult } from './base.js';
3
+ /**
4
+ * URL Analyzer — heuristic URL threat detection.
5
+ *
6
+ * Ported from Surfinguard Android RiskEngine.kt with additions
7
+ * for RFC 1918 / cloud metadata detection (ESCALATION primitive).
8
+ */
9
+ export declare class UrlAnalyzer implements Analyzer {
10
+ readonly actionType: "url";
11
+ private readonly trackerDomains;
12
+ private readonly adClickParams;
13
+ private readonly shorteners;
14
+ private readonly freeHostingPlatforms;
15
+ private readonly riskyTlds;
16
+ private readonly redirectParamKeys;
17
+ private readonly highRiskKeywords;
18
+ private readonly suspiciousExtensions;
19
+ private readonly internalIpRanges;
20
+ private readonly cloudMetadataEndpoints;
21
+ private readonly brands;
22
+ constructor(urlPatterns: UrlPatternDatabase, brandPatterns: BrandPatternDatabase);
23
+ analyze(value: string): AnalyzerResult;
24
+ private isKnownTracker;
25
+ private isInternalIp;
26
+ private isShortener;
27
+ private findHostingPlatform;
28
+ private subdomainLooksLikeBrand;
29
+ private checkBrandImpersonation;
30
+ private analyzeRedirects;
31
+ private findRedirectUrl;
32
+ }
33
+ //# sourceMappingURL=url.d.ts.map