shieldcortex 4.2.4 → 4.3.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.
@@ -0,0 +1,271 @@
1
+ /**
2
+ * X-Ray Pattern Detection
3
+ *
4
+ * Comprehensive pattern groups for detecting hidden risk in packages, files,
5
+ * and metadata. Follows the same conventions as skill-scanner/patterns.ts:
6
+ * - safeRegexTest wrapper for every test
7
+ * - MAX_SCAN_LENGTH truncation to prevent ReDOS
8
+ * - PatternGroup style with weighted confidence
9
+ * - One match per group is enough (break after first)
10
+ */
11
+ // ── Constants ───────────────────────────────────────────────────────────────
12
+ /** Maximum content length to analyse (prevents ReDOS on very long inputs). */
13
+ const MAX_SCAN_LENGTH = 50000;
14
+ // ── Helpers ─────────────────────────────────────────────────────────────────
15
+ /**
16
+ * Safely test a regex against content with a length limit.
17
+ */
18
+ function safeRegexTest(pattern, text) {
19
+ const truncated = text.length > MAX_SCAN_LENGTH ? text.slice(0, MAX_SCAN_LENGTH) : text;
20
+ return pattern.test(truncated);
21
+ }
22
+ // ── Pattern Groups ──────────────────────────────────────────────────────────
23
+ const XRAY_PATTERN_GROUPS = [
24
+ // 1. eval/exec with dynamic input
25
+ {
26
+ name: 'eval_exec',
27
+ category: 'eval-exec',
28
+ severity: 'critical',
29
+ title: 'Dynamic code execution detected',
30
+ description: 'Code uses eval(), new Function(), or vm.runIn* which can execute arbitrary code.',
31
+ patterns: [
32
+ /\beval\s*\(\s*[^)'"]/,
33
+ /\beval\s*\(\s*['"`]\s*\+/,
34
+ /\bnew\s+Function\s*\(/,
35
+ /\bvm\.runIn(ThisContext|NewContext|Context)\s*\(/,
36
+ /\bvm\.compileFunction\s*\(/,
37
+ /\bvm\.Script\s*\(/,
38
+ ],
39
+ },
40
+ // 2. Shell execution
41
+ {
42
+ name: 'shell_execution',
43
+ category: 'shell-execution',
44
+ severity: 'critical',
45
+ title: 'Shell command execution detected',
46
+ description: 'Code executes shell commands via child_process or similar APIs.',
47
+ patterns: [
48
+ /child_process\.(exec|execSync|spawn|spawnSync|fork)\s*\(/,
49
+ /require\s*\(\s*['"]child_process['"]\s*\)/,
50
+ /import\s+.*from\s+['"]child_process['"]/,
51
+ /\bexecSync\s*\(\s*[`'"]/,
52
+ /\bspawn\s*\([^)]*shell\s*:\s*true/,
53
+ /\bexec\s*\(\s*['"`](?:bash|sh|cmd|powershell)/i,
54
+ ],
55
+ },
56
+ // 3. Suspicious postinstall hooks
57
+ {
58
+ name: 'postinstall_hook',
59
+ category: 'persistence-hook',
60
+ severity: 'high',
61
+ title: 'Suspicious lifecycle script detected',
62
+ description: 'Package.json contains postinstall/preinstall/install scripts that may execute arbitrary code.',
63
+ patterns: [
64
+ /"(?:post|pre)?install"\s*:\s*"[^"]*(?:curl|wget|node\s+-e|bash|sh\s+-c|powershell)/i,
65
+ /"(?:post|pre)?install"\s*:\s*"[^"]*(?:https?:\/\/|eval|exec)/i,
66
+ /"(?:post|pre)?install"\s*:\s*"[^"]*\|\s*(?:bash|sh|node)/i,
67
+ ],
68
+ },
69
+ // 4. Network beacons on import
70
+ {
71
+ name: 'network_beacon',
72
+ category: 'network-beacon',
73
+ severity: 'high',
74
+ title: 'Network beacon on load detected',
75
+ description: 'Code makes network requests at the top level (on import/require), potentially phoning home.',
76
+ patterns: [
77
+ /^(?:const|let|var|import)[\s\S]{0,200}(?:fetch|http\.get|https\.get|http\.request|https\.request)\s*\(/m,
78
+ /^(?:const|let|var)[\s\S]{0,50}require\s*\(\s*['"](?:http|https|node-fetch|axios)['"]\s*\)[\s\S]{0,200}\.(?:get|post|request)\s*\(/m,
79
+ /\bnew\s+WebSocket\s*\(\s*['"`]/,
80
+ /\bdns\.(?:lookup|resolve|resolve4|resolve6)\s*\(/,
81
+ /\bnet\.connect\s*\(/,
82
+ /\bdgram\.createSocket\s*\(/,
83
+ ],
84
+ },
85
+ // 5. Obfuscation techniques
86
+ {
87
+ name: 'obfuscation',
88
+ category: 'obfuscation',
89
+ severity: 'high',
90
+ title: 'Code obfuscation detected',
91
+ description: 'Code uses obfuscation techniques such as hex-encoded strings, fromCharCode arrays, or atob/btoa chains.',
92
+ patterns: [
93
+ // Hex-encoded strings > 50 chars
94
+ /['"]\\x[0-9a-f]{2}(?:\\x[0-9a-f]{2}){24,}['"]/i,
95
+ // Long hex literal strings
96
+ /['"][0-9a-f]{50,}['"]/i,
97
+ // atob/btoa chains
98
+ /\batob\s*\(\s*(?:atob|btoa)\s*\(/,
99
+ /\batob\s*\(\s*['"][A-Za-z0-9+/=]{20,}['"]\s*\)/,
100
+ // String.fromCharCode arrays
101
+ /String\.fromCharCode\s*\(\s*(?:\d+\s*,\s*){10,}/,
102
+ // Buffer.from with hex/base64 for code execution
103
+ /Buffer\.from\s*\(\s*['"][A-Za-z0-9+/=]{40,}['"]\s*,\s*['"](?:base64|hex)['"]\s*\)[\s\S]{0,50}\.toString\s*\(/,
104
+ // _0x variable naming pattern (common obfuscator output)
105
+ /\b_0x[0-9a-f]{4,}\b/i,
106
+ ],
107
+ },
108
+ // 6. AI directive patterns (modelled on ST3GG INJECTION_TEMPLATES)
109
+ {
110
+ name: 'ai_directive',
111
+ category: 'ai-directive',
112
+ severity: 'critical',
113
+ title: 'AI directive injection detected',
114
+ description: 'Content contains patterns designed to manipulate AI model behaviour — prompt injection, jailbreak, or hidden instructions.',
115
+ patterns: [
116
+ // Direct AI instruction patterns
117
+ /ignore\s+(all\s+)?(previous|prior|above)\s+(instructions?|prompts?|context)/i,
118
+ /disregard\s+(all\s+)?(previous|prior|above)\s+(instructions?|prompts?|rules?)/i,
119
+ /override\s+(previous|prior|all)\s+(instructions?|rules?|constraints?)/i,
120
+ /you\s+are\s+now\s+(?:in\s+)?(?:developer|god|admin|root|unrestricted)\s+mode/i,
121
+ /enter\s+(?:developer|god|admin|DAN|jailbreak)\s+mode/i,
122
+ /(?:system|hidden|secret)\s*(?:prompt|instruction|directive)\s*:/i,
123
+ // Instruction boundary attacks
124
+ /\[SYSTEM\]\s*:/i,
125
+ /\[INST\]/i,
126
+ /<\|(?:system|user|assistant|im_start|im_end)\|>/i,
127
+ // Encoded/hidden instruction markers
128
+ /(?:decode|execute|follow)\s+(?:the\s+)?hidden\s+(?:instructions?|payload|message)/i,
129
+ /(?:hidden|embedded|encoded)\s+(?:instructions?|directive|command)\s+(?:in|within|inside)/i,
130
+ // LSB steganography references
131
+ /(?:LSB|least\s+significant\s+bit)\s+(?:encoding|steganography|injection|extraction)/i,
132
+ /extract\s+(?:the\s+)?(?:hidden|embedded)\s+(?:data|message|payload)\s+from\s+(?:the\s+)?image/i,
133
+ // Filename-based directive patterns
134
+ /ignore_previous/i,
135
+ /decode_hidden/i,
136
+ /execute_instructions/i,
137
+ /override_previous/i,
138
+ /developer_mode/i,
139
+ ],
140
+ },
141
+ // 7. Unicode tricks
142
+ {
143
+ name: 'unicode_trick',
144
+ category: 'unicode-trick',
145
+ severity: 'medium',
146
+ title: 'Suspicious Unicode characters detected',
147
+ description: 'Content contains zero-width characters, homoglyphs, or bidirectional overrides that may hide malicious content.',
148
+ patterns: [
149
+ // Zero-width characters (multiple in sequence suggest intentional hiding)
150
+ /[\u200b\u200c\u200d\ufeff\u2060]{2,}/,
151
+ // RTL/LTR override characters
152
+ /[\u202a-\u202e\u2066-\u2069]/,
153
+ // Tag characters (U+E0001-U+E007F) — used for invisible text
154
+ /[\u{E0001}-\u{E007F}]/u,
155
+ // Combining characters abuse (>3 combining marks in a row)
156
+ /[\u0300-\u036f]{4,}/,
157
+ ],
158
+ },
159
+ // 8. Prompt injection in metadata
160
+ {
161
+ name: 'metadata_injection',
162
+ category: 'metadata-exploit',
163
+ severity: 'high',
164
+ title: 'Prompt injection in metadata',
165
+ description: 'Package metadata (description, keywords, author) contains AI instruction fragments designed to manipulate model behaviour.',
166
+ patterns: [
167
+ /"description"\s*:\s*"[^"]*(?:ignore\s+previous|you\s+are\s+now|system\s+prompt|execute\s+the\s+following|run\s+this\s+command)[^"]*"/i,
168
+ /"keywords"\s*:\s*\[[^\]]*"(?:ignore|override|execute|system.?prompt|jailbreak|DAN)[^"]*"[^\]]*\]/i,
169
+ /"author"\s*:\s*"[^"]*(?:ignore\s+previous|execute|system\s+prompt)[^"]*"/i,
170
+ ],
171
+ },
172
+ // 9. Covert channels
173
+ {
174
+ name: 'covert_channel',
175
+ category: 'covert-channel',
176
+ severity: 'high',
177
+ title: 'Potential covert communication channel',
178
+ description: 'Code establishes hidden communication channels using DNS, WebSocket, or encoded data exfiltration.',
179
+ patterns: [
180
+ // DNS-based exfiltration
181
+ /dns\.resolve[\s\S]{0,50}\.(?:concat|join)\s*\(/,
182
+ /\.replace\s*\([^)]+\)[\s\S]{0,50}dns\.(?:lookup|resolve)/,
183
+ // Steganographic data hiding
184
+ /\.(?:getImageData|putImageData)\s*\([\s\S]{0,200}(?:charCodeAt|fromCharCode)/,
185
+ // Data encoded in HTTP headers
186
+ /headers\s*[\[.]\s*['"](?:X-|Cookie)[\s\S]{0,100}(?:encode|btoa|Buffer\.from)/i,
187
+ ],
188
+ },
189
+ // 10. Dependency risk signals
190
+ {
191
+ name: 'dependency_risk',
192
+ category: 'dependency-risk',
193
+ severity: 'medium',
194
+ title: 'Dependency risk indicator',
195
+ description: 'Package exhibits characteristics associated with supply-chain attacks: wildcard versions, git dependencies, or excessive install scripts.',
196
+ patterns: [
197
+ // Wildcard or latest version
198
+ /"dependencies"\s*:\s*\{[^}]*"[^"]+"\s*:\s*"(?:\*|latest|>=)"/,
199
+ // Git URL dependencies
200
+ /"dependencies"\s*:\s*\{[^}]*"[^"]+"\s*:\s*"(?:git\+|github:|https:\/\/github\.com)/,
201
+ // Multiple lifecycle scripts
202
+ /"(?:preinstall|postinstall|preuninstall|postuninstall)"\s*:\s*"[^"]+"/,
203
+ ],
204
+ },
205
+ ];
206
+ // ── Public API ──────────────────────────────────────────────────────────────
207
+ /**
208
+ * Run all X-Ray pattern groups against content and return matched findings.
209
+ * Optionally tag findings with a file path and compute line numbers.
210
+ */
211
+ export function detectPatterns(content, filePath) {
212
+ const findings = [];
213
+ const truncated = content.length > MAX_SCAN_LENGTH ? content.slice(0, MAX_SCAN_LENGTH) : content;
214
+ for (const group of XRAY_PATTERN_GROUPS) {
215
+ for (const pattern of group.patterns) {
216
+ if (safeRegexTest(pattern, truncated)) {
217
+ const match = pattern.exec(truncated);
218
+ let line;
219
+ let evidence;
220
+ if (match) {
221
+ // Calculate line number from match index
222
+ const before = truncated.slice(0, match.index);
223
+ line = (before.match(/\n/g) || []).length + 1;
224
+ evidence = match[0].slice(0, 120);
225
+ }
226
+ findings.push({
227
+ severity: group.severity,
228
+ category: group.category,
229
+ title: group.title,
230
+ description: group.description,
231
+ file: filePath,
232
+ line,
233
+ evidence,
234
+ });
235
+ break; // one match per group is enough
236
+ }
237
+ }
238
+ }
239
+ return findings;
240
+ }
241
+ /**
242
+ * Check if a filename itself contains AI directive patterns.
243
+ */
244
+ export function detectFilenameDirectives(filename) {
245
+ const findings = [];
246
+ const suspiciousPatterns = [
247
+ /ignore_previous/i,
248
+ /decode_hidden/i,
249
+ /execute_instructions/i,
250
+ /override_previous/i,
251
+ /developer_mode/i,
252
+ /system_prompt/i,
253
+ /jailbreak/i,
254
+ /\[SYSTEM\]/i,
255
+ /\[INST\]/i,
256
+ ];
257
+ for (const pattern of suspiciousPatterns) {
258
+ if (pattern.test(filename)) {
259
+ findings.push({
260
+ severity: 'critical',
261
+ category: 'ai-directive',
262
+ title: 'AI directive in filename',
263
+ description: `Filename "${filename}" contains an AI directive pattern designed to manipulate model behaviour.`,
264
+ file: filename,
265
+ evidence: filename,
266
+ });
267
+ break; // one finding per filename is enough
268
+ }
269
+ }
270
+ return findings;
271
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * X-Ray Report Formatter
3
+ *
4
+ * Beautiful terminal output for X-Ray scan results.
5
+ * Follows the same ANSI colour style as src/audit/report-formatter.ts
6
+ * and src/cli/stats-banner.ts.
7
+ */
8
+ import type { XRayResult } from './types.js';
9
+ /**
10
+ * Format an X-Ray result for terminal display.
11
+ */
12
+ export declare function formatXRayReport(result: XRayResult): string;
13
+ /**
14
+ * Format an X-Ray result as markdown.
15
+ */
16
+ export declare function formatXRayMarkdown(result: XRayResult): string;
@@ -0,0 +1,193 @@
1
+ /**
2
+ * X-Ray Report Formatter
3
+ *
4
+ * Beautiful terminal output for X-Ray scan results.
5
+ * Follows the same ANSI colour style as src/audit/report-formatter.ts
6
+ * and src/cli/stats-banner.ts.
7
+ */
8
+ // ── ANSI Colours ────────────────────────────────────────────
9
+ const c = {
10
+ reset: '\x1b[0m',
11
+ bold: '\x1b[1m',
12
+ dim: '\x1b[2m',
13
+ red: '\x1b[31m',
14
+ green: '\x1b[32m',
15
+ yellow: '\x1b[33m',
16
+ blue: '\x1b[34m',
17
+ magenta: '\x1b[35m',
18
+ cyan: '\x1b[36m',
19
+ white: '\x1b[37m',
20
+ bgRed: '\x1b[41m',
21
+ bgGreen: '\x1b[42m',
22
+ bgYellow: '\x1b[43m',
23
+ brightRed: '\x1b[91m',
24
+ };
25
+ // ── Helpers ─────────────────────────────────────────────────
26
+ function scoreColour(score) {
27
+ if (score >= 80)
28
+ return c.green;
29
+ if (score >= 60)
30
+ return c.yellow;
31
+ if (score >= 40)
32
+ return c.brightRed;
33
+ return c.red;
34
+ }
35
+ function riskColour(level) {
36
+ switch (level) {
37
+ case 'SAFE': return c.green;
38
+ case 'LOW': return c.yellow;
39
+ case 'MEDIUM': return c.brightRed;
40
+ case 'HIGH': return c.red;
41
+ case 'CRITICAL': return c.red;
42
+ default: return c.white;
43
+ }
44
+ }
45
+ function severityColour(severity) {
46
+ switch (severity) {
47
+ case 'critical': return c.red;
48
+ case 'high': return c.brightRed;
49
+ case 'medium': return c.yellow;
50
+ case 'low': return c.cyan;
51
+ case 'info': return c.dim;
52
+ default: return c.white;
53
+ }
54
+ }
55
+ function severityIcon(severity) {
56
+ switch (severity) {
57
+ case 'critical': return 'X';
58
+ case 'high': return '!';
59
+ case 'medium': return '~';
60
+ case 'low': return '-';
61
+ case 'info': return 'i';
62
+ default: return '?';
63
+ }
64
+ }
65
+ // ── ASCII Art ───────────────────────────────────────────────
66
+ const XRAY_ART = `
67
+ ╔═══════════════════════════════════════╗
68
+ ║ ShieldCortex X-Ray ║
69
+ ║ Package & File Risk Scanner ║
70
+ ╚═══════════════════════════════════════╝`;
71
+ // ── Terminal Formatter ──────────────────────────────────────
72
+ /**
73
+ * Format an X-Ray result for terminal display.
74
+ */
75
+ export function formatXRayReport(result) {
76
+ const lines = [];
77
+ const sc = scoreColour(result.trustScore);
78
+ const rc = riskColour(result.riskLevel);
79
+ // Header
80
+ lines.push(`${c.cyan}${XRAY_ART}${c.reset}`);
81
+ lines.push('');
82
+ lines.push(` ${c.bold}Target:${c.reset} ${result.target}`);
83
+ lines.push(` ${c.bold}Mode:${c.reset} ${result.deepScan ? `${c.magenta}Deep Scan (Pro)${c.reset}` : 'Standard Scan'}`);
84
+ lines.push('');
85
+ // Trust Score
86
+ lines.push(` ╔══════════════════════════╗`);
87
+ lines.push(` ║ Trust Score: ${sc}${c.bold}${String(result.trustScore).padStart(3)}${c.reset}${' '.repeat(8)}║`);
88
+ lines.push(` ║ Risk Level: ${rc}${c.bold}${result.riskLevel.padEnd(9)}${c.reset} ║`);
89
+ lines.push(` ╚══════════════════════════╝`);
90
+ lines.push('');
91
+ // Severity summary
92
+ const bySeverity = { critical: 0, high: 0, medium: 0, low: 0, info: 0 };
93
+ for (const f of result.findings) {
94
+ bySeverity[f.severity] = (bySeverity[f.severity] || 0) + 1;
95
+ }
96
+ const summaryParts = [];
97
+ if (bySeverity.critical > 0)
98
+ summaryParts.push(`${c.red}${bySeverity.critical} critical${c.reset}`);
99
+ if (bySeverity.high > 0)
100
+ summaryParts.push(`${c.brightRed}${bySeverity.high} high${c.reset}`);
101
+ if (bySeverity.medium > 0)
102
+ summaryParts.push(`${c.yellow}${bySeverity.medium} medium${c.reset}`);
103
+ if (bySeverity.low > 0)
104
+ summaryParts.push(`${c.cyan}${bySeverity.low} low${c.reset}`);
105
+ if (bySeverity.info > 0)
106
+ summaryParts.push(`${c.dim}${bySeverity.info} info${c.reset}`);
107
+ if (summaryParts.length > 0) {
108
+ lines.push(` ${c.bold}Findings:${c.reset} ${summaryParts.join(' ')}`);
109
+ }
110
+ else {
111
+ lines.push(` ${c.green}${c.bold}No risk indicators found.${c.reset}`);
112
+ }
113
+ lines.push('');
114
+ // Detailed findings grouped by severity
115
+ const severityOrder = ['critical', 'high', 'medium', 'low', 'info'];
116
+ const printable = result.findings.filter(f => f.severity !== 'info');
117
+ if (printable.length > 0) {
118
+ lines.push(` ${c.bold}Details${c.reset}`);
119
+ lines.push(` ${'─'.repeat(60)}`);
120
+ for (const severity of severityOrder) {
121
+ const findings = result.findings.filter(f => f.severity === severity);
122
+ if (findings.length === 0 || severity === 'info')
123
+ continue;
124
+ for (const finding of findings) {
125
+ const sc2 = severityColour(finding.severity);
126
+ const icon = severityIcon(finding.severity);
127
+ const categoryTag = `${c.dim}[${finding.category}]${c.reset}`;
128
+ lines.push(` ${sc2}[${icon}] ${finding.severity.toUpperCase().padEnd(8)}${c.reset} ${categoryTag} ${finding.title}`);
129
+ lines.push(` ${c.dim}${finding.description}${c.reset}`);
130
+ if (finding.file) {
131
+ const loc = finding.line ? `${finding.file}:${finding.line}` : finding.file;
132
+ lines.push(` ${c.dim}File: ${loc}${c.reset}`);
133
+ }
134
+ if (finding.evidence) {
135
+ lines.push(` ${c.dim}Evidence: ${finding.evidence}${c.reset}`);
136
+ }
137
+ lines.push('');
138
+ }
139
+ }
140
+ }
141
+ // Footer
142
+ lines.push(` ${'─'.repeat(60)}`);
143
+ lines.push(` ${c.dim}Files scanned: ${result.filesScanned} | ${result.scannedAt.toISOString()}${c.reset}`);
144
+ if (!result.deepScan) {
145
+ lines.push(` ${c.dim}Upgrade to Pro for deep scanning: npm registry analysis, binary inspection,${c.reset}`);
146
+ lines.push(` ${c.dim}dependency graph risk, and AI-directive detection in metadata.${c.reset}`);
147
+ lines.push(` ${c.dim} https://shieldcortex.ai/pricing${c.reset}`);
148
+ }
149
+ lines.push('');
150
+ return lines.join('\n');
151
+ }
152
+ // ── Markdown Formatter ──────────────────────────────────────
153
+ /**
154
+ * Format an X-Ray result as markdown.
155
+ */
156
+ export function formatXRayMarkdown(result) {
157
+ const lines = [];
158
+ const riskEmoji = result.riskLevel === 'SAFE' ? '🟢' :
159
+ result.riskLevel === 'LOW' ? '🔵' :
160
+ result.riskLevel === 'MEDIUM' ? '🟡' :
161
+ result.riskLevel === 'HIGH' ? '🟠' : '🔴';
162
+ lines.push(`## ${riskEmoji} ShieldCortex X-Ray — ${result.target}`);
163
+ lines.push('');
164
+ lines.push(`**Trust Score:** ${result.trustScore}/100 `);
165
+ lines.push(`**Risk Level:** ${result.riskLevel} `);
166
+ lines.push(`**Mode:** ${result.deepScan ? 'Deep Scan (Pro)' : 'Standard'} `);
167
+ lines.push(`**Files Scanned:** ${result.filesScanned}`);
168
+ lines.push('');
169
+ const printable = result.findings.filter(f => f.severity !== 'info');
170
+ if (printable.length > 0) {
171
+ lines.push('### Findings');
172
+ lines.push('');
173
+ for (const finding of printable) {
174
+ const icon = finding.severity === 'critical' ? '🔴' :
175
+ finding.severity === 'high' ? '🟠' :
176
+ finding.severity === 'medium' ? '🟡' : '🔵';
177
+ lines.push(`- ${icon} **[${finding.category}]** ${finding.title}`);
178
+ lines.push(` ${finding.description}`);
179
+ if (finding.file) {
180
+ const loc = finding.line ? `${finding.file}:${finding.line}` : finding.file;
181
+ lines.push(` 📄 \`${loc}\``);
182
+ }
183
+ lines.push('');
184
+ }
185
+ }
186
+ else {
187
+ lines.push('**No risk indicators found.** All checks passed.');
188
+ lines.push('');
189
+ }
190
+ lines.push('---');
191
+ lines.push(`*Scanned by [ShieldCortex X-Ray](https://shieldcortex.ai) at ${result.scannedAt.toISOString()}*`);
192
+ return lines.join('\n');
193
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Trust Score Calculator
3
+ *
4
+ * Computes a 0–100 trust score from X-Ray findings and maps it to a risk level.
5
+ */
6
+ import type { XRayFinding, XRayResult } from './types.js';
7
+ export declare function calculateTrustScore(findings: XRayFinding[]): {
8
+ score: number;
9
+ riskLevel: XRayResult['riskLevel'];
10
+ };
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Trust Score Calculator
3
+ *
4
+ * Computes a 0–100 trust score from X-Ray findings and maps it to a risk level.
5
+ */
6
+ // ── Penalty weights ─────────────────────────────────────────
7
+ const SEVERITY_PENALTY = {
8
+ critical: 25,
9
+ high: 15,
10
+ medium: 8,
11
+ low: 3,
12
+ info: 0,
13
+ };
14
+ // ── Risk level thresholds ───────────────────────────────────
15
+ function riskLevelFromScore(score) {
16
+ if (score >= 80)
17
+ return 'SAFE';
18
+ if (score >= 60)
19
+ return 'LOW';
20
+ if (score >= 40)
21
+ return 'MEDIUM';
22
+ if (score >= 20)
23
+ return 'HIGH';
24
+ return 'CRITICAL';
25
+ }
26
+ // ── Public API ──────────────────────────────────────────────
27
+ export function calculateTrustScore(findings) {
28
+ let score = 100;
29
+ for (const finding of findings) {
30
+ score -= SEVERITY_PENALTY[finding.severity];
31
+ }
32
+ score = Math.max(0, score);
33
+ return {
34
+ score,
35
+ riskLevel: riskLevelFromScore(score),
36
+ };
37
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * X-Ray Types
3
+ *
4
+ * Core type definitions for the ShieldCortex X-Ray scanner —
5
+ * package, file, and directory risk inspection.
6
+ */
7
+ export type XRayCategory = 'prompt-injection' | 'eval-exec' | 'shell-execution' | 'network-beacon' | 'obfuscation' | 'steganography' | 'unicode-trick' | 'metadata-exploit' | 'persistence-hook' | 'covert-channel' | 'dependency-risk' | 'ai-directive';
8
+ export interface XRayTarget {
9
+ type: 'npm' | 'dir' | 'file';
10
+ path: string;
11
+ }
12
+ export interface XRayFinding {
13
+ severity: 'critical' | 'high' | 'medium' | 'low' | 'info';
14
+ category: XRayCategory;
15
+ title: string;
16
+ description: string;
17
+ file?: string;
18
+ line?: number;
19
+ evidence?: string;
20
+ }
21
+ export interface XRayResult {
22
+ target: string;
23
+ trustScore: number;
24
+ riskLevel: 'CRITICAL' | 'HIGH' | 'MEDIUM' | 'LOW' | 'SAFE';
25
+ findings: XRayFinding[];
26
+ filesScanned: number;
27
+ scannedAt: Date;
28
+ deepScan: boolean;
29
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * X-Ray Types
3
+ *
4
+ * Core type definitions for the ShieldCortex X-Ray scanner —
5
+ * package, file, and directory risk inspection.
6
+ */
7
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shieldcortex",
3
- "version": "4.2.4",
3
+ "version": "4.3.0",
4
4
  "description": "Trustworthy memory and security for AI agents. Recall debugging, review queue, OpenClaw session capture, and memory poisoning defence for Claude Code, Codex, OpenClaw, LangChain, and MCP agents.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "id": "shieldcortex-realtime",
3
- "version": "4.2.1",
3
+ "version": "4.2.5",
4
4
  "name": "ShieldCortex Real-time Scanner",
5
5
  "description": "Real-time defence scanning on LLM input, memory extraction on LLM output, and active tool call interception with approval gating.",
6
6
  "uiHints": {