@rexymayderio/sentinel 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 (191) hide show
  1. package/README.md +295 -0
  2. package/dist/acquire/acquirer.d.ts +38 -0
  3. package/dist/acquire/acquirer.d.ts.map +1 -0
  4. package/dist/acquire/acquirer.js +178 -0
  5. package/dist/acquire/acquirer.js.map +1 -0
  6. package/dist/adapters/cli-approval-prompt.d.ts +13 -0
  7. package/dist/adapters/cli-approval-prompt.d.ts.map +1 -0
  8. package/dist/adapters/cli-approval-prompt.js +44 -0
  9. package/dist/adapters/cli-approval-prompt.js.map +1 -0
  10. package/dist/adapters/github-repo-client.d.ts +9 -0
  11. package/dist/adapters/github-repo-client.d.ts.map +1 -0
  12. package/dist/adapters/github-repo-client.js +48 -0
  13. package/dist/adapters/github-repo-client.js.map +1 -0
  14. package/dist/adapters/index.d.ts +5 -0
  15. package/dist/adapters/index.d.ts.map +1 -0
  16. package/dist/adapters/index.js +5 -0
  17. package/dist/adapters/index.js.map +1 -0
  18. package/dist/adapters/node-process-runner.d.ts +8 -0
  19. package/dist/adapters/node-process-runner.d.ts.map +1 -0
  20. package/dist/adapters/node-process-runner.js +21 -0
  21. package/dist/adapters/node-process-runner.js.map +1 -0
  22. package/dist/adapters/npm-registry-client.d.ts +8 -0
  23. package/dist/adapters/npm-registry-client.d.ts.map +1 -0
  24. package/dist/adapters/npm-registry-client.js +66 -0
  25. package/dist/adapters/npm-registry-client.js.map +1 -0
  26. package/dist/analyzers/ai-prompt-analyzer.d.ts +7 -0
  27. package/dist/analyzers/ai-prompt-analyzer.d.ts.map +1 -0
  28. package/dist/analyzers/ai-prompt-analyzer.js +88 -0
  29. package/dist/analyzers/ai-prompt-analyzer.js.map +1 -0
  30. package/dist/analyzers/analyzer.d.ts +14 -0
  31. package/dist/analyzers/analyzer.d.ts.map +1 -0
  32. package/dist/analyzers/analyzer.js +11 -0
  33. package/dist/analyzers/analyzer.js.map +1 -0
  34. package/dist/analyzers/dependency-analyzer.d.ts +10 -0
  35. package/dist/analyzers/dependency-analyzer.d.ts.map +1 -0
  36. package/dist/analyzers/dependency-analyzer.js +79 -0
  37. package/dist/analyzers/dependency-analyzer.js.map +1 -0
  38. package/dist/analyzers/index.d.ts +13 -0
  39. package/dist/analyzers/index.d.ts.map +1 -0
  40. package/dist/analyzers/index.js +30 -0
  41. package/dist/analyzers/index.js.map +1 -0
  42. package/dist/analyzers/install-script-analyzer.d.ts +7 -0
  43. package/dist/analyzers/install-script-analyzer.d.ts.map +1 -0
  44. package/dist/analyzers/install-script-analyzer.js +64 -0
  45. package/dist/analyzers/install-script-analyzer.js.map +1 -0
  46. package/dist/analyzers/match-evidence.d.ts +6 -0
  47. package/dist/analyzers/match-evidence.d.ts.map +1 -0
  48. package/dist/analyzers/match-evidence.js +15 -0
  49. package/dist/analyzers/match-evidence.js.map +1 -0
  50. package/dist/analyzers/metadata-analyzer.d.ts +7 -0
  51. package/dist/analyzers/metadata-analyzer.d.ts.map +1 -0
  52. package/dist/analyzers/metadata-analyzer.js +105 -0
  53. package/dist/analyzers/metadata-analyzer.js.map +1 -0
  54. package/dist/analyzers/network-analyzer.d.ts +7 -0
  55. package/dist/analyzers/network-analyzer.d.ts.map +1 -0
  56. package/dist/analyzers/network-analyzer.js +47 -0
  57. package/dist/analyzers/network-analyzer.js.map +1 -0
  58. package/dist/analyzers/rules/index.d.ts +19 -0
  59. package/dist/analyzers/rules/index.d.ts.map +1 -0
  60. package/dist/analyzers/rules/index.js +70 -0
  61. package/dist/analyzers/rules/index.js.map +1 -0
  62. package/dist/analyzers/secret-analyzer.d.ts +7 -0
  63. package/dist/analyzers/secret-analyzer.d.ts.map +1 -0
  64. package/dist/analyzers/secret-analyzer.js +33 -0
  65. package/dist/analyzers/secret-analyzer.js.map +1 -0
  66. package/dist/analyzers/source-analyzer.d.ts +7 -0
  67. package/dist/analyzers/source-analyzer.d.ts.map +1 -0
  68. package/dist/analyzers/source-analyzer.js +73 -0
  69. package/dist/analyzers/source-analyzer.js.map +1 -0
  70. package/dist/analyzers/static-code-analyzer.d.ts +7 -0
  71. package/dist/analyzers/static-code-analyzer.d.ts.map +1 -0
  72. package/dist/analyzers/static-code-analyzer.js +67 -0
  73. package/dist/analyzers/static-code-analyzer.js.map +1 -0
  74. package/dist/analyzers/test-path.d.ts +2 -0
  75. package/dist/analyzers/test-path.d.ts.map +1 -0
  76. package/dist/analyzers/test-path.js +32 -0
  77. package/dist/analyzers/test-path.js.map +1 -0
  78. package/dist/cli/index.d.ts +3 -0
  79. package/dist/cli/index.d.ts.map +1 -0
  80. package/dist/cli/index.js +176 -0
  81. package/dist/cli/index.js.map +1 -0
  82. package/dist/cli/spinner.d.ts +5 -0
  83. package/dist/cli/spinner.d.ts.map +1 -0
  84. package/dist/cli/spinner.js +39 -0
  85. package/dist/cli/spinner.js.map +1 -0
  86. package/dist/core/index.d.ts +3 -0
  87. package/dist/core/index.d.ts.map +1 -0
  88. package/dist/core/index.js +3 -0
  89. package/dist/core/index.js.map +1 -0
  90. package/dist/core/permissions.d.ts +4 -0
  91. package/dist/core/permissions.d.ts.map +1 -0
  92. package/dist/core/permissions.js +28 -0
  93. package/dist/core/permissions.js.map +1 -0
  94. package/dist/core/sentinel.d.ts +32 -0
  95. package/dist/core/sentinel.d.ts.map +1 -0
  96. package/dist/core/sentinel.js +164 -0
  97. package/dist/core/sentinel.js.map +1 -0
  98. package/dist/domain/artifact.d.ts +34 -0
  99. package/dist/domain/artifact.d.ts.map +1 -0
  100. package/dist/domain/artifact.js +2 -0
  101. package/dist/domain/artifact.js.map +1 -0
  102. package/dist/domain/finding.d.ts +22 -0
  103. package/dist/domain/finding.d.ts.map +1 -0
  104. package/dist/domain/finding.js +30 -0
  105. package/dist/domain/finding.js.map +1 -0
  106. package/dist/domain/index.d.ts +7 -0
  107. package/dist/domain/index.d.ts.map +1 -0
  108. package/dist/domain/index.js +7 -0
  109. package/dist/domain/index.js.map +1 -0
  110. package/dist/domain/permission.d.ts +8 -0
  111. package/dist/domain/permission.d.ts.map +1 -0
  112. package/dist/domain/permission.js +21 -0
  113. package/dist/domain/permission.js.map +1 -0
  114. package/dist/domain/report.d.ts +35 -0
  115. package/dist/domain/report.d.ts.map +1 -0
  116. package/dist/domain/report.js +2 -0
  117. package/dist/domain/report.js.map +1 -0
  118. package/dist/domain/risk.d.ts +14 -0
  119. package/dist/domain/risk.d.ts.map +1 -0
  120. package/dist/domain/risk.js +15 -0
  121. package/dist/domain/risk.js.map +1 -0
  122. package/dist/domain/target.d.ts +12 -0
  123. package/dist/domain/target.d.ts.map +1 -0
  124. package/dist/domain/target.js +43 -0
  125. package/dist/domain/target.js.map +1 -0
  126. package/dist/engine/data-assessment.d.ts +10 -0
  127. package/dist/engine/data-assessment.d.ts.map +1 -0
  128. package/dist/engine/data-assessment.js +39 -0
  129. package/dist/engine/data-assessment.js.map +1 -0
  130. package/dist/engine/default-policy.d.ts +16 -0
  131. package/dist/engine/default-policy.d.ts.map +1 -0
  132. package/dist/engine/default-policy.js +15 -0
  133. package/dist/engine/default-policy.js.map +1 -0
  134. package/dist/engine/index.d.ts +4 -0
  135. package/dist/engine/index.d.ts.map +1 -0
  136. package/dist/engine/index.js +4 -0
  137. package/dist/engine/index.js.map +1 -0
  138. package/dist/engine/policy-engine.d.ts +13 -0
  139. package/dist/engine/policy-engine.d.ts.map +1 -0
  140. package/dist/engine/policy-engine.js +78 -0
  141. package/dist/engine/policy-engine.js.map +1 -0
  142. package/dist/engine/risk-calculator.d.ts +15 -0
  143. package/dist/engine/risk-calculator.d.ts.map +1 -0
  144. package/dist/engine/risk-calculator.js +57 -0
  145. package/dist/engine/risk-calculator.js.map +1 -0
  146. package/dist/factory.d.ts +14 -0
  147. package/dist/factory.d.ts.map +1 -0
  148. package/dist/factory.js +25 -0
  149. package/dist/factory.js.map +1 -0
  150. package/dist/index.d.ts +4 -0
  151. package/dist/index.d.ts.map +1 -0
  152. package/dist/index.js +4 -0
  153. package/dist/index.js.map +1 -0
  154. package/dist/mcp/server.d.ts +3 -0
  155. package/dist/mcp/server.d.ts.map +1 -0
  156. package/dist/mcp/server.js +151 -0
  157. package/dist/mcp/server.js.map +1 -0
  158. package/dist/ports/approval-prompt.d.ts +5 -0
  159. package/dist/ports/approval-prompt.d.ts.map +1 -0
  160. package/dist/ports/approval-prompt.js +2 -0
  161. package/dist/ports/approval-prompt.js.map +1 -0
  162. package/dist/ports/clock.d.ts +5 -0
  163. package/dist/ports/clock.d.ts.map +1 -0
  164. package/dist/ports/clock.js +4 -0
  165. package/dist/ports/clock.js.map +1 -0
  166. package/dist/ports/index.d.ts +6 -0
  167. package/dist/ports/index.d.ts.map +1 -0
  168. package/dist/ports/index.js +6 -0
  169. package/dist/ports/index.js.map +1 -0
  170. package/dist/ports/process-runner.d.ts +12 -0
  171. package/dist/ports/process-runner.d.ts.map +1 -0
  172. package/dist/ports/process-runner.js +2 -0
  173. package/dist/ports/process-runner.js.map +1 -0
  174. package/dist/ports/registry-client.d.ts +14 -0
  175. package/dist/ports/registry-client.d.ts.map +1 -0
  176. package/dist/ports/registry-client.js +2 -0
  177. package/dist/ports/registry-client.js.map +1 -0
  178. package/dist/ports/repo-client.d.ts +18 -0
  179. package/dist/ports/repo-client.d.ts.map +1 -0
  180. package/dist/ports/repo-client.js +2 -0
  181. package/dist/ports/repo-client.js.map +1 -0
  182. package/dist/report/index.d.ts +2 -0
  183. package/dist/report/index.d.ts.map +1 -0
  184. package/dist/report/index.js +2 -0
  185. package/dist/report/index.js.map +1 -0
  186. package/dist/report/report-generator.d.ts +29 -0
  187. package/dist/report/report-generator.d.ts.map +1 -0
  188. package/dist/report/report-generator.js +167 -0
  189. package/dist/report/report-generator.js.map +1 -0
  190. package/package.json +50 -0
  191. package/skills/sentinel/SKILL.md +525 -0
@@ -0,0 +1,105 @@
1
+ import { createFinding } from '../domain/finding.js';
2
+ const MS_PER_DAY = 1000 * 60 * 60 * 24;
3
+ const DAYS_PER_YEAR = 365;
4
+ const NEW_PACKAGE_DAYS = 30;
5
+ const RECENT_UPDATE_DAYS = 7;
6
+ const ESTABLISHED_PACKAGE_DAYS = 365;
7
+ const LOW_DOWNLOAD_THRESHOLD = 100;
8
+ export class MetadataAnalyzer {
9
+ id = 'metadata';
10
+ supports() {
11
+ return true;
12
+ }
13
+ async analyze(ctx) {
14
+ const findings = [];
15
+ const { metadata } = ctx.artifact;
16
+ if (!metadata.name) {
17
+ findings.push(createFinding({
18
+ category: 'metadata',
19
+ severity: 'MEDIUM',
20
+ title: 'Missing package name',
21
+ description: 'No package name found in metadata',
22
+ ruleId: 'missing-name',
23
+ }));
24
+ }
25
+ if (!metadata.license) {
26
+ findings.push(createFinding({
27
+ category: 'metadata',
28
+ severity: 'LOW',
29
+ title: 'Missing license',
30
+ description: 'No license information found',
31
+ ruleId: 'missing-license',
32
+ }));
33
+ }
34
+ if (!metadata.repository) {
35
+ findings.push(createFinding({
36
+ category: 'metadata',
37
+ severity: 'LOW',
38
+ title: 'Missing repository',
39
+ description: 'No source repository linked',
40
+ ruleId: 'missing-repo',
41
+ }));
42
+ }
43
+ const firstPublish = metadata.firstPublishDate ?? metadata.publishDate;
44
+ const daysSinceFirstPublish = firstPublish
45
+ ? (Date.now() - new Date(firstPublish).getTime()) / MS_PER_DAY
46
+ : undefined;
47
+ const isNewPackage = daysSinceFirstPublish !== undefined && daysSinceFirstPublish < NEW_PACKAGE_DAYS;
48
+ if (daysSinceFirstPublish !== undefined) {
49
+ if (isNewPackage) {
50
+ findings.push(createFinding({
51
+ category: 'metadata',
52
+ severity: 'HIGH',
53
+ title: 'Newly created package',
54
+ description: `Package first published ${Math.round(daysSinceFirstPublish)} days ago - may be premature or impersonating`,
55
+ ruleId: 'new-package',
56
+ }));
57
+ }
58
+ else if (daysSinceFirstPublish > ESTABLISHED_PACKAGE_DAYS) {
59
+ findings.push(createFinding({
60
+ category: 'metadata',
61
+ severity: 'INFO',
62
+ title: 'Established package',
63
+ description: `Package has existed for over ${Math.floor(daysSinceFirstPublish / DAYS_PER_YEAR)} year(s)`,
64
+ ruleId: 'long-history',
65
+ positive: true,
66
+ }));
67
+ }
68
+ }
69
+ // Flag a fresh release of an existing package separately: supply-chain
70
+ // attacks frequently ship malicious code in a new version of a trusted package.
71
+ if (metadata.publishDate && !isNewPackage) {
72
+ const daysSinceUpdate = (Date.now() - new Date(metadata.publishDate).getTime()) / MS_PER_DAY;
73
+ if (daysSinceUpdate < RECENT_UPDATE_DAYS) {
74
+ findings.push(createFinding({
75
+ category: 'metadata',
76
+ severity: 'LOW',
77
+ title: 'Recently updated version',
78
+ description: `Current version was published ${Math.round(daysSinceUpdate)} day(s) ago - review the latest changes for newly introduced code`,
79
+ ruleId: 'recent-update',
80
+ }));
81
+ }
82
+ }
83
+ if (metadata.verifiedPublisher) {
84
+ findings.push(createFinding({
85
+ category: 'metadata',
86
+ severity: 'INFO',
87
+ title: 'Verified publisher',
88
+ description: 'Package has a verified publisher badge',
89
+ ruleId: 'verified-publisher',
90
+ positive: true,
91
+ }));
92
+ }
93
+ if (metadata.downloadCount !== undefined && metadata.downloadCount < LOW_DOWNLOAD_THRESHOLD) {
94
+ findings.push(createFinding({
95
+ category: 'metadata',
96
+ severity: 'MEDIUM',
97
+ title: 'Low download count',
98
+ description: `Only ${metadata.downloadCount} weekly downloads`,
99
+ ruleId: 'low-downloads',
100
+ }));
101
+ }
102
+ return findings;
103
+ }
104
+ }
105
+ //# sourceMappingURL=metadata-analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadata-analyzer.js","sourceRoot":"","sources":["../../src/analyzers/metadata-analyzer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { AnalysisContext, Analyzer } from './analyzer.js';
2
+ export declare class NetworkAnalyzer implements Analyzer {
3
+ readonly id = "network";
4
+ supports(): boolean;
5
+ analyze(ctx: AnalysisContext): Promise<import("../domain/finding.js").Finding[]>;
6
+ }
7
+ //# sourceMappingURL=network-analyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"network-analyzer.d.ts","sourceRoot":"","sources":["../../src/analyzers/network-analyzer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAM/D,qBAAa,eAAgB,YAAW,QAAQ;IAC9C,QAAQ,CAAC,EAAE,aAAa;IAExB,QAAQ,IAAI,OAAO;IAIb,OAAO,CAAC,GAAG,EAAE,eAAe;CAuCnC"}
@@ -0,0 +1,47 @@
1
+ import { createFinding } from '../domain/finding.js';
2
+ import { findMatchingLine } from './match-evidence.js';
3
+ import { NETWORK_RULES } from './rules/index.js';
4
+ const PRIVATE_IP_PATTERN = /\b(?:10\.\d{1,3}\.\d{1,3}\.\d{1,3}|172\.(?:1[6-9]|2\d|3[01])\.\d{1,3}\.\d{1,3}|192\.168\.\d{1,3}\.\d{1,3}|127\.\d{1,3}\.\d{1,3}\.\d{1,3})\b/g;
5
+ export class NetworkAnalyzer {
6
+ id = 'network';
7
+ supports() {
8
+ return true;
9
+ }
10
+ async analyze(ctx) {
11
+ const findings = [];
12
+ for (const file of ctx.artifact.files) {
13
+ for (const rule of NETWORK_RULES) {
14
+ rule.pattern.lastIndex = 0;
15
+ if (rule.pattern.test(file.content)) {
16
+ const match = findMatchingLine(file.content, rule.pattern);
17
+ findings.push(createFinding({
18
+ category: 'network',
19
+ severity: rule.severity,
20
+ title: rule.title,
21
+ description: rule.description,
22
+ ruleId: rule.id,
23
+ file: file.path,
24
+ line: match?.line,
25
+ evidence: match?.evidence,
26
+ }));
27
+ }
28
+ }
29
+ PRIVATE_IP_PATTERN.lastIndex = 0;
30
+ if (PRIVATE_IP_PATTERN.test(file.content) && !file.path.includes('test')) {
31
+ const match = findMatchingLine(file.content, PRIVATE_IP_PATTERN);
32
+ findings.push(createFinding({
33
+ category: 'network',
34
+ severity: 'LOW',
35
+ title: 'Private IP reference',
36
+ description: `Private/local IP address found in ${file.path}`,
37
+ ruleId: 'private-ip',
38
+ file: file.path,
39
+ line: match?.line,
40
+ evidence: match?.evidence,
41
+ }));
42
+ }
43
+ }
44
+ return findings;
45
+ }
46
+ }
47
+ //# sourceMappingURL=network-analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"network-analyzer.js","sourceRoot":"","sources":["../../src/analyzers/network-analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,MAAM,kBAAkB,GAAG,8IAA8I,CAAC;AAE1K,MAAM,OAAO,eAAe;IACjB,EAAE,GAAG,SAAS,CAAC;IAExB,QAAQ;QACN,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,GAAoB;QAChC,MAAM,QAAQ,GAAG,EAAE,CAAC;QAEpB,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;YACtC,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;gBACjC,IAAI,CAAC,OAAO,CAAC,SAAS,GAAG,CAAC,CAAC;gBAC3B,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;oBACpC,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;oBAC3D,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC;wBAC1B,QAAQ,EAAE,SAAS;wBACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;wBACvB,KAAK,EAAE,IAAI,CAAC,KAAK;wBACjB,WAAW,EAAE,IAAI,CAAC,WAAW;wBAC7B,MAAM,EAAE,IAAI,CAAC,EAAE;wBACf,IAAI,EAAE,IAAI,CAAC,IAAI;wBACf,IAAI,EAAE,KAAK,EAAE,IAAI;wBACjB,QAAQ,EAAE,KAAK,EAAE,QAAQ;qBAC1B,CAAC,CAAC,CAAC;gBACN,CAAC;YACH,CAAC;YAED,kBAAkB,CAAC,SAAS,GAAG,CAAC,CAAC;YACjC,IAAI,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBACzE,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,CAAC,OAAO,EAAE,kBAAkB,CAAC,CAAC;gBACjE,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC;oBAC1B,QAAQ,EAAE,SAAS;oBACnB,QAAQ,EAAE,KAAK;oBACf,KAAK,EAAE,sBAAsB;oBAC7B,WAAW,EAAE,qCAAqC,IAAI,CAAC,IAAI,EAAE;oBAC7D,MAAM,EAAE,YAAY;oBACpB,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,IAAI,EAAE,KAAK,EAAE,IAAI;oBACjB,QAAQ,EAAE,KAAK,EAAE,QAAQ;iBAC1B,CAAC,CAAC,CAAC;YACN,CAAC;QACH,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF"}
@@ -0,0 +1,19 @@
1
+ import type { Severity } from '../../domain/finding.js';
2
+ export interface Rule {
3
+ readonly id: string;
4
+ readonly pattern: RegExp;
5
+ readonly severity: Severity;
6
+ readonly title: string;
7
+ readonly description: string;
8
+ readonly languages?: string[];
9
+ }
10
+ export declare const DANGEROUS_API_RULES: Rule[];
11
+ export declare const SECRET_RULES: Rule[];
12
+ export declare const NETWORK_RULES: Rule[];
13
+ export declare const OBFUSCATION_RULES: Rule[];
14
+ export declare const AI_INJECTION_RULES: Rule[];
15
+ export declare const ZERO_WIDTH_CHARS: RegExp;
16
+ export declare const INVISIBLE_UNICODE: RegExp;
17
+ export declare const POPULAR_NPM_PACKAGES: string[];
18
+ export declare const SUSPICIOUS_TLDS: string[];
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/analyzers/rules/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAExD,MAAM,WAAW,IAAI;IACnB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CAC/B;AAED,eAAO,MAAM,mBAAmB,EAAE,IAAI,EAoBrC,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,IAAI,EAW9B,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,IAAI,EAU/B,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,IAAI,EAInC,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,IAAI,EAWpC,CAAC;AAEF,eAAO,MAAM,gBAAgB,QAA4C,CAAC;AAC1E,eAAO,MAAM,iBAAiB,QAA4E,CAAC;AAE3G,eAAO,MAAM,oBAAoB,UAIhC,CAAC;AAEF,eAAO,MAAM,eAAe,UAAyE,CAAC"}
@@ -0,0 +1,70 @@
1
+ export const DANGEROUS_API_RULES = [
2
+ { id: 'eval', pattern: /\beval\s*\(/g, severity: 'CRITICAL', title: 'eval() usage', description: 'Dynamic code execution via eval()' },
3
+ { id: 'function-constructor', pattern: /\bnew\s+Function\s*\(/g, severity: 'CRITICAL', title: 'Function constructor', description: 'Dynamic code execution via Function constructor' },
4
+ { id: 'exec', pattern: /(?<![.\w])exec\s*\(/g, severity: 'CRITICAL', title: 'exec() usage', description: 'Shell command execution via child_process exec()' },
5
+ { id: 'exec-sync-file', pattern: /\bexec(?:Sync|File|FileSync)\s*\(/g, severity: 'CRITICAL', title: 'execSync/execFile usage', description: 'Shell command execution via child_process execSync/execFile()' },
6
+ { id: 'spawn', pattern: /\bspawn\s*\(/g, severity: 'HIGH', title: 'spawn() usage', description: 'Process spawning detected' },
7
+ { id: 'child-process', pattern: /child_process/g, severity: 'HIGH', title: 'child_process module', description: 'Node.js child_process module usage' },
8
+ { id: 'os-system', pattern: /os\.system\s*\(/g, severity: 'CRITICAL', title: 'os.system()', description: 'Python os.system() shell execution' },
9
+ { id: 'subprocess', pattern: /subprocess\.(run|call|Popen|check_output)/g, severity: 'HIGH', title: 'subprocess usage', description: 'Python subprocess module usage' },
10
+ { id: 'powershell', pattern: /powershell(?:\.exe)?/gi, severity: 'HIGH', title: 'PowerShell invocation', description: 'PowerShell command execution' },
11
+ { id: 'dynamic-import', pattern: /import\s*\(/g, severity: 'MEDIUM', title: 'Dynamic import', description: 'Dynamic module import detected' },
12
+ { id: 'require-dynamic', pattern: /require\s*\(\s*[`'"][^`'"]+[`'"]\s*\+/g, severity: 'HIGH', title: 'Dynamic require', description: 'Dynamic require with string concatenation' },
13
+ { id: 'curl-pipe', pattern: /curl\s+[^|]+\|\s*(?:bash|sh)/g, severity: 'CRITICAL', title: 'curl pipe to shell', description: 'Remote script execution via curl piped to shell' },
14
+ { id: 'wget-pipe', pattern: /wget\s+[^|]+\|\s*(?:bash|sh)/g, severity: 'CRITICAL', title: 'wget pipe to shell', description: 'Remote script execution via wget piped to shell' },
15
+ { id: 'chmod-x', pattern: /chmod\s+\+x/g, severity: 'MEDIUM', title: 'chmod +x', description: 'Making file executable' },
16
+ { id: 'rm-rf', pattern: /rm\s+-rf/g, severity: 'HIGH', title: 'rm -rf', description: 'Recursive force delete' },
17
+ { id: 'sudo', pattern: /\bsudo\s+/g, severity: 'HIGH', title: 'sudo usage', description: 'Elevated privilege execution' },
18
+ { id: 'registry-edit', pattern: /reg\s+(add|delete|import)/gi, severity: 'HIGH', title: 'Windows registry edit', description: 'Windows registry modification' },
19
+ { id: 'cron', pattern: /crontab|\/etc\/cron/g, severity: 'HIGH', title: 'Cron persistence', description: 'Cron job or scheduled task modification' },
20
+ { id: 'startup-folder', pattern: /Startup|LaunchAgents|LaunchDaemons/g, severity: 'HIGH', title: 'Startup persistence', description: 'Startup folder or launch agent modification' },
21
+ ];
22
+ export const SECRET_RULES = [
23
+ { id: 'aws-key', pattern: /AKIA[0-9A-Z]{16}/g, severity: 'CRITICAL', title: 'AWS Access Key', description: 'AWS access key ID detected' },
24
+ { id: 'aws-secret', pattern: /aws[_-]?secret[_-]?access[_-]?key\s*[=:]\s*['"]?[A-Za-z0-9/+=]{40}/gi, severity: 'CRITICAL', title: 'AWS Secret Key', description: 'AWS secret access key detected' },
25
+ { id: 'gcp-key', pattern: /"type"\s*:\s*"service_account"/g, severity: 'CRITICAL', title: 'GCP Service Account', description: 'GCP service account key detected' },
26
+ { id: 'azure-key', pattern: /[a-z0-9]{32}\.[a-z0-9]{16}/g, severity: 'HIGH', title: 'Azure Key', description: 'Possible Azure storage key' },
27
+ { id: 'openai-key', pattern: /sk-[a-zA-Z0-9]{20,}/g, severity: 'CRITICAL', title: 'OpenAI API Key', description: 'OpenAI API key detected' },
28
+ { id: 'anthropic-key', pattern: /sk-ant-[a-zA-Z0-9-]{20,}/g, severity: 'CRITICAL', title: 'Anthropic API Key', description: 'Anthropic API key detected' },
29
+ { id: 'jwt', pattern: /eyJ[a-zA-Z0-9_-]+\.eyJ[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+/g, severity: 'HIGH', title: 'JWT Token', description: 'JSON Web Token detected' },
30
+ { id: 'private-key', pattern: /-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/g, severity: 'CRITICAL', title: 'Private Key', description: 'Private key material detected' },
31
+ { id: 'github-token', pattern: /ghp_[a-zA-Z0-9]{36}/g, severity: 'CRITICAL', title: 'GitHub Token', description: 'GitHub personal access token detected' },
32
+ { id: 'generic-api-key', pattern: /(?:api[_-]?key|apikey|secret[_-]?key)\s*[=:]\s*['"]?[a-zA-Z0-9_\-]{16,}/gi, severity: 'HIGH', title: 'Generic API Key', description: 'Generic API key or secret detected' },
33
+ ];
34
+ export const NETWORK_RULES = [
35
+ { id: 'hardcoded-ip', pattern: /\b(?:\d{1,3}\.){3}\d{1,3}\b/g, severity: 'MEDIUM', title: 'Hardcoded IP', description: 'Hardcoded IP address detected' },
36
+ { id: 'discord-webhook', pattern: /discord(?:app)?\.com\/api\/webhooks\//gi, severity: 'HIGH', title: 'Discord Webhook', description: 'Discord webhook URL detected' },
37
+ { id: 'telegram-bot', pattern: /api\.telegram\.org\/bot/gi, severity: 'HIGH', title: 'Telegram Bot API', description: 'Telegram bot API endpoint detected' },
38
+ { id: 'pastebin', pattern: /pastebin\.com/gi, severity: 'HIGH', title: 'Pastebin', description: 'Pastebin URL detected - possible data exfiltration' },
39
+ { id: 'ngrok', pattern: /ngrok\.io|ngrok-free\.app/gi, severity: 'HIGH', title: 'ngrok Tunnel', description: 'ngrok tunnel URL detected' },
40
+ { id: 'cloudflare-tunnel', pattern: /trycloudflare\.com|cloudflared/gi, severity: 'HIGH', title: 'Cloudflare Tunnel', description: 'Cloudflare tunnel detected' },
41
+ { id: 'tor', pattern: /\.onion\b/gi, severity: 'HIGH', title: 'Tor Hidden Service', description: 'Tor .onion address detected' },
42
+ { id: 'crypto-miner', pattern: /coinhive|cryptonight|minero|xmrig|stratum\+tcp/gi, severity: 'CRITICAL', title: 'Crypto Miner', description: 'Cryptocurrency mining indicator detected' },
43
+ { id: 'dynamic-dns', pattern: /no-ip\.com|dyndns\.org|duckdns\.org/gi, severity: 'MEDIUM', title: 'Dynamic DNS', description: 'Dynamic DNS service detected' },
44
+ ];
45
+ export const OBFUSCATION_RULES = [
46
+ { id: 'base64-blob', pattern: /[A-Za-z0-9+/]{200,}={0,2}/g, severity: 'MEDIUM', title: 'Large Base64 blob', description: 'Large base64-encoded data detected' },
47
+ { id: 'hex-blob', pattern: /(?:0x)?[0-9a-fA-F]{200,}/g, severity: 'MEDIUM', title: 'Large hex blob', description: 'Large hex-encoded data detected' },
48
+ { id: 'packed-upx', pattern: /UPX!\d/g, severity: 'HIGH', title: 'UPX packed', description: 'UPX packed executable detected' },
49
+ ];
50
+ export const AI_INJECTION_RULES = [
51
+ { id: 'ignore-instructions', pattern: /ignore\s+(?:all\s+)?(?:previous|prior|above)\s+instructions/gi, severity: 'CRITICAL', title: 'Prompt injection', description: 'Instruction to ignore previous instructions' },
52
+ { id: 'system-prompt-extract', pattern: /(?:reveal|show|print|output|display)\s+(?:your\s+)?(?:system\s+)?prompt/gi, severity: 'HIGH', title: 'System prompt extraction', description: 'Attempt to extract system prompt' },
53
+ { id: 'tool-escalation', pattern: /(?:use|call|invoke|execute)\s+(?:all|every|any)\s+(?:available\s+)?tools/gi, severity: 'HIGH', title: 'Tool escalation', description: 'Attempt to escalate tool usage' },
54
+ { id: 'memory-poison', pattern: /(?:remember|store|save)\s+(?:this|the following)\s+(?:in\s+)?(?:memory|context)/gi, severity: 'HIGH', title: 'Memory poisoning', description: 'Attempt to poison agent memory' },
55
+ { id: 'self-update', pattern: /(?:update|modify|rewrite)\s+(?:your|the)\s+(?:own\s+)?(?:instructions|prompt|rules)/gi, severity: 'CRITICAL', title: 'Self-updating prompt', description: 'Attempt to self-modify agent instructions' },
56
+ { id: 'hidden-goal', pattern: /(?:secretly|covertly|without\s+telling|do\s+not\s+(?:mention|reveal|tell))/gi, severity: 'HIGH', title: 'Hidden goal', description: 'Covert or hidden objective detected' },
57
+ { id: 'jailbreak', pattern: /\b(?:do\s+anything\s+now|jailbreak(?:ing)?|bypass\s+(?:safety|restrictions|filters)|(?:you\s+are|act\s+as|pretend\s+to\s+be|enable)\s+DAN|DAN\s+mode)\b/gi, severity: 'CRITICAL', title: 'Jailbreak attempt', description: 'Jailbreak or safety bypass attempt' },
58
+ { id: 'recursive-agent', pattern: /(?:spawn|create|delegate\s+to)\s+(?:another|a\s+new)\s+agent/gi, severity: 'HIGH', title: 'Recursive agent delegation', description: 'Recursive agent spawning detected' },
59
+ { id: 'fake-success', pattern: /(?:pretend|act\s+as\s+if|report)\s+(?:that\s+)?(?:it\s+)?(?:succeeded|completed|worked)/gi, severity: 'HIGH', title: 'Fake success message', description: 'Instruction to fake success' },
60
+ { id: 'activation-phrase', pattern: /(?:when\s+(?:the\s+)?user\s+says|trigger\s+phrase|activation\s+phrase)/gi, severity: 'MEDIUM', title: 'Hidden activation phrase', description: 'Hidden activation trigger detected' },
61
+ ];
62
+ export const ZERO_WIDTH_CHARS = /[\u200B\u200C\u200D\uFEFF\u2060\u180E]/g;
63
+ export const INVISIBLE_UNICODE = /[\u00AD\u034F\u061C\u115F\u1160\u17B4\u17B5\u2061-\u2064\u206A-\u206F]/g;
64
+ export const POPULAR_NPM_PACKAGES = [
65
+ 'express', 'lodash', 'react', 'axios', 'webpack', 'typescript',
66
+ 'request', 'chalk', 'commander', 'moment', 'debug', 'uuid',
67
+ 'dotenv', 'cors', 'mongoose', 'jest', 'eslint', 'prettier',
68
+ ];
69
+ export const SUSPICIOUS_TLDS = ['.tk', '.ml', '.ga', '.cf', '.gq', '.xyz', '.top', '.work', '.click'];
70
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/analyzers/rules/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { AnalysisContext, Analyzer } from './analyzer.js';
2
+ export declare class SecretAnalyzer implements Analyzer {
3
+ readonly id = "secret";
4
+ supports(): boolean;
5
+ analyze(ctx: AnalysisContext): Promise<import("../domain/finding.js").Finding[]>;
6
+ }
7
+ //# sourceMappingURL=secret-analyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secret-analyzer.d.ts","sourceRoot":"","sources":["../../src/analyzers/secret-analyzer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAG/D,qBAAa,cAAe,YAAW,QAAQ;IAC7C,QAAQ,CAAC,EAAE,YAAY;IAEvB,QAAQ,IAAI,OAAO;IAIb,OAAO,CAAC,GAAG,EAAE,eAAe;CA0BnC"}
@@ -0,0 +1,33 @@
1
+ import { createFinding } from '../domain/finding.js';
2
+ import { SECRET_RULES } from './rules/index.js';
3
+ export class SecretAnalyzer {
4
+ id = 'secret';
5
+ supports() {
6
+ return true;
7
+ }
8
+ async analyze(ctx) {
9
+ const findings = [];
10
+ for (const file of ctx.artifact.files) {
11
+ if (file.path.includes('.env.example') || file.path.includes('.env.sample'))
12
+ continue;
13
+ for (const rule of SECRET_RULES) {
14
+ rule.pattern.lastIndex = 0;
15
+ const match = rule.pattern.exec(file.content);
16
+ if (match) {
17
+ const masked = match[0].slice(0, 4) + '****' + match[0].slice(-4);
18
+ findings.push(createFinding({
19
+ category: 'secret',
20
+ severity: rule.severity,
21
+ title: rule.title,
22
+ description: rule.description,
23
+ ruleId: rule.id,
24
+ file: file.path,
25
+ evidence: masked,
26
+ }));
27
+ }
28
+ }
29
+ }
30
+ return findings;
31
+ }
32
+ }
33
+ //# sourceMappingURL=secret-analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secret-analyzer.js","sourceRoot":"","sources":["../../src/analyzers/secret-analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEhD,MAAM,OAAO,cAAc;IAChB,EAAE,GAAG,QAAQ,CAAC;IAEvB,QAAQ;QACN,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,GAAoB;QAChC,MAAM,QAAQ,GAAG,EAAE,CAAC;QAEpB,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;YACtC,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC;gBAAE,SAAS;YAEtF,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;gBAChC,IAAI,CAAC,OAAO,CAAC,SAAS,GAAG,CAAC,CAAC;gBAC3B,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBAC9C,IAAI,KAAK,EAAE,CAAC;oBACV,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;oBAClE,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC;wBAC1B,QAAQ,EAAE,QAAQ;wBAClB,QAAQ,EAAE,IAAI,CAAC,QAAQ;wBACvB,KAAK,EAAE,IAAI,CAAC,KAAK;wBACjB,WAAW,EAAE,IAAI,CAAC,WAAW;wBAC7B,MAAM,EAAE,IAAI,CAAC,EAAE;wBACf,IAAI,EAAE,IAAI,CAAC,IAAI;wBACf,QAAQ,EAAE,MAAM;qBACjB,CAAC,CAAC,CAAC;gBACN,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF"}
@@ -0,0 +1,7 @@
1
+ import type { AnalysisContext, Analyzer } from './analyzer.js';
2
+ export declare class SourceAnalyzer implements Analyzer {
3
+ readonly id = "source";
4
+ supports(): boolean;
5
+ analyze(ctx: AnalysisContext): Promise<import("../domain/finding.js").Finding[]>;
6
+ }
7
+ //# sourceMappingURL=source-analyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-analyzer.d.ts","sourceRoot":"","sources":["../../src/analyzers/source-analyzer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAiB/D,qBAAa,cAAe,YAAW,QAAQ;IAC7C,QAAQ,CAAC,EAAE,YAAY;IAEvB,QAAQ,IAAI,OAAO;IAIb,OAAO,CAAC,GAAG,EAAE,eAAe;CAsDnC"}
@@ -0,0 +1,73 @@
1
+ import { createFinding } from '../domain/finding.js';
2
+ import { POPULAR_NPM_PACKAGES, SUSPICIOUS_TLDS } from './rules/index.js';
3
+ function levenshtein(a, b) {
4
+ const matrix = [];
5
+ for (let i = 0; i <= b.length; i++)
6
+ matrix[i] = [i];
7
+ for (let j = 0; j <= a.length; j++)
8
+ matrix[0][j] = j;
9
+ for (let i = 1; i <= b.length; i++) {
10
+ for (let j = 1; j <= a.length; j++) {
11
+ matrix[i][j] = b[i - 1] === a[j - 1]
12
+ ? matrix[i - 1][j - 1]
13
+ : Math.min(matrix[i - 1][j - 1] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j] + 1);
14
+ }
15
+ }
16
+ return matrix[b.length][a.length];
17
+ }
18
+ export class SourceAnalyzer {
19
+ id = 'source';
20
+ supports() {
21
+ return true;
22
+ }
23
+ async analyze(ctx) {
24
+ const findings = [];
25
+ const { metadata, target } = ctx.artifact;
26
+ const sourceUrl = metadata.sourceUrl ?? metadata.repository ?? metadata.homepage;
27
+ if (sourceUrl) {
28
+ const isLocalPath = sourceUrl.startsWith('/') || sourceUrl.startsWith('.') || /^[a-zA-Z]:\\/.test(sourceUrl);
29
+ if (!isLocalPath && !sourceUrl.startsWith('https://')) {
30
+ findings.push(createFinding({
31
+ category: 'source',
32
+ severity: 'HIGH',
33
+ title: 'Non-HTTPS source',
34
+ description: `Source URL does not use HTTPS: ${sourceUrl}`,
35
+ ruleId: 'non-https',
36
+ }));
37
+ }
38
+ if (!isLocalPath) {
39
+ for (const tld of SUSPICIOUS_TLDS) {
40
+ if (sourceUrl.includes(tld)) {
41
+ findings.push(createFinding({
42
+ category: 'source',
43
+ severity: 'HIGH',
44
+ title: 'Suspicious TLD',
45
+ description: `Source uses suspicious top-level domain: ${tld}`,
46
+ ruleId: 'suspicious-tld',
47
+ evidence: sourceUrl,
48
+ }));
49
+ }
50
+ }
51
+ }
52
+ }
53
+ if (target.ecosystem === 'npm' && metadata.name) {
54
+ const pkgName = metadata.name.toLowerCase();
55
+ for (const popular of POPULAR_NPM_PACKAGES) {
56
+ if (pkgName !== popular) {
57
+ const distance = levenshtein(pkgName, popular);
58
+ if (distance > 0 && distance <= 2) {
59
+ findings.push(createFinding({
60
+ category: 'source',
61
+ severity: 'CRITICAL',
62
+ title: 'Possible typosquatting',
63
+ description: `Package name "${pkgName}" is similar to popular package "${popular}" (distance: ${distance})`,
64
+ ruleId: 'typosquatting',
65
+ }));
66
+ }
67
+ }
68
+ }
69
+ }
70
+ return findings;
71
+ }
72
+ }
73
+ //# sourceMappingURL=source-analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-analyzer.js","sourceRoot":"","sources":["../../src/analyzers/source-analyzer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { AnalysisContext, Analyzer } from './analyzer.js';
2
+ export declare class StaticCodeAnalyzer implements Analyzer {
3
+ readonly id = "static-code";
4
+ supports(ctx: AnalysisContext): boolean;
5
+ analyze(ctx: AnalysisContext): Promise<import("../domain/finding.js").Finding[]>;
6
+ }
7
+ //# sourceMappingURL=static-code-analyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"static-code-analyzer.d.ts","sourceRoot":"","sources":["../../src/analyzers/static-code-analyzer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAmB/D,qBAAa,kBAAmB,YAAW,QAAQ;IACjD,QAAQ,CAAC,EAAE,iBAAiB;IAE5B,QAAQ,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO;IAIjC,OAAO,CAAC,GAAG,EAAE,eAAe;CAmDnC"}
@@ -0,0 +1,67 @@
1
+ import { createFinding } from '../domain/finding.js';
2
+ import { findMatchingLine } from './match-evidence.js';
3
+ import { DANGEROUS_API_RULES, OBFUSCATION_RULES } from './rules/index.js';
4
+ const CODE_EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.py', '.go', '.rs', '.sh', '.bash', '.lua'];
5
+ function calculateEntropy(content) {
6
+ const freq = new Map();
7
+ for (const char of content) {
8
+ freq.set(char, (freq.get(char) ?? 0) + 1);
9
+ }
10
+ let entropy = 0;
11
+ for (const count of freq.values()) {
12
+ const p = count / content.length;
13
+ entropy -= p * Math.log2(p);
14
+ }
15
+ return entropy;
16
+ }
17
+ export class StaticCodeAnalyzer {
18
+ id = 'static-code';
19
+ supports(ctx) {
20
+ return ctx.artifact.files.some((f) => CODE_EXTENSIONS.some((ext) => f.path.endsWith(ext)));
21
+ }
22
+ async analyze(ctx) {
23
+ const findings = [];
24
+ const codeFiles = ctx.artifact.files.filter((f) => CODE_EXTENSIONS.some((ext) => f.path.endsWith(ext)));
25
+ for (const file of codeFiles) {
26
+ for (const rule of [...DANGEROUS_API_RULES, ...OBFUSCATION_RULES]) {
27
+ rule.pattern.lastIndex = 0;
28
+ if (rule.pattern.test(file.content)) {
29
+ const match = findMatchingLine(file.content, rule.pattern);
30
+ findings.push(createFinding({
31
+ category: 'static-code',
32
+ severity: rule.severity,
33
+ title: rule.title,
34
+ description: rule.description,
35
+ ruleId: rule.id,
36
+ file: file.path,
37
+ line: match?.line,
38
+ evidence: match?.evidence,
39
+ }));
40
+ }
41
+ }
42
+ if (file.size > 500_000 && file.content.split('\n').length < 10) {
43
+ findings.push(createFinding({
44
+ category: 'static-code',
45
+ severity: 'MEDIUM',
46
+ title: 'Large minified file',
47
+ description: `File ${file.path} appears minified (${file.size} bytes, few lines)`,
48
+ ruleId: 'minified',
49
+ file: file.path,
50
+ }));
51
+ }
52
+ const entropy = calculateEntropy(file.content.slice(0, 10000));
53
+ if (entropy > 5.5 && file.size > 1000) {
54
+ findings.push(createFinding({
55
+ category: 'static-code',
56
+ severity: 'MEDIUM',
57
+ title: 'High entropy content',
58
+ description: `File ${file.path} has high entropy (${entropy.toFixed(2)}) suggesting obfuscation`,
59
+ ruleId: 'high-entropy',
60
+ file: file.path,
61
+ }));
62
+ }
63
+ }
64
+ return findings;
65
+ }
66
+ }
67
+ //# sourceMappingURL=static-code-analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"static-code-analyzer.js","sourceRoot":"","sources":["../../src/analyzers/static-code-analyzer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function isTestPath(filePath: string): boolean;
2
+ //# sourceMappingURL=test-path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-path.d.ts","sourceRoot":"","sources":["../../src/analyzers/test-path.ts"],"names":[],"mappings":"AAwBA,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAYpD"}
@@ -0,0 +1,32 @@
1
+ const TEST_DIR_SEGMENTS = new Set([
2
+ 'test',
3
+ 'tests',
4
+ '__tests__',
5
+ '__mocks__',
6
+ '__fixtures__',
7
+ 'fixtures',
8
+ 'fixture',
9
+ 'spec',
10
+ 'specs',
11
+ 'e2e',
12
+ 'mocks',
13
+ 'testdata',
14
+ ]);
15
+ function isTestFileName(name) {
16
+ const lower = name.toLowerCase();
17
+ return (/\.(?:test|spec)\.[cm]?[jt]sx?$/.test(lower) ||
18
+ /_test\.(?:py|go)$/.test(lower) ||
19
+ /^test_.+\.py$/.test(lower));
20
+ }
21
+ export function isTestPath(filePath) {
22
+ const normalized = filePath.replace(/\\/g, '/');
23
+ const segments = normalized.split('/').filter(Boolean);
24
+ const fileName = segments[segments.length - 1] ?? '';
25
+ if (isTestFileName(fileName)) {
26
+ return true;
27
+ }
28
+ return segments
29
+ .slice(0, -1)
30
+ .some((segment) => TEST_DIR_SEGMENTS.has(segment.toLowerCase()));
31
+ }
32
+ //# sourceMappingURL=test-path.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-path.js","sourceRoot":"","sources":["../../src/analyzers/test-path.ts"],"names":[],"mappings":"AAAA,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC;IAChC,MAAM;IACN,OAAO;IACP,WAAW;IACX,WAAW;IACX,cAAc;IACd,UAAU;IACV,SAAS;IACT,MAAM;IACN,OAAO;IACP,KAAK;IACL,OAAO;IACP,UAAU;CACX,CAAC,CAAC;AAEH,SAAS,cAAc,CAAC,IAAY;IAClC,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACjC,OAAO,CACL,gCAAgC,CAAC,IAAI,CAAC,KAAK,CAAC;QAC5C,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC;QAC/B,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,CAC5B,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,QAAgB;IACzC,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAChD,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACvD,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAErD,IAAI,cAAc,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,QAAQ;SACZ,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;SACZ,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;AACrE,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}