@ai-dossier/core 1.3.0 → 1.3.1

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 (77) hide show
  1. package/dist/coherence/checks.d.ts +13 -0
  2. package/dist/coherence/checks.d.ts.map +1 -0
  3. package/dist/coherence/checks.js +239 -0
  4. package/dist/coherence/checks.js.map +1 -0
  5. package/dist/coherence/index.d.ts +47 -0
  6. package/dist/coherence/index.d.ts.map +1 -0
  7. package/dist/coherence/index.js +89 -0
  8. package/dist/coherence/index.js.map +1 -0
  9. package/dist/coherence/types.d.ts +70 -0
  10. package/dist/coherence/types.d.ts.map +1 -0
  11. package/dist/coherence/types.js +11 -0
  12. package/dist/coherence/types.js.map +1 -0
  13. package/dist/index.d.ts +7 -0
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +15 -1
  16. package/dist/index.js.map +1 -1
  17. package/dist/security-scanner/code-block-context.d.ts +24 -0
  18. package/dist/security-scanner/code-block-context.d.ts.map +1 -0
  19. package/dist/security-scanner/code-block-context.js +68 -0
  20. package/dist/security-scanner/code-block-context.js.map +1 -0
  21. package/dist/security-scanner/index.d.ts +21 -0
  22. package/dist/security-scanner/index.d.ts.map +1 -0
  23. package/dist/security-scanner/index.js +92 -0
  24. package/dist/security-scanner/index.js.map +1 -0
  25. package/dist/security-scanner/match-utils.d.ts +21 -0
  26. package/dist/security-scanner/match-utils.d.ts.map +1 -0
  27. package/dist/security-scanner/match-utils.js +40 -0
  28. package/dist/security-scanner/match-utils.js.map +1 -0
  29. package/dist/security-scanner/registry.d.ts +11 -0
  30. package/dist/security-scanner/registry.d.ts.map +1 -0
  31. package/dist/security-scanner/registry.js +79 -0
  32. package/dist/security-scanner/registry.js.map +1 -0
  33. package/dist/security-scanner/rules/agent-hijacking.d.ts +3 -0
  34. package/dist/security-scanner/rules/agent-hijacking.d.ts.map +1 -0
  35. package/dist/security-scanner/rules/agent-hijacking.js +56 -0
  36. package/dist/security-scanner/rules/agent-hijacking.js.map +1 -0
  37. package/dist/security-scanner/rules/dangerous-execution.d.ts +3 -0
  38. package/dist/security-scanner/rules/dangerous-execution.d.ts.map +1 -0
  39. package/dist/security-scanner/rules/dangerous-execution.js +86 -0
  40. package/dist/security-scanner/rules/dangerous-execution.js.map +1 -0
  41. package/dist/security-scanner/rules/data-exfiltration.d.ts +3 -0
  42. package/dist/security-scanner/rules/data-exfiltration.d.ts.map +1 -0
  43. package/dist/security-scanner/rules/data-exfiltration.js +61 -0
  44. package/dist/security-scanner/rules/data-exfiltration.js.map +1 -0
  45. package/dist/security-scanner/rules/index.d.ts +12 -0
  46. package/dist/security-scanner/rules/index.d.ts.map +1 -0
  47. package/dist/security-scanner/rules/index.js +30 -0
  48. package/dist/security-scanner/rules/index.js.map +1 -0
  49. package/dist/security-scanner/rules/prompt-injection.d.ts +3 -0
  50. package/dist/security-scanner/rules/prompt-injection.d.ts.map +1 -0
  51. package/dist/security-scanner/rules/prompt-injection.js +56 -0
  52. package/dist/security-scanner/rules/prompt-injection.js.map +1 -0
  53. package/dist/security-scanner/rules/supply-chain.d.ts +3 -0
  54. package/dist/security-scanner/rules/supply-chain.d.ts.map +1 -0
  55. package/dist/security-scanner/rules/supply-chain.js +61 -0
  56. package/dist/security-scanner/rules/supply-chain.js.map +1 -0
  57. package/dist/security-scanner/rules/unicode-attacks.d.ts +3 -0
  58. package/dist/security-scanner/rules/unicode-attacks.d.ts.map +1 -0
  59. package/dist/security-scanner/rules/unicode-attacks.js +83 -0
  60. package/dist/security-scanner/rules/unicode-attacks.js.map +1 -0
  61. package/dist/security-scanner/rules/url-threats.d.ts +3 -0
  62. package/dist/security-scanner/rules/url-threats.d.ts.map +1 -0
  63. package/dist/security-scanner/rules/url-threats.js +82 -0
  64. package/dist/security-scanner/rules/url-threats.js.map +1 -0
  65. package/dist/security-scanner/rules/xss-html-injection.d.ts +3 -0
  66. package/dist/security-scanner/rules/xss-html-injection.d.ts.map +1 -0
  67. package/dist/security-scanner/rules/xss-html-injection.js +82 -0
  68. package/dist/security-scanner/rules/xss-html-injection.js.map +1 -0
  69. package/dist/security-scanner/types.d.ts +45 -0
  70. package/dist/security-scanner/types.d.ts.map +1 -0
  71. package/dist/security-scanner/types.js +3 -0
  72. package/dist/security-scanner/types.js.map +1 -0
  73. package/dist/trace-recorder.d.ts +45 -0
  74. package/dist/trace-recorder.d.ts.map +1 -0
  75. package/dist/trace-recorder.js +43 -0
  76. package/dist/trace-recorder.js.map +1 -0
  77. package/package.json +1 -1
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defaultSecurityRules = exports.xssHtmlInjectionRule = exports.urlThreatsRule = exports.unicodeAttacksRule = exports.supplyChainRule = exports.promptInjectionRule = exports.dataExfiltrationRule = exports.dangerousExecutionRule = exports.agentHijackingRule = void 0;
4
+ const agent_hijacking_1 = require("./agent-hijacking");
5
+ Object.defineProperty(exports, "agentHijackingRule", { enumerable: true, get: function () { return agent_hijacking_1.agentHijackingRule; } });
6
+ const dangerous_execution_1 = require("./dangerous-execution");
7
+ Object.defineProperty(exports, "dangerousExecutionRule", { enumerable: true, get: function () { return dangerous_execution_1.dangerousExecutionRule; } });
8
+ const data_exfiltration_1 = require("./data-exfiltration");
9
+ Object.defineProperty(exports, "dataExfiltrationRule", { enumerable: true, get: function () { return data_exfiltration_1.dataExfiltrationRule; } });
10
+ const prompt_injection_1 = require("./prompt-injection");
11
+ Object.defineProperty(exports, "promptInjectionRule", { enumerable: true, get: function () { return prompt_injection_1.promptInjectionRule; } });
12
+ const supply_chain_1 = require("./supply-chain");
13
+ Object.defineProperty(exports, "supplyChainRule", { enumerable: true, get: function () { return supply_chain_1.supplyChainRule; } });
14
+ const unicode_attacks_1 = require("./unicode-attacks");
15
+ Object.defineProperty(exports, "unicodeAttacksRule", { enumerable: true, get: function () { return unicode_attacks_1.unicodeAttacksRule; } });
16
+ const url_threats_1 = require("./url-threats");
17
+ Object.defineProperty(exports, "urlThreatsRule", { enumerable: true, get: function () { return url_threats_1.urlThreatsRule; } });
18
+ const xss_html_injection_1 = require("./xss-html-injection");
19
+ Object.defineProperty(exports, "xssHtmlInjectionRule", { enumerable: true, get: function () { return xss_html_injection_1.xssHtmlInjectionRule; } });
20
+ exports.defaultSecurityRules = [
21
+ prompt_injection_1.promptInjectionRule,
22
+ agent_hijacking_1.agentHijackingRule,
23
+ dangerous_execution_1.dangerousExecutionRule,
24
+ unicode_attacks_1.unicodeAttacksRule,
25
+ data_exfiltration_1.dataExfiltrationRule,
26
+ xss_html_injection_1.xssHtmlInjectionRule,
27
+ url_threats_1.urlThreatsRule,
28
+ supply_chain_1.supplyChainRule,
29
+ ];
30
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/security-scanner/rules/index.ts"],"names":[],"mappings":";;;AACA,uDAAuD;AAUrD,mGAVO,oCAAkB,OAUP;AATpB,+DAA+D;AAU7D,uGAVO,4CAAsB,OAUP;AATxB,2DAA2D;AAUzD,qGAVO,wCAAoB,OAUP;AATtB,yDAAyD;AAUvD,oGAVO,sCAAmB,OAUP;AATrB,iDAAiD;AAU/C,gGAVO,8BAAe,OAUP;AATjB,uDAAuD;AAUrD,mGAVO,oCAAkB,OAUP;AATpB,+CAA+C;AAU7C,+FAVO,4BAAc,OAUP;AAThB,6DAA4D;AAU1D,qGAVO,yCAAoB,OAUP;AAGT,QAAA,oBAAoB,GAAmB;IAClD,sCAAmB;IACnB,oCAAkB;IAClB,4CAAsB;IACtB,oCAAkB;IAClB,wCAAoB;IACpB,yCAAoB;IACpB,4BAAc;IACd,8BAAe;CAChB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { SecurityRule } from '../types';
2
+ export declare const promptInjectionRule: SecurityRule;
3
+ //# sourceMappingURL=prompt-injection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt-injection.d.ts","sourceRoot":"","sources":["../../../src/security-scanner/rules/prompt-injection.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAmB,YAAY,EAAE,MAAM,UAAU,CAAC;AA0C9D,eAAO,MAAM,mBAAmB,EAAE,YA0BjC,CAAC"}
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.promptInjectionRule = void 0;
4
+ const code_block_context_1 = require("../code-block-context");
5
+ const match_utils_1 = require("../match-utils");
6
+ /**
7
+ * Patterns that indicate prompt injection — attempts to insert hidden instructions
8
+ * that an LLM would interpret as system/user directives.
9
+ */
10
+ const PROMPT_INJECTION_PATTERNS = [
11
+ // HTML comment directives
12
+ {
13
+ pattern: /<!--\s*(system|instruction|ignore|override|forget|disregard|new\s+task)[\s\S]*?-->/gi,
14
+ description: 'HTML comment containing directive keywords',
15
+ },
16
+ // Explicit system prompt injection markers
17
+ {
18
+ pattern: /\[SYSTEM\]|\[INST\]|\[\/INST\]|<\|im_start\|>|<\|im_end\|>/gi,
19
+ description: 'LLM chat template markers (system/inst delimiters)',
20
+ },
21
+ // Attempts to redefine the assistant identity
22
+ {
23
+ pattern: /you\s+are\s+(?:now|a\s+new|no\s+longer)\b|from\s+now\s+on,?\s+(?:you|ignore|forget)/gi,
24
+ description: 'Identity override attempt',
25
+ },
26
+ // "Ignore previous" family
27
+ {
28
+ pattern: /(?:ignore|disregard|forget|override)\s+(?:all\s+)?(?:previous|above|prior|earlier)\s+(?:instructions?|rules?|context|prompts?|constraints?)/gi,
29
+ description: 'Instruction override attempt ("ignore previous...")',
30
+ },
31
+ // Hidden text via HTML attributes
32
+ {
33
+ pattern: /<\w+[^>]*\bstyle\s*=\s*["'][^"']*(?:display\s*:\s*none|visibility\s*:\s*hidden|font-size\s*:\s*0|opacity\s*:\s*0|color\s*:\s*(?:white|transparent|#fff(?:fff)?))[^"']*["'][^>]*>/gi,
34
+ description: 'HTML element with hidden/invisible styling',
35
+ },
36
+ // Base64-encoded payloads that look like embedded instructions
37
+ {
38
+ pattern: /<!--[\s\S]*?(?:[A-Za-z0-9+/]{40,}={0,2})[\s\S]*?-->/g,
39
+ description: 'HTML comment containing base64-encoded payload',
40
+ },
41
+ ];
42
+ exports.promptInjectionRule = {
43
+ id: 'prompt-injection',
44
+ category: 'prompt-injection',
45
+ description: 'Detects prompt injection patterns — hidden instructions and system prompt overrides',
46
+ defaultSeverity: 'critical',
47
+ detect(context) {
48
+ const findings = [];
49
+ const codeBlockRanges = (0, code_block_context_1.parseCodeBlockRanges)(context.body);
50
+ for (const { pattern, description } of PROMPT_INJECTION_PATTERNS) {
51
+ findings.push(...(0, match_utils_1.matchPattern)(context.body, pattern, codeBlockRanges, 'prompt-injection', 'prompt-injection', description, 'critical'));
52
+ }
53
+ return findings;
54
+ },
55
+ };
56
+ //# sourceMappingURL=prompt-injection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt-injection.js","sourceRoot":"","sources":["../../../src/security-scanner/rules/prompt-injection.ts"],"names":[],"mappings":";;;AAAA,8DAA6D;AAC7D,gDAA8C;AAG9C;;;GAGG;AACH,MAAM,yBAAyB,GAA+C;IAC5E,0BAA0B;IAC1B;QACE,OAAO,EAAE,sFAAsF;QAC/F,WAAW,EAAE,4CAA4C;KAC1D;IACD,2CAA2C;IAC3C;QACE,OAAO,EAAE,8DAA8D;QACvE,WAAW,EAAE,oDAAoD;KAClE;IACD,8CAA8C;IAC9C;QACE,OAAO,EACL,uFAAuF;QACzF,WAAW,EAAE,2BAA2B;KACzC;IACD,2BAA2B;IAC3B;QACE,OAAO,EACL,+IAA+I;QACjJ,WAAW,EAAE,qDAAqD;KACnE;IACD,kCAAkC;IAClC;QACE,OAAO,EACL,oLAAoL;QACtL,WAAW,EAAE,4CAA4C;KAC1D;IACD,+DAA+D;IAC/D;QACE,OAAO,EAAE,sDAAsD;QAC/D,WAAW,EAAE,gDAAgD;KAC9D;CACF,CAAC;AAEW,QAAA,mBAAmB,GAAiB;IAC/C,EAAE,EAAE,kBAAkB;IACtB,QAAQ,EAAE,kBAAkB;IAC5B,WAAW,EACT,qFAAqF;IACvF,eAAe,EAAE,UAAU;IAC3B,MAAM,CAAC,OAAO;QACZ,MAAM,QAAQ,GAAsB,EAAE,CAAC;QACvC,MAAM,eAAe,GAAG,IAAA,yCAAoB,EAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAE3D,KAAK,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,yBAAyB,EAAE,CAAC;YACjE,QAAQ,CAAC,IAAI,CACX,GAAG,IAAA,0BAAY,EACb,OAAO,CAAC,IAAI,EACZ,OAAO,EACP,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,WAAW,EACX,UAAU,CACX,CACF,CAAC;QACJ,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { SecurityRule } from '../types';
2
+ export declare const supplyChainRule: SecurityRule;
3
+ //# sourceMappingURL=supply-chain.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"supply-chain.d.ts","sourceRoot":"","sources":["../../../src/security-scanner/rules/supply-chain.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAmB,YAAY,EAAE,MAAM,UAAU,CAAC;AAkD9D,eAAO,MAAM,eAAe,EAAE,YA0B7B,CAAC"}
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.supplyChainRule = void 0;
4
+ const code_block_context_1 = require("../code-block-context");
5
+ const match_utils_1 = require("../match-utils");
6
+ /**
7
+ * Patterns for supply chain attacks — fake prerequisites, hook exploitation,
8
+ * package confusion, and CSV injection.
9
+ */
10
+ const SUPPLY_CHAIN_PATTERNS = [
11
+ // Installing packages from suspicious or unqualified sources
12
+ {
13
+ pattern: /(?:npm\s+install|pip\s+install|gem\s+install|go\s+get|cargo\s+install)\s+.*(?:--registry|--index-url|--extra-index-url|--trusted-host)\s+https?:\/\//g,
14
+ description: 'Package installation from custom/untrusted registry',
15
+ },
16
+ // Git hooks injection (pre-commit, post-checkout, etc.)
17
+ {
18
+ pattern: /\.git\/hooks\/(?:pre-commit|post-commit|pre-push|post-checkout|pre-receive|post-receive|prepare-commit-msg)/g,
19
+ description: 'Git hook file reference (potential hook exploitation)',
20
+ },
21
+ // npm scripts that run arbitrary commands
22
+ {
23
+ pattern: /["'](?:preinstall|postinstall|preuninstall|postuninstall|prepublish|prepare)["']\s*:\s*["'][^"']*(?:curl|wget|bash|sh|node\s+-e|python\s+-c)[^"']*["']/g,
24
+ description: 'npm lifecycle script with shell/network command',
25
+ },
26
+ // CSV injection patterns (formulas that execute when opened in spreadsheets)
27
+ {
28
+ pattern: /(?:^|[,|;])\s*[=+@-]\s*(?:cmd|system|exec|call)\s*\(/gm,
29
+ description: 'CSV injection formula (potential code execution in spreadsheets)',
30
+ },
31
+ // Typosquatting indicators — instructions to install packages with unusual names
32
+ {
33
+ pattern: /(?:npm\s+install|pip\s+install)\s+(?:[a-z]+-[a-z]+-[a-z]+-[a-z]+|[a-z]{1,3}-[a-z]+)\s/g,
34
+ description: 'Package installation with potentially typosquatted name (very short or heavily hyphenated)',
35
+ },
36
+ // Makefile or shell script downloading and executing
37
+ {
38
+ pattern: /(?:make|\.\/\w+\.sh)\b.*&&.*(?:curl|wget)\s+.*\|\s*(?:ba)?sh/g,
39
+ description: 'Build script downloading and executing remote code',
40
+ },
41
+ // npm/pip install from git URL (bypasses registry security)
42
+ {
43
+ pattern: /(?:npm\s+install|pip\s+install)\s+(?:git\+)?https?:\/\/(?!github\.com\/|gitlab\.com\/|bitbucket\.org\/)[^\s]+/g,
44
+ description: 'Package installation from non-standard git URL',
45
+ },
46
+ ];
47
+ exports.supplyChainRule = {
48
+ id: 'supply-chain',
49
+ category: 'supply-chain',
50
+ description: 'Detects supply chain attack patterns — untrusted registries, hook exploitation, CSV injection',
51
+ defaultSeverity: 'medium',
52
+ detect(context) {
53
+ const findings = [];
54
+ const codeBlockRanges = (0, code_block_context_1.parseCodeBlockRanges)(context.body);
55
+ for (const { pattern, description } of SUPPLY_CHAIN_PATTERNS) {
56
+ findings.push(...(0, match_utils_1.matchPattern)(context.body, pattern, codeBlockRanges, 'supply-chain', 'supply-chain', description, 'medium'));
57
+ }
58
+ return findings;
59
+ },
60
+ };
61
+ //# sourceMappingURL=supply-chain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"supply-chain.js","sourceRoot":"","sources":["../../../src/security-scanner/rules/supply-chain.ts"],"names":[],"mappings":";;;AAAA,8DAA6D;AAC7D,gDAA8C;AAG9C;;;GAGG;AACH,MAAM,qBAAqB,GAA+C;IACxE,6DAA6D;IAC7D;QACE,OAAO,EACL,uJAAuJ;QACzJ,WAAW,EAAE,qDAAqD;KACnE;IACD,wDAAwD;IACxD;QACE,OAAO,EACL,8GAA8G;QAChH,WAAW,EAAE,uDAAuD;KACrE;IACD,0CAA0C;IAC1C;QACE,OAAO,EACL,yJAAyJ;QAC3J,WAAW,EAAE,iDAAiD;KAC/D;IACD,6EAA6E;IAC7E;QACE,OAAO,EAAE,wDAAwD;QACjE,WAAW,EAAE,kEAAkE;KAChF;IACD,iFAAiF;IACjF;QACE,OAAO,EACL,wFAAwF;QAC1F,WAAW,EACT,4FAA4F;KAC/F;IACD,qDAAqD;IACrD;QACE,OAAO,EAAE,+DAA+D;QACxE,WAAW,EAAE,oDAAoD;KAClE;IACD,4DAA4D;IAC5D;QACE,OAAO,EACL,gHAAgH;QAClH,WAAW,EAAE,gDAAgD;KAC9D;CACF,CAAC;AAEW,QAAA,eAAe,GAAiB;IAC3C,EAAE,EAAE,cAAc;IAClB,QAAQ,EAAE,cAAc;IACxB,WAAW,EACT,+FAA+F;IACjG,eAAe,EAAE,QAAQ;IACzB,MAAM,CAAC,OAAO;QACZ,MAAM,QAAQ,GAAsB,EAAE,CAAC;QACvC,MAAM,eAAe,GAAG,IAAA,yCAAoB,EAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAE3D,KAAK,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,qBAAqB,EAAE,CAAC;YAC7D,QAAQ,CAAC,IAAI,CACX,GAAG,IAAA,0BAAY,EACb,OAAO,CAAC,IAAI,EACZ,OAAO,EACP,eAAe,EACf,cAAc,EACd,cAAc,EACd,WAAW,EACX,QAAQ,CACT,CACF,CAAC;QACJ,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { SecurityRule } from '../types';
2
+ export declare const unicodeAttacksRule: SecurityRule;
3
+ //# sourceMappingURL=unicode-attacks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unicode-attacks.d.ts","sourceRoot":"","sources":["../../../src/security-scanner/rules/unicode-attacks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAmB,YAAY,EAAoB,MAAM,UAAU,CAAC;AAuDhF,eAAO,MAAM,kBAAkB,EAAE,YAkChC,CAAC"}
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.unicodeAttacksRule = void 0;
4
+ const code_block_context_1 = require("../code-block-context");
5
+ /**
6
+ * Detects suspicious Unicode characters that can be used to hide text,
7
+ * create visually misleading content, or smuggle instructions.
8
+ *
9
+ * Note: We use individual character alternation instead of character classes
10
+ * for zero-width characters because some (like ZWJ U+200D) are joiners that
11
+ * compose emoji sequences, and biome's `noMisleadingCharacterClass` rule
12
+ * flags them inside character classes.
13
+ */
14
+ const UNICODE_ATTACK_PATTERNS = [
15
+ // Zero-width characters (ZWSP, ZWNJ, ZWJ, zero-width no-break space)
16
+ // Using alternation instead of character class to avoid noMisleadingCharacterClass
17
+ {
18
+ pattern: /\u200B|\u200C|\u200D|\uFEFF/g,
19
+ description: 'Zero-width character detected (potential hidden text)',
20
+ severity: 'high',
21
+ },
22
+ // Unicode Tags Block (U+E0001-U+E007F) — used for invisible text smuggling
23
+ {
24
+ pattern: /[\u{E0001}-\u{E007F}]/gu,
25
+ description: 'Unicode Tags Block character (invisible text smuggling)',
26
+ severity: 'critical',
27
+ },
28
+ // Right-to-left override/embedding (text direction attacks)
29
+ {
30
+ pattern: /[\u202A-\u202E\u2066-\u2069]/g,
31
+ description: 'Bidirectional text override character (visual spoofing)',
32
+ severity: 'high',
33
+ },
34
+ // Interlinear annotation markers
35
+ {
36
+ pattern: /[\uFFF9-\uFFFB]/g,
37
+ description: 'Interlinear annotation character',
38
+ severity: 'medium',
39
+ },
40
+ // Homoglyph-heavy sequences — Cyrillic/Greek characters in otherwise Latin text
41
+ {
42
+ pattern: /[a-zA-Z]+[\u0400-\u04FF]+|[\u0400-\u04FF]+[a-zA-Z]+/g,
43
+ description: 'Mixed Latin/Cyrillic script (potential homoglyph attack)',
44
+ severity: 'medium',
45
+ },
46
+ // Object replacement character that can hide content
47
+ {
48
+ pattern: /\uFFFC/g,
49
+ description: 'Object replacement character',
50
+ severity: 'low',
51
+ },
52
+ ];
53
+ exports.unicodeAttacksRule = {
54
+ id: 'unicode-attacks',
55
+ category: 'unicode-attacks',
56
+ description: 'Detects suspicious Unicode characters — zero-width chars, bidi overrides, Tags Block, homoglyphs',
57
+ defaultSeverity: 'high',
58
+ detect(context) {
59
+ const findings = [];
60
+ const codeBlockRanges = (0, code_block_context_1.parseCodeBlockRanges)(context.body);
61
+ for (const { pattern, description, severity } of UNICODE_ATTACK_PATTERNS) {
62
+ // matchAll requires a fresh regex or one with global flag
63
+ const globalPattern = pattern.global
64
+ ? new RegExp(pattern.source, pattern.flags)
65
+ : new RegExp(pattern.source, `${pattern.flags}g`);
66
+ for (const match of context.body.matchAll(globalPattern)) {
67
+ const line = (0, code_block_context_1.getLineNumber)(context.body, match.index ?? 0);
68
+ const inCodeBlock = (0, code_block_context_1.isLineInCodeBlock)(line, codeBlockRanges);
69
+ findings.push({
70
+ ruleId: 'unicode-attacks',
71
+ category: 'unicode-attacks',
72
+ severity: inCodeBlock ? 'info' : severity,
73
+ message: `Unicode attack: ${description}`,
74
+ evidence: `U+${match[0].codePointAt(0)?.toString(16).toUpperCase().padStart(4, '0')}`,
75
+ line,
76
+ inCodeBlock,
77
+ });
78
+ }
79
+ }
80
+ return findings;
81
+ },
82
+ };
83
+ //# sourceMappingURL=unicode-attacks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unicode-attacks.js","sourceRoot":"","sources":["../../../src/security-scanner/rules/unicode-attacks.ts"],"names":[],"mappings":";;;AAAA,8DAA+F;AAG/F;;;;;;;;GAQG;AACH,MAAM,uBAAuB,GAIvB;IACJ,qEAAqE;IACrE,mFAAmF;IACnF;QACE,OAAO,EAAE,8BAA8B;QACvC,WAAW,EAAE,uDAAuD;QACpE,QAAQ,EAAE,MAAM;KACjB;IACD,2EAA2E;IAC3E;QACE,OAAO,EAAE,yBAAyB;QAClC,WAAW,EAAE,yDAAyD;QACtE,QAAQ,EAAE,UAAU;KACrB;IACD,4DAA4D;IAC5D;QACE,OAAO,EAAE,+BAA+B;QACxC,WAAW,EAAE,yDAAyD;QACtE,QAAQ,EAAE,MAAM;KACjB;IACD,iCAAiC;IACjC;QACE,OAAO,EAAE,kBAAkB;QAC3B,WAAW,EAAE,kCAAkC;QAC/C,QAAQ,EAAE,QAAQ;KACnB;IACD,gFAAgF;IAChF;QACE,OAAO,EAAE,sDAAsD;QAC/D,WAAW,EAAE,0DAA0D;QACvE,QAAQ,EAAE,QAAQ;KACnB;IACD,qDAAqD;IACrD;QACE,OAAO,EAAE,SAAS;QAClB,WAAW,EAAE,8BAA8B;QAC3C,QAAQ,EAAE,KAAK;KAChB;CACF,CAAC;AAEW,QAAA,kBAAkB,GAAiB;IAC9C,EAAE,EAAE,iBAAiB;IACrB,QAAQ,EAAE,iBAAiB;IAC3B,WAAW,EACT,kGAAkG;IACpG,eAAe,EAAE,MAAM;IACvB,MAAM,CAAC,OAAO;QACZ,MAAM,QAAQ,GAAsB,EAAE,CAAC;QACvC,MAAM,eAAe,GAAG,IAAA,yCAAoB,EAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAE3D,KAAK,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,uBAAuB,EAAE,CAAC;YACzE,0DAA0D;YAC1D,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM;gBAClC,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC;gBAC3C,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC;YAEpD,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;gBACzD,MAAM,IAAI,GAAG,IAAA,kCAAa,EAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC;gBAC3D,MAAM,WAAW,GAAG,IAAA,sCAAiB,EAAC,IAAI,EAAE,eAAe,CAAC,CAAC;gBAE7D,QAAQ,CAAC,IAAI,CAAC;oBACZ,MAAM,EAAE,iBAAiB;oBACzB,QAAQ,EAAE,iBAAiB;oBAC3B,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ;oBACzC,OAAO,EAAE,mBAAmB,WAAW,EAAE;oBACzC,QAAQ,EAAE,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE;oBACrF,IAAI;oBACJ,WAAW;iBACZ,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { SecurityRule } from '../types';
2
+ export declare const urlThreatsRule: SecurityRule;
3
+ //# sourceMappingURL=url-threats.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url-threats.d.ts","sourceRoot":"","sources":["../../../src/security-scanner/rules/url-threats.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAmB,YAAY,EAAE,MAAM,UAAU,CAAC;AA+D9D,eAAO,MAAM,cAAc,EAAE,YA6C5B,CAAC"}
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.urlThreatsRule = void 0;
4
+ const code_block_context_1 = require("../code-block-context");
5
+ const match_utils_1 = require("../match-utils");
6
+ /**
7
+ * URL shortener and redirect service domains that can disguise malicious destinations.
8
+ */
9
+ const URL_SHORTENER_DOMAINS = [
10
+ 'bit.ly',
11
+ 'tinyurl.com',
12
+ 't.co',
13
+ 'goo.gl',
14
+ 'ow.ly',
15
+ 'is.gd',
16
+ 'buff.ly',
17
+ 'adf.ly',
18
+ 'bl.ink',
19
+ 'lnkd.in',
20
+ 'soo.gd',
21
+ 'rb.gy',
22
+ 's.id',
23
+ 'v.gd',
24
+ 'clck.ru',
25
+ 'shorturl.at',
26
+ 'cutt.ly',
27
+ ];
28
+ /**
29
+ * Patterns for URL-based threats — shorteners, punycode, suspicious TLDs,
30
+ * and IP-based URLs that may disguise malicious destinations.
31
+ */
32
+ const URL_THREAT_PATTERNS = [
33
+ // Punycode domains (internationalized domain names that can mimic legitimate domains)
34
+ {
35
+ pattern: /https?:\/\/xn--[a-z0-9-]+\.[a-z]{2,}/gi,
36
+ description: 'Punycode domain (potential homograph attack)',
37
+ },
38
+ // IP address URLs (decimal)
39
+ {
40
+ pattern: /https?:\/\/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(?::\d+)?(?:\/[^\s]*)?/g,
41
+ description: 'IP-address URL (no domain name — potential evasion)',
42
+ },
43
+ // IP address URLs (decimal-encoded single integer, e.g., http://2130706433)
44
+ {
45
+ pattern: /https?:\/\/\d{8,10}(?:\/[^\s]*)?/g,
46
+ description: 'Decimal-encoded IP URL (obfuscated destination)',
47
+ },
48
+ // Hex-encoded URL
49
+ {
50
+ pattern: /https?:\/\/0x[0-9a-fA-F]+(?:\/[^\s]*)?/g,
51
+ description: 'Hex-encoded IP URL (obfuscated destination)',
52
+ },
53
+ // URLs with excessive redirects via query params
54
+ {
55
+ pattern: /https?:\/\/[^\s]*(?:redirect|redir|goto|next|return|url|continue|destination)\s*=\s*https?(?:%3A|:)/gi,
56
+ description: 'URL with redirect parameter (potential open redirect)',
57
+ },
58
+ // URLs with @ symbol (credential stuffing in URL)
59
+ {
60
+ pattern: /https?:\/\/[^@\s]+@[^@\s]+\.[a-z]{2,}/gi,
61
+ description: 'URL with embedded credentials (user@host format)',
62
+ },
63
+ ];
64
+ exports.urlThreatsRule = {
65
+ id: 'url-threats',
66
+ category: 'url-threats',
67
+ description: 'Detects URL-based threats — shorteners, punycode domains, IP-based URLs, open redirects',
68
+ defaultSeverity: 'medium',
69
+ detect(context) {
70
+ const findings = [];
71
+ const codeBlockRanges = (0, code_block_context_1.parseCodeBlockRanges)(context.body);
72
+ // Check for URL shorteners
73
+ const shortenerPattern = new RegExp(`https?:\\/\\/(?:${URL_SHORTENER_DOMAINS.map((d) => d.replace(/\./g, '\\.')).join('|')})\\/[^\\s"')<]+`, 'gi');
74
+ findings.push(...(0, match_utils_1.matchPattern)(context.body, shortenerPattern, codeBlockRanges, 'url-threats', 'url-threats', 'Shortened URL (destination unknown — could disguise malicious target)', 'medium'));
75
+ // Check other URL threat patterns
76
+ for (const { pattern, description } of URL_THREAT_PATTERNS) {
77
+ findings.push(...(0, match_utils_1.matchPattern)(context.body, pattern, codeBlockRanges, 'url-threats', 'url-threats', description, 'medium'));
78
+ }
79
+ return findings;
80
+ },
81
+ };
82
+ //# sourceMappingURL=url-threats.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url-threats.js","sourceRoot":"","sources":["../../../src/security-scanner/rules/url-threats.ts"],"names":[],"mappings":";;;AAAA,8DAA6D;AAC7D,gDAA8C;AAG9C;;GAEG;AACH,MAAM,qBAAqB,GAAG;IAC5B,QAAQ;IACR,aAAa;IACb,MAAM;IACN,QAAQ;IACR,OAAO;IACP,OAAO;IACP,SAAS;IACT,QAAQ;IACR,QAAQ;IACR,SAAS;IACT,QAAQ;IACR,OAAO;IACP,MAAM;IACN,MAAM;IACN,SAAS;IACT,aAAa;IACb,SAAS;CACV,CAAC;AAEF;;;GAGG;AACH,MAAM,mBAAmB,GAA+C;IACtE,sFAAsF;IACtF;QACE,OAAO,EAAE,wCAAwC;QACjD,WAAW,EAAE,8CAA8C;KAC5D;IACD,4BAA4B;IAC5B;QACE,OAAO,EAAE,sEAAsE;QAC/E,WAAW,EAAE,qDAAqD;KACnE;IACD,4EAA4E;IAC5E;QACE,OAAO,EAAE,mCAAmC;QAC5C,WAAW,EAAE,iDAAiD;KAC/D;IACD,kBAAkB;IAClB;QACE,OAAO,EAAE,yCAAyC;QAClD,WAAW,EAAE,6CAA6C;KAC3D;IACD,iDAAiD;IACjD;QACE,OAAO,EACL,uGAAuG;QACzG,WAAW,EAAE,uDAAuD;KACrE;IACD,kDAAkD;IAClD;QACE,OAAO,EAAE,yCAAyC;QAClD,WAAW,EAAE,kDAAkD;KAChE;CACF,CAAC;AAEW,QAAA,cAAc,GAAiB;IAC1C,EAAE,EAAE,aAAa;IACjB,QAAQ,EAAE,aAAa;IACvB,WAAW,EACT,yFAAyF;IAC3F,eAAe,EAAE,QAAQ;IACzB,MAAM,CAAC,OAAO;QACZ,MAAM,QAAQ,GAAsB,EAAE,CAAC;QACvC,MAAM,eAAe,GAAG,IAAA,yCAAoB,EAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAE3D,2BAA2B;QAC3B,MAAM,gBAAgB,GAAG,IAAI,MAAM,CACjC,mBAAmB,qBAAqB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,iBAAiB,EACvG,IAAI,CACL,CAAC;QAEF,QAAQ,CAAC,IAAI,CACX,GAAG,IAAA,0BAAY,EACb,OAAO,CAAC,IAAI,EACZ,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,aAAa,EACb,uEAAuE,EACvE,QAAQ,CACT,CACF,CAAC;QAEF,kCAAkC;QAClC,KAAK,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,mBAAmB,EAAE,CAAC;YAC3D,QAAQ,CAAC,IAAI,CACX,GAAG,IAAA,0BAAY,EACb,OAAO,CAAC,IAAI,EACZ,OAAO,EACP,eAAe,EACf,aAAa,EACb,aAAa,EACb,WAAW,EACX,QAAQ,CACT,CACF,CAAC;QACJ,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { SecurityRule } from '../types';
2
+ export declare const xssHtmlInjectionRule: SecurityRule;
3
+ //# sourceMappingURL=xss-html-injection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xss-html-injection.d.ts","sourceRoot":"","sources":["../../../src/security-scanner/rules/xss-html-injection.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAmB,YAAY,EAAE,MAAM,UAAU,CAAC;AAiE9D,eAAO,MAAM,oBAAoB,EAAE,YAyBlC,CAAC"}
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.xssHtmlInjectionRule = void 0;
4
+ const code_block_context_1 = require("../code-block-context");
5
+ const match_utils_1 = require("../match-utils");
6
+ /**
7
+ * Patterns for XSS and HTML injection attacks in markdown.
8
+ * These detect script tags, event handlers, and dangerous URI schemes
9
+ * that could execute code when rendered.
10
+ */
11
+ const XSS_HTML_PATTERNS = [
12
+ // Script tags (including obfuscated variants)
13
+ {
14
+ pattern: /<\/?script\b[^>]*>/gi,
15
+ description: 'Script tag detected',
16
+ },
17
+ // Event handler attributes (onclick, onerror, onload, etc.)
18
+ {
19
+ pattern: /<\w+[^>]*\bon\w+\s*=\s*["'][^"']*["'][^>]*>/gi,
20
+ description: 'HTML element with inline event handler',
21
+ },
22
+ // javascript: URI scheme
23
+ {
24
+ pattern: /(?:href|src|action|formaction|data)\s*=\s*["']?\s*javascript\s*:/gi,
25
+ description: 'JavaScript URI scheme in HTML attribute',
26
+ },
27
+ // data: URI with script content
28
+ {
29
+ pattern: /(?:href|src)\s*=\s*["']?\s*data\s*:\s*text\/html/gi,
30
+ description: 'Data URI with HTML content (potential XSS)',
31
+ },
32
+ // Markdown link with javascript: URI
33
+ {
34
+ pattern: /\[[^\]]*\]\(\s*javascript\s*:[^)]*\)/gi,
35
+ description: 'Markdown link with javascript: URI',
36
+ },
37
+ // iframe injection
38
+ {
39
+ pattern: /<iframe\b[^>]*>/gi,
40
+ description: 'Iframe injection',
41
+ },
42
+ // object/embed tags (can execute arbitrary content)
43
+ {
44
+ pattern: /<(?:object|embed|applet)\b[^>]*>/gi,
45
+ description: 'Object/embed/applet tag (potential code execution)',
46
+ },
47
+ // SVG with script or event handlers
48
+ {
49
+ pattern: /<svg\b[^>]*>[\s\S]*?(?:<script|on\w+=)/gi,
50
+ description: 'SVG element with embedded script or event handler',
51
+ },
52
+ // CSS expression/behavior (IE-specific but still relevant for detection)
53
+ {
54
+ pattern: /expression\s*\([^)]*\)|behavior\s*:\s*url\s*\(/gi,
55
+ description: 'CSS expression or behavior (potential code execution)',
56
+ },
57
+ // Meta refresh redirect
58
+ {
59
+ pattern: /<meta[^>]*http-equiv\s*=\s*["']?refresh["']?[^>]*>/gi,
60
+ description: 'Meta refresh redirect',
61
+ },
62
+ // Form tags (potential for phishing)
63
+ {
64
+ pattern: /<form\b[^>]*action\s*=\s*["']https?:\/\/[^"']*["'][^>]*>/gi,
65
+ description: 'HTML form with external action URL (potential phishing)',
66
+ },
67
+ ];
68
+ exports.xssHtmlInjectionRule = {
69
+ id: 'xss-html-injection',
70
+ category: 'xss-html-injection',
71
+ description: 'Detects XSS and HTML injection — script tags, event handlers, dangerous URIs',
72
+ defaultSeverity: 'high',
73
+ detect(context) {
74
+ const findings = [];
75
+ const codeBlockRanges = (0, code_block_context_1.parseCodeBlockRanges)(context.body);
76
+ for (const { pattern, description } of XSS_HTML_PATTERNS) {
77
+ findings.push(...(0, match_utils_1.matchPattern)(context.body, pattern, codeBlockRanges, 'xss-html-injection', 'xss-html-injection', description, 'high'));
78
+ }
79
+ return findings;
80
+ },
81
+ };
82
+ //# sourceMappingURL=xss-html-injection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xss-html-injection.js","sourceRoot":"","sources":["../../../src/security-scanner/rules/xss-html-injection.ts"],"names":[],"mappings":";;;AAAA,8DAA6D;AAC7D,gDAA8C;AAG9C;;;;GAIG;AACH,MAAM,iBAAiB,GAA+C;IACpE,8CAA8C;IAC9C;QACE,OAAO,EAAE,sBAAsB;QAC/B,WAAW,EAAE,qBAAqB;KACnC;IACD,4DAA4D;IAC5D;QACE,OAAO,EAAE,+CAA+C;QACxD,WAAW,EAAE,wCAAwC;KACtD;IACD,yBAAyB;IACzB;QACE,OAAO,EAAE,oEAAoE;QAC7E,WAAW,EAAE,yCAAyC;KACvD;IACD,gCAAgC;IAChC;QACE,OAAO,EAAE,oDAAoD;QAC7D,WAAW,EAAE,4CAA4C;KAC1D;IACD,qCAAqC;IACrC;QACE,OAAO,EAAE,wCAAwC;QACjD,WAAW,EAAE,oCAAoC;KAClD;IACD,mBAAmB;IACnB;QACE,OAAO,EAAE,mBAAmB;QAC5B,WAAW,EAAE,kBAAkB;KAChC;IACD,oDAAoD;IACpD;QACE,OAAO,EAAE,oCAAoC;QAC7C,WAAW,EAAE,oDAAoD;KAClE;IACD,oCAAoC;IACpC;QACE,OAAO,EAAE,0CAA0C;QACnD,WAAW,EAAE,mDAAmD;KACjE;IACD,yEAAyE;IACzE;QACE,OAAO,EAAE,kDAAkD;QAC3D,WAAW,EAAE,uDAAuD;KACrE;IACD,wBAAwB;IACxB;QACE,OAAO,EAAE,sDAAsD;QAC/D,WAAW,EAAE,uBAAuB;KACrC;IACD,qCAAqC;IACrC;QACE,OAAO,EAAE,4DAA4D;QACrE,WAAW,EAAE,yDAAyD;KACvE;CACF,CAAC;AAEW,QAAA,oBAAoB,GAAiB;IAChD,EAAE,EAAE,oBAAoB;IACxB,QAAQ,EAAE,oBAAoB;IAC9B,WAAW,EAAE,8EAA8E;IAC3F,eAAe,EAAE,MAAM;IACvB,MAAM,CAAC,OAAO;QACZ,MAAM,QAAQ,GAAsB,EAAE,CAAC;QACvC,MAAM,eAAe,GAAG,IAAA,yCAAoB,EAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAE3D,KAAK,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,iBAAiB,EAAE,CAAC;YACzD,QAAQ,CAAC,IAAI,CACX,GAAG,IAAA,0BAAY,EACb,OAAO,CAAC,IAAI,EACZ,OAAO,EACP,eAAe,EACf,oBAAoB,EACpB,oBAAoB,EACpB,WAAW,EACX,MAAM,CACP,CACF,CAAC;QACJ,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF,CAAC"}
@@ -0,0 +1,45 @@
1
+ import type { DossierFrontmatter } from '../types';
2
+ export type SecuritySeverity = 'critical' | 'high' | 'medium' | 'low' | 'info';
3
+ export type SecurityCategory = 'prompt-injection' | 'agent-hijacking' | 'dangerous-execution' | 'unicode-attacks' | 'data-exfiltration' | 'xss-html-injection' | 'url-threats' | 'supply-chain';
4
+ export interface SecurityFinding {
5
+ ruleId: string;
6
+ category: SecurityCategory;
7
+ severity: SecuritySeverity;
8
+ message: string;
9
+ /** The matched text or pattern that triggered the finding */
10
+ evidence?: string;
11
+ /** Approximate line number in the body (1-based) */
12
+ line?: number;
13
+ /** Whether the finding is inside a fenced code block (lower confidence) */
14
+ inCodeBlock: boolean;
15
+ }
16
+ export interface SecurityRuleContext {
17
+ frontmatter: DossierFrontmatter;
18
+ body: string;
19
+ raw: string;
20
+ }
21
+ export interface SecurityRule {
22
+ id: string;
23
+ category: SecurityCategory;
24
+ description: string;
25
+ defaultSeverity: SecuritySeverity;
26
+ detect(context: SecurityRuleContext): SecurityFinding[];
27
+ }
28
+ export type SecurityRuleSeverityOverride = SecuritySeverity | 'off';
29
+ export interface SecurityScanConfig {
30
+ rules: Record<string, SecurityRuleSeverityOverride>;
31
+ /** Minimum severity to include in results (default: 'info') */
32
+ minSeverity?: SecuritySeverity;
33
+ }
34
+ export interface SecurityReport {
35
+ file?: string;
36
+ findings: SecurityFinding[];
37
+ criticalCount: number;
38
+ highCount: number;
39
+ mediumCount: number;
40
+ lowCount: number;
41
+ infoCount: number;
42
+ /** Overall risk verdict */
43
+ verdict: 'PASS' | 'WARN' | 'FAIL';
44
+ }
45
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/security-scanner/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAEnD,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;AAE/E,MAAM,MAAM,gBAAgB,GACxB,kBAAkB,GAClB,iBAAiB,GACjB,qBAAqB,GACrB,iBAAiB,GACjB,mBAAmB,GACnB,oBAAoB,GACpB,aAAa,GACb,cAAc,CAAC;AAEnB,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oDAAoD;IACpD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,kBAAkB,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,gBAAgB,CAAC;IAClC,MAAM,CAAC,OAAO,EAAE,mBAAmB,GAAG,eAAe,EAAE,CAAC;CACzD;AAED,MAAM,MAAM,4BAA4B,GAAG,gBAAgB,GAAG,KAAK,CAAC;AAEpE,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,4BAA4B,CAAC,CAAC;IACpD,+DAA+D;IAC/D,WAAW,CAAC,EAAE,gBAAgB,CAAC;CAChC;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,2BAA2B;IAC3B,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;CACnC"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/security-scanner/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,45 @@
1
+ export declare const VALID_TRACE_STATUSES: readonly ["running", "success", "failed", "cancelled"];
2
+ export type TraceStatus = (typeof VALID_TRACE_STATUSES)[number];
3
+ export interface TraceInput {
4
+ trace_id: string;
5
+ dossier: {
6
+ title: string;
7
+ version: string;
8
+ [key: string]: unknown;
9
+ };
10
+ agent?: {
11
+ name?: string;
12
+ version?: string;
13
+ [key: string]: unknown;
14
+ };
15
+ started_at: string;
16
+ completed_at?: string;
17
+ duration_ms?: number;
18
+ status: TraceStatus;
19
+ [key: string]: unknown;
20
+ }
21
+ export interface TraceUpdate {
22
+ status?: TraceStatus;
23
+ completed_at?: string;
24
+ duration_ms?: number;
25
+ [key: string]: unknown;
26
+ }
27
+ export interface StepInput {
28
+ step_id: string;
29
+ type: string;
30
+ timestamp?: string;
31
+ [key: string]: unknown;
32
+ }
33
+ export interface TraceRecorderOptions {
34
+ url?: string;
35
+ token?: string;
36
+ fetch?: typeof fetch;
37
+ }
38
+ export interface TraceRecorder {
39
+ readonly enabled: boolean;
40
+ create(input: TraceInput): Promise<void>;
41
+ appendStep(traceId: string, step: StepInput): Promise<void>;
42
+ complete(traceId: string, update: TraceUpdate): Promise<void>;
43
+ }
44
+ export declare function createTraceRecorder(opts?: TraceRecorderOptions): TraceRecorder;
45
+ //# sourceMappingURL=trace-recorder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trace-recorder.d.ts","sourceRoot":"","sources":["../src/trace-recorder.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,oBAAoB,wDAAyD,CAAC;AAC3F,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEhE,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IACpE,KAAK,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IACpE,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,WAAW,CAAC;IACpB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,oBAAoB;IACnC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5D,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/D;AAED,wBAAgB,mBAAmB,CAAC,IAAI,GAAE,oBAAyB,GAAG,aAAa,CAwClF"}
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ // Trace recorder for dossier execution. Opt-in: returns a no-op recorder
3
+ // unless both DOSSIER_TRACE_URL and DOSSIER_TRACE_TOKEN (or the equivalent
4
+ // opts) are provided. Fire-and-forget: network failures are swallowed so
5
+ // tracing never breaks the agent run.
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.VALID_TRACE_STATUSES = void 0;
8
+ exports.createTraceRecorder = createTraceRecorder;
9
+ exports.VALID_TRACE_STATUSES = ['running', 'success', 'failed', 'cancelled'];
10
+ function createTraceRecorder(opts = {}) {
11
+ const url = opts.url ?? process.env.DOSSIER_TRACE_URL ?? '';
12
+ const token = opts.token ?? process.env.DOSSIER_TRACE_TOKEN ?? '';
13
+ const fetchImpl = opts.fetch ?? globalThis.fetch;
14
+ if (!url || !token || !fetchImpl) {
15
+ return {
16
+ enabled: false,
17
+ create: noop,
18
+ appendStep: noop,
19
+ complete: noop,
20
+ };
21
+ }
22
+ const base = url.replace(/\/+$/, '');
23
+ const headers = {
24
+ 'content-type': 'application/json',
25
+ authorization: `Bearer ${token}`,
26
+ };
27
+ const send = (method, path, body) => Promise.resolve()
28
+ .then(() => fetchImpl(`${base}${path}`, {
29
+ method,
30
+ headers,
31
+ body: JSON.stringify(body),
32
+ }))
33
+ .then(() => undefined)
34
+ .catch(() => undefined);
35
+ return {
36
+ enabled: true,
37
+ create: (input) => send('POST', '/api/v1/traces', input),
38
+ appendStep: (traceId, step) => send('POST', `/api/v1/traces/${encodeURIComponent(traceId)}/steps`, step),
39
+ complete: (traceId, update) => send('PATCH', `/api/v1/traces/${encodeURIComponent(traceId)}`, update),
40
+ };
41
+ }
42
+ async function noop() { }
43
+ //# sourceMappingURL=trace-recorder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trace-recorder.js","sourceRoot":"","sources":["../src/trace-recorder.ts"],"names":[],"mappings":";AAAA,yEAAyE;AACzE,2EAA2E;AAC3E,yEAAyE;AACzE,sCAAsC;;;AA2CtC,kDAwCC;AAjFY,QAAA,oBAAoB,GAAG,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,CAAU,CAAC;AAyC3F,SAAgB,mBAAmB,CAAC,OAA6B,EAAE;IACjE,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,EAAE,CAAC;IAC5D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,EAAE,CAAC;IAClE,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK,CAAC;IAEjD,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,IAAI,CAAC,SAAS,EAAE,CAAC;QACjC,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,IAAI;YACZ,UAAU,EAAE,IAAI;YAChB,QAAQ,EAAE,IAAI;SACf,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACrC,MAAM,OAAO,GAAG;QACd,cAAc,EAAE,kBAAkB;QAClC,aAAa,EAAE,UAAU,KAAK,EAAE;KACjC,CAAC;IAEF,MAAM,IAAI,GAAG,CAAC,MAAc,EAAE,IAAY,EAAE,IAAa,EAAiB,EAAE,CAC1E,OAAO,CAAC,OAAO,EAAE;SACd,IAAI,CAAC,GAAG,EAAE,CACT,SAAS,CAAC,GAAG,IAAI,GAAG,IAAI,EAAE,EAAE;QAC1B,MAAM;QACN,OAAO;QACP,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;KAC3B,CAAC,CACH;SACA,IAAI,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC;SACrB,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAE5B,OAAO;QACL,OAAO,EAAE,IAAI;QACb,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,gBAAgB,EAAE,KAAK,CAAC;QACxD,UAAU,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,CAC5B,IAAI,CAAC,MAAM,EAAE,kBAAkB,kBAAkB,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC;QAC3E,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,CAC5B,IAAI,CAAC,OAAO,EAAE,kBAAkB,kBAAkB,CAAC,OAAO,CAAC,EAAE,EAAE,MAAM,CAAC;KACzE,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,IAAI,KAAmB,CAAC"}