toolip 1.0.7 → 2.0.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 (174) hide show
  1. package/README.md +189 -448
  2. package/dist/src/analyzers/ast/ast-security-analyzer.d.ts +6 -0
  3. package/dist/src/analyzers/ast/ast-security-analyzer.js +64 -0
  4. package/dist/src/analyzers/ast/ast-security-analyzer.js.map +1 -0
  5. package/dist/src/analyzers/ast/rules.d.ts +48 -0
  6. package/dist/src/analyzers/ast/rules.js +39 -0
  7. package/dist/src/analyzers/ast/rules.js.map +1 -0
  8. package/dist/src/analyzers/ast/source-analysis.d.ts +2 -0
  9. package/dist/src/analyzers/ast/source-analysis.js +225 -0
  10. package/dist/src/analyzers/ast/source-analysis.js.map +1 -0
  11. package/dist/src/analyzers/dependency-confusion/analyzer.d.ts +9 -0
  12. package/dist/src/analyzers/dependency-confusion/analyzer.js +98 -0
  13. package/dist/src/analyzers/dependency-confusion/analyzer.js.map +1 -0
  14. package/dist/src/analyzers/docker/analyzer.d.ts +6 -0
  15. package/dist/src/analyzers/docker/analyzer.js +103 -0
  16. package/dist/src/analyzers/docker/analyzer.js.map +1 -0
  17. package/dist/src/analyzers/git-history/analyzer.d.ts +8 -0
  18. package/dist/src/analyzers/git-history/analyzer.js +202 -0
  19. package/dist/src/analyzers/git-history/analyzer.js.map +1 -0
  20. package/dist/src/analyzers/git-history/secret-patterns.d.ts +7 -0
  21. package/dist/src/analyzers/git-history/secret-patterns.js +33 -0
  22. package/dist/src/analyzers/git-history/secret-patterns.js.map +1 -0
  23. package/dist/src/analyzers/install-scripts/install-script-analyzer.d.ts +6 -0
  24. package/dist/src/analyzers/install-scripts/install-script-analyzer.js +135 -0
  25. package/dist/src/analyzers/install-scripts/install-script-analyzer.js.map +1 -0
  26. package/dist/src/analyzers/reachability/import-graph.d.ts +9 -0
  27. package/dist/src/analyzers/reachability/import-graph.js +110 -0
  28. package/dist/src/analyzers/reachability/import-graph.js.map +1 -0
  29. package/dist/src/analyzers/reachability/reachability-analyzer.d.ts +16 -0
  30. package/dist/src/analyzers/reachability/reachability-analyzer.js +95 -0
  31. package/dist/src/analyzers/reachability/reachability-analyzer.js.map +1 -0
  32. package/dist/src/analyzers/vulnerability/osv-analyzer.d.ts +9 -0
  33. package/dist/src/analyzers/vulnerability/osv-analyzer.js +94 -0
  34. package/dist/src/analyzers/vulnerability/osv-analyzer.js.map +1 -0
  35. package/dist/src/analyzers/vulnerability/severity.d.ts +3 -0
  36. package/dist/src/analyzers/vulnerability/severity.js +13 -0
  37. package/dist/src/analyzers/vulnerability/severity.js.map +1 -0
  38. package/dist/src/application/analyzer-runner.d.ts +12 -0
  39. package/dist/src/application/analyzer-runner.js +45 -0
  40. package/dist/src/application/analyzer-runner.js.map +1 -0
  41. package/dist/src/commands/announce.d.ts +2 -0
  42. package/dist/src/commands/announce.js +27 -0
  43. package/dist/src/commands/announce.js.map +1 -0
  44. package/dist/src/commands/ast-scan.d.ts +2 -0
  45. package/dist/src/commands/ast-scan.js +86 -0
  46. package/dist/src/commands/ast-scan.js.map +1 -0
  47. package/dist/src/commands/audit-repo.d.ts +2 -0
  48. package/dist/src/commands/audit-repo.js +20 -0
  49. package/dist/src/commands/audit-repo.js.map +1 -0
  50. package/dist/src/commands/config.d.ts +2 -0
  51. package/dist/src/commands/config.js +69 -0
  52. package/dist/src/commands/config.js.map +1 -0
  53. package/dist/src/commands/dependency-confusion.d.ts +2 -0
  54. package/dist/src/commands/dependency-confusion.js +37 -0
  55. package/dist/src/commands/dependency-confusion.js.map +1 -0
  56. package/dist/src/commands/diff.d.ts +2 -0
  57. package/dist/src/commands/diff.js +24 -0
  58. package/dist/src/commands/diff.js.map +1 -0
  59. package/dist/src/commands/docker-scan.d.ts +2 -0
  60. package/dist/src/commands/docker-scan.js +34 -0
  61. package/dist/src/commands/docker-scan.js.map +1 -0
  62. package/dist/src/commands/git-history.d.ts +2 -0
  63. package/dist/src/commands/git-history.js +40 -0
  64. package/dist/src/commands/git-history.js.map +1 -0
  65. package/dist/src/commands/history.d.ts +2 -0
  66. package/dist/src/commands/history.js +69 -0
  67. package/dist/src/commands/history.js.map +1 -0
  68. package/dist/src/commands/install-scripts.d.ts +2 -0
  69. package/dist/src/commands/install-scripts.js +52 -0
  70. package/dist/src/commands/install-scripts.js.map +1 -0
  71. package/dist/src/commands/mcp.d.ts +2 -0
  72. package/dist/src/commands/mcp.js +10 -0
  73. package/dist/src/commands/mcp.js.map +1 -0
  74. package/dist/src/commands/monorepo.d.ts +2 -0
  75. package/dist/src/commands/monorepo.js +21 -0
  76. package/dist/src/commands/monorepo.js.map +1 -0
  77. package/dist/src/commands/package-health.d.ts +2 -0
  78. package/dist/src/commands/package-health.js +50 -0
  79. package/dist/src/commands/package-health.js.map +1 -0
  80. package/dist/src/commands/publish.d.ts +2 -0
  81. package/dist/src/commands/publish.js +25 -0
  82. package/dist/src/commands/publish.js.map +1 -0
  83. package/dist/src/commands/reachability.d.ts +2 -0
  84. package/dist/src/commands/reachability.js +47 -0
  85. package/dist/src/commands/reachability.js.map +1 -0
  86. package/dist/src/commands/sbom.d.ts +2 -0
  87. package/dist/src/commands/sbom.js +33 -0
  88. package/dist/src/commands/sbom.js.map +1 -0
  89. package/dist/src/commands/upgrade-pr.d.ts +2 -0
  90. package/dist/src/commands/upgrade-pr.js +15 -0
  91. package/dist/src/commands/upgrade-pr.js.map +1 -0
  92. package/dist/src/commands/vulnerabilities.d.ts +2 -0
  93. package/dist/src/commands/vulnerabilities.js +42 -0
  94. package/dist/src/commands/vulnerabilities.js.map +1 -0
  95. package/dist/src/commands/watch.d.ts +2 -0
  96. package/dist/src/commands/watch.js +34 -0
  97. package/dist/src/commands/watch.js.map +1 -0
  98. package/dist/src/contracts/analyzer.d.ts +23 -0
  99. package/dist/src/contracts/analyzer.js +2 -0
  100. package/dist/src/contracts/analyzer.js.map +1 -0
  101. package/dist/src/contracts/finding.d.ts +35 -0
  102. package/dist/src/contracts/finding.js +13 -0
  103. package/dist/src/contracts/finding.js.map +1 -0
  104. package/dist/src/contracts/report.d.ts +30 -0
  105. package/dist/src/contracts/report.js +2 -0
  106. package/dist/src/contracts/report.js.map +1 -0
  107. package/dist/src/contracts/rule.d.ts +12 -0
  108. package/dist/src/contracts/rule.js +7 -0
  109. package/dist/src/contracts/rule.js.map +1 -0
  110. package/dist/src/core/announce/generate.d.ts +9 -0
  111. package/dist/src/core/announce/generate.js +19 -0
  112. package/dist/src/core/announce/generate.js.map +1 -0
  113. package/dist/src/core/config/load.d.ts +3 -0
  114. package/dist/src/core/config/load.js +21 -0
  115. package/dist/src/core/config/load.js.map +1 -0
  116. package/dist/src/core/config/policy.d.ts +3 -0
  117. package/dist/src/core/config/policy.js +48 -0
  118. package/dist/src/core/config/policy.js.map +1 -0
  119. package/dist/src/core/config/schema.d.ts +172 -0
  120. package/dist/src/core/config/schema.js +84 -0
  121. package/dist/src/core/config/schema.js.map +1 -0
  122. package/dist/src/core/dependencies/inventory.d.ts +9 -0
  123. package/dist/src/core/dependencies/inventory.js +43 -0
  124. package/dist/src/core/dependencies/inventory.js.map +1 -0
  125. package/dist/src/core/diff/security-diff.d.ts +10 -0
  126. package/dist/src/core/diff/security-diff.js +20 -0
  127. package/dist/src/core/diff/security-diff.js.map +1 -0
  128. package/dist/src/core/github/remote-audit.d.ts +5 -0
  129. package/dist/src/core/github/remote-audit.js +28 -0
  130. package/dist/src/core/github/remote-audit.js.map +1 -0
  131. package/dist/src/core/github/upgrade-pr.d.ts +4 -0
  132. package/dist/src/core/github/upgrade-pr.js +41 -0
  133. package/dist/src/core/github/upgrade-pr.js.map +1 -0
  134. package/dist/src/core/history/git-metadata.d.ts +5 -0
  135. package/dist/src/core/history/git-metadata.js +37 -0
  136. package/dist/src/core/history/git-metadata.js.map +1 -0
  137. package/dist/src/core/history/store.d.ts +5 -0
  138. package/dist/src/core/history/store.js +65 -0
  139. package/dist/src/core/history/store.js.map +1 -0
  140. package/dist/src/core/history/types.d.ts +27 -0
  141. package/dist/src/core/history/types.js +2 -0
  142. package/dist/src/core/history/types.js.map +1 -0
  143. package/dist/src/core/monorepo/discover.d.ts +7 -0
  144. package/dist/src/core/monorepo/discover.js +49 -0
  145. package/dist/src/core/monorepo/discover.js.map +1 -0
  146. package/dist/src/core/publish/html.d.ts +6 -0
  147. package/dist/src/core/publish/html.js +44 -0
  148. package/dist/src/core/publish/html.js.map +1 -0
  149. package/dist/src/core/sbom/generate.d.ts +2 -0
  150. package/dist/src/core/sbom/generate.js +120 -0
  151. package/dist/src/core/sbom/generate.js.map +1 -0
  152. package/dist/src/core/security-doctor.js +19 -5
  153. package/dist/src/core/security-doctor.js.map +1 -1
  154. package/dist/src/core/watch/watch.d.ts +5 -0
  155. package/dist/src/core/watch/watch.js +49 -0
  156. package/dist/src/core/watch/watch.js.map +1 -0
  157. package/dist/src/index.js +38 -0
  158. package/dist/src/index.js.map +1 -1
  159. package/dist/src/mcp/server.d.ts +1 -0
  160. package/dist/src/mcp/server.js +64 -0
  161. package/dist/src/mcp/server.js.map +1 -0
  162. package/dist/src/providers/depsdev/client.d.ts +71 -0
  163. package/dist/src/providers/depsdev/client.js +44 -0
  164. package/dist/src/providers/depsdev/client.js.map +1 -0
  165. package/dist/src/providers/osv/client.d.ts +15 -0
  166. package/dist/src/providers/osv/client.js +51 -0
  167. package/dist/src/providers/osv/client.js.map +1 -0
  168. package/dist/src/providers/osv/types.d.ts +38 -0
  169. package/dist/src/providers/osv/types.js +2 -0
  170. package/dist/src/providers/osv/types.js.map +1 -0
  171. package/dist/src/storage/memory-cache.d.ts +7 -0
  172. package/dist/src/storage/memory-cache.js +25 -0
  173. package/dist/src/storage/memory-cache.js.map +1 -0
  174. package/package.json +5 -3
@@ -0,0 +1,6 @@
1
+ import type { Analyzer, AnalyzerContext, AnalyzerResult } from '../../contracts/analyzer.js';
2
+ export declare class AstSecurityAnalyzer implements Analyzer {
3
+ readonly id = "typescript-ast-security";
4
+ readonly version = "1.0.0";
5
+ analyze(context: AnalyzerContext): Promise<AnalyzerResult>;
6
+ }
@@ -0,0 +1,64 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { createScannerContext } from '../../core/scanner-context.js';
3
+ import { analyzeAstSource } from './source-analysis.js';
4
+ const supportedExtensions = new Set([
5
+ 'js',
6
+ 'jsx',
7
+ 'ts',
8
+ 'tsx',
9
+ 'mjs',
10
+ 'cjs'
11
+ ]);
12
+ function shouldAnalyze(relativePath, extension) {
13
+ if (!supportedExtensions.has(extension))
14
+ return false;
15
+ if (relativePath.endsWith('.d.ts'))
16
+ return false;
17
+ if (relativePath.endsWith('.map'))
18
+ return false;
19
+ if (relativePath.startsWith('dist/'))
20
+ return false;
21
+ return true;
22
+ }
23
+ export class AstSecurityAnalyzer {
24
+ id = 'typescript-ast-security';
25
+ version = '1.0.0';
26
+ async analyze(context) {
27
+ const startedAt = performance.now();
28
+ const scannerContext = await createScannerContext(context.root);
29
+ const findings = [];
30
+ const warnings = [];
31
+ let filesAnalyzed = 0;
32
+ for (const file of scannerContext.files) {
33
+ if (!shouldAnalyze(file.relativePath, file.extension)) {
34
+ continue;
35
+ }
36
+ if (context.signal?.aborted) {
37
+ throw new Error('AST security analysis was cancelled.');
38
+ }
39
+ try {
40
+ const content = await readFile(file.absolutePath, 'utf8');
41
+ findings.push(...analyzeAstSource(file.relativePath, content));
42
+ filesAnalyzed += 1;
43
+ }
44
+ catch (error) {
45
+ const message = error instanceof Error
46
+ ? error.message
47
+ : String(error);
48
+ warnings.push(`${file.relativePath}: ${message}`);
49
+ }
50
+ }
51
+ return {
52
+ analyzer: this.id,
53
+ durationMs: Math.round(performance.now() - startedAt),
54
+ findings,
55
+ warnings: warnings.length > 0 ? warnings : undefined,
56
+ metadata: {
57
+ filesAnalyzed,
58
+ findings: findings.length,
59
+ parser: 'typescript-compiler-api'
60
+ }
61
+ };
62
+ }
63
+ }
64
+ //# sourceMappingURL=ast-security-analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast-security-analyzer.js","sourceRoot":"","sources":["../../../../src/analyzers/ast/ast-security-analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAM5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC;IAClC,IAAI;IACJ,KAAK;IACL,IAAI;IACJ,KAAK;IACL,KAAK;IACL,KAAK;CACN,CAAC,CAAC;AAEH,SAAS,aAAa,CACpB,YAAoB,EACpB,SAAiB;IAEjB,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,SAAS,CAAC;QAAE,OAAO,KAAK,CAAC;IACtD,IAAI,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC;QAAE,OAAO,KAAK,CAAC;IACjD,IAAI,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAC;IAChD,IAAI,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,KAAK,CAAC;IACnD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,OAAO,mBAAmB;IACrB,EAAE,GAAG,yBAAyB,CAAC;IAC/B,OAAO,GAAG,OAAO,CAAC;IAE3B,KAAK,CAAC,OAAO,CACX,OAAwB;QAExB,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QACpC,MAAM,cAAc,GAAG,MAAM,oBAAoB,CAC/C,OAAO,CAAC,IAAI,CACb,CAAC;QACF,MAAM,QAAQ,GAAG,EAAE,CAAC;QACpB,MAAM,QAAQ,GAAa,EAAE,CAAC;QAC9B,IAAI,aAAa,GAAG,CAAC,CAAC;QAEtB,KAAK,MAAM,IAAI,IAAI,cAAc,CAAC,KAAK,EAAE,CAAC;YACxC,IACE,CAAC,aAAa,CACZ,IAAI,CAAC,YAAY,EACjB,IAAI,CAAC,SAAS,CACf,EACD,CAAC;gBACD,SAAS;YACX,CAAC;YAED,IAAI,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;gBAC5B,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;YAC1D,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAC5B,IAAI,CAAC,YAAY,EACjB,MAAM,CACP,CAAC;gBAEF,QAAQ,CAAC,IAAI,CACX,GAAG,gBAAgB,CACjB,IAAI,CAAC,YAAY,EACjB,OAAO,CACR,CACF,CAAC;gBAEF,aAAa,IAAI,CAAC,CAAC;YACrB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,OAAO,GACX,KAAK,YAAY,KAAK;oBACpB,CAAC,CAAC,KAAK,CAAC,OAAO;oBACf,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBAEpB,QAAQ,CAAC,IAAI,CACX,GAAG,IAAI,CAAC,YAAY,KAAK,OAAO,EAAE,CACnC,CAAC;YACJ,CAAC;QACH,CAAC;QAED,OAAO;YACL,QAAQ,EAAE,IAAI,CAAC,EAAE;YACjB,UAAU,EAAE,IAAI,CAAC,KAAK,CACpB,WAAW,CAAC,GAAG,EAAE,GAAG,SAAS,CAC9B;YACD,QAAQ;YACR,QAAQ,EACN,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;YAC5C,QAAQ,EAAE;gBACR,aAAa;gBACb,QAAQ,EAAE,QAAQ,CAAC,MAAM;gBACzB,MAAM,EAAE,yBAAyB;aAClC;SACF,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,48 @@
1
+ import type { FindingConfidence, FindingSeverity } from '../../contracts/finding.js';
2
+ export type AstSecurityRule = {
3
+ id: string;
4
+ title: string;
5
+ category: 'dangerous-code';
6
+ severity: FindingSeverity;
7
+ confidence: FindingConfidence;
8
+ message: string;
9
+ remediation: string;
10
+ };
11
+ export declare const astSecurityRules: {
12
+ eval: {
13
+ id: string;
14
+ title: string;
15
+ category: "dangerous-code";
16
+ severity: "high";
17
+ confidence: "high";
18
+ message: string;
19
+ remediation: string;
20
+ };
21
+ functionConstructor: {
22
+ id: string;
23
+ title: string;
24
+ category: "dangerous-code";
25
+ severity: "high";
26
+ confidence: "high";
27
+ message: string;
28
+ remediation: string;
29
+ };
30
+ childProcessExec: {
31
+ id: string;
32
+ title: string;
33
+ category: "dangerous-code";
34
+ severity: "high";
35
+ confidence: "high";
36
+ message: string;
37
+ remediation: string;
38
+ };
39
+ childProcessExecSync: {
40
+ id: string;
41
+ title: string;
42
+ category: "dangerous-code";
43
+ severity: "high";
44
+ confidence: "high";
45
+ message: string;
46
+ remediation: string;
47
+ };
48
+ };
@@ -0,0 +1,39 @@
1
+ export const astSecurityRules = {
2
+ eval: {
3
+ id: 'TLP-AST-001',
4
+ title: 'Dynamic eval execution',
5
+ category: 'dangerous-code',
6
+ severity: 'high',
7
+ confidence: 'high',
8
+ message: 'eval() executes code from a string and can introduce code-injection vulnerabilities.',
9
+ remediation: 'Replace eval() with explicit parsing, validated dispatch, or a purpose-built interpreter.'
10
+ },
11
+ functionConstructor: {
12
+ id: 'TLP-AST-002',
13
+ title: 'Dynamic Function constructor',
14
+ category: 'dangerous-code',
15
+ severity: 'high',
16
+ confidence: 'high',
17
+ message: 'The Function constructor creates executable code from strings.',
18
+ remediation: 'Use explicit functions and validated control flow instead of runtime code generation.'
19
+ },
20
+ childProcessExec: {
21
+ id: 'TLP-AST-003',
22
+ title: 'Shell execution with child_process.exec',
23
+ category: 'dangerous-code',
24
+ severity: 'high',
25
+ confidence: 'high',
26
+ message: 'child_process.exec() invokes a shell and can become vulnerable when command input is not strictly controlled.',
27
+ remediation: 'Prefer execFile() or spawn() with argument arrays and validate every untrusted value.'
28
+ },
29
+ childProcessExecSync: {
30
+ id: 'TLP-AST-004',
31
+ title: 'Synchronous shell execution with child_process.execSync',
32
+ category: 'dangerous-code',
33
+ severity: 'high',
34
+ confidence: 'high',
35
+ message: 'child_process.execSync() invokes a shell synchronously and can introduce injection and availability risks.',
36
+ remediation: 'Avoid shell interpolation. Prefer execFileSync() or spawnSync() with validated argument arrays.'
37
+ }
38
+ };
39
+ //# sourceMappingURL=rules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rules.js","sourceRoot":"","sources":["../../../../src/analyzers/ast/rules.ts"],"names":[],"mappings":"AAeA,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,IAAI,EAAE;QACJ,EAAE,EAAE,aAAa;QACjB,KAAK,EAAE,wBAAwB;QAC/B,QAAQ,EAAE,gBAAgB;QAC1B,QAAQ,EAAE,MAAM;QAChB,UAAU,EAAE,MAAM;QAClB,OAAO,EACL,sFAAsF;QACxF,WAAW,EACT,2FAA2F;KAC9F;IACD,mBAAmB,EAAE;QACnB,EAAE,EAAE,aAAa;QACjB,KAAK,EAAE,8BAA8B;QACrC,QAAQ,EAAE,gBAAgB;QAC1B,QAAQ,EAAE,MAAM;QAChB,UAAU,EAAE,MAAM;QAClB,OAAO,EACL,gEAAgE;QAClE,WAAW,EACT,uFAAuF;KAC1F;IACD,gBAAgB,EAAE;QAChB,EAAE,EAAE,aAAa;QACjB,KAAK,EAAE,yCAAyC;QAChD,QAAQ,EAAE,gBAAgB;QAC1B,QAAQ,EAAE,MAAM;QAChB,UAAU,EAAE,MAAM;QAClB,OAAO,EACL,+GAA+G;QACjH,WAAW,EACT,uFAAuF;KAC1F;IACD,oBAAoB,EAAE;QACpB,EAAE,EAAE,aAAa;QACjB,KAAK,EAAE,yDAAyD;QAChE,QAAQ,EAAE,gBAAgB;QAC1B,QAAQ,EAAE,MAAM;QAChB,UAAU,EAAE,MAAM;QAClB,OAAO,EACL,4GAA4G;QAC9G,WAAW,EACT,iGAAiG;KACpG;CACwC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { Finding } from '../../contracts/finding.js';
2
+ export declare function analyzeAstSource(filePath: string, content: string): Finding[];
@@ -0,0 +1,225 @@
1
+ import ts from 'typescript';
2
+ import { astSecurityRules } from './rules.js';
3
+ function scriptKind(filePath) {
4
+ if (filePath.endsWith('.tsx'))
5
+ return ts.ScriptKind.TSX;
6
+ if (filePath.endsWith('.jsx'))
7
+ return ts.ScriptKind.JSX;
8
+ if (filePath.endsWith('.js'))
9
+ return ts.ScriptKind.JS;
10
+ if (filePath.endsWith('.mjs'))
11
+ return ts.ScriptKind.JS;
12
+ if (filePath.endsWith('.cjs'))
13
+ return ts.ScriptKind.JS;
14
+ return ts.ScriptKind.TS;
15
+ }
16
+ function isChildProcessModule(value) {
17
+ return value === 'child_process' || value === 'node:child_process';
18
+ }
19
+ function moduleNameFromImport(declaration) {
20
+ return ts.isStringLiteral(declaration.moduleSpecifier)
21
+ ? declaration.moduleSpecifier.text
22
+ : undefined;
23
+ }
24
+ function requireModuleName(expression) {
25
+ if (!expression ||
26
+ !ts.isCallExpression(expression) ||
27
+ !ts.isIdentifier(expression.expression) ||
28
+ expression.expression.text !== 'require' ||
29
+ expression.arguments.length !== 1) {
30
+ return undefined;
31
+ }
32
+ const [argument] = expression.arguments;
33
+ return argument && ts.isStringLiteral(argument)
34
+ ? argument.text
35
+ : undefined;
36
+ }
37
+ function collectBindings(sourceFile) {
38
+ const bindings = {
39
+ namespaceImports: new Set(),
40
+ execImports: new Set(),
41
+ execSyncImports: new Set()
42
+ };
43
+ for (const statement of sourceFile.statements) {
44
+ if (ts.isImportDeclaration(statement)) {
45
+ const moduleName = moduleNameFromImport(statement);
46
+ if (!moduleName || !isChildProcessModule(moduleName)) {
47
+ continue;
48
+ }
49
+ const importClause = statement.importClause;
50
+ if (!importClause) {
51
+ continue;
52
+ }
53
+ const bindingsClause = importClause.namedBindings;
54
+ if (bindingsClause && ts.isNamespaceImport(bindingsClause)) {
55
+ bindings.namespaceImports.add(bindingsClause.name.text);
56
+ }
57
+ if (bindingsClause && ts.isNamedImports(bindingsClause)) {
58
+ for (const element of bindingsClause.elements) {
59
+ const importedName = element.propertyName?.text ?? element.name.text;
60
+ const localName = element.name.text;
61
+ if (importedName === 'exec') {
62
+ bindings.execImports.add(localName);
63
+ }
64
+ if (importedName === 'execSync') {
65
+ bindings.execSyncImports.add(localName);
66
+ }
67
+ }
68
+ }
69
+ }
70
+ if (!ts.isVariableStatement(statement)) {
71
+ continue;
72
+ }
73
+ for (const declaration of statement.declarationList.declarations) {
74
+ const initializer = declaration.initializer;
75
+ const moduleName = requireModuleName(initializer);
76
+ if (moduleName &&
77
+ isChildProcessModule(moduleName) &&
78
+ ts.isIdentifier(declaration.name)) {
79
+ bindings.namespaceImports.add(declaration.name.text);
80
+ }
81
+ if (moduleName &&
82
+ isChildProcessModule(moduleName) &&
83
+ ts.isObjectBindingPattern(declaration.name)) {
84
+ for (const element of declaration.name.elements) {
85
+ if (!ts.isIdentifier(element.name)) {
86
+ continue;
87
+ }
88
+ const importedName = element.propertyName &&
89
+ ts.isIdentifier(element.propertyName)
90
+ ? element.propertyName.text
91
+ : element.name.text;
92
+ if (importedName === 'exec') {
93
+ bindings.execImports.add(element.name.text);
94
+ }
95
+ if (importedName === 'execSync') {
96
+ bindings.execSyncImports.add(element.name.text);
97
+ }
98
+ }
99
+ }
100
+ if (initializer &&
101
+ ts.isPropertyAccessExpression(initializer) &&
102
+ ts.isCallExpression(initializer.expression) &&
103
+ ts.isIdentifier(initializer.expression.expression) &&
104
+ initializer.expression.expression.text === 'require' &&
105
+ initializer.expression.arguments.length === 1) {
106
+ const [argument] = initializer.expression.arguments;
107
+ const requiredModule = argument && ts.isStringLiteral(argument)
108
+ ? argument.text
109
+ : undefined;
110
+ if (requiredModule &&
111
+ isChildProcessModule(requiredModule) &&
112
+ ts.isIdentifier(declaration.name)) {
113
+ if (initializer.name.text === 'exec') {
114
+ bindings.execImports.add(declaration.name.text);
115
+ }
116
+ if (initializer.name.text === 'execSync') {
117
+ bindings.execSyncImports.add(declaration.name.text);
118
+ }
119
+ }
120
+ }
121
+ }
122
+ }
123
+ return bindings;
124
+ }
125
+ function findingLocation(sourceFile, node) {
126
+ const start = sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile));
127
+ const end = sourceFile.getLineAndCharacterOfPosition(node.getEnd());
128
+ return {
129
+ file: sourceFile.fileName,
130
+ line: start.line + 1,
131
+ column: start.character + 1,
132
+ endLine: end.line + 1,
133
+ endColumn: end.character + 1
134
+ };
135
+ }
136
+ function evidenceExcerpt(sourceFile, node) {
137
+ const text = node
138
+ .getText(sourceFile)
139
+ .replaceAll(/\s+/g, ' ')
140
+ .trim();
141
+ return text.length <= 180
142
+ ? text
143
+ : `${text.slice(0, 177)}...`;
144
+ }
145
+ function createFinding(sourceFile, node, rule) {
146
+ const location = findingLocation(sourceFile, node);
147
+ const fingerprint = `${rule.id}:${sourceFile.fileName}:` +
148
+ `${location?.line ?? 0}:${location?.column ?? 0}`;
149
+ return {
150
+ id: fingerprint,
151
+ ruleId: rule.id,
152
+ title: rule.title,
153
+ category: rule.category,
154
+ severity: rule.severity,
155
+ confidence: rule.confidence,
156
+ message: rule.message,
157
+ source: 'typescript-ast',
158
+ location,
159
+ evidence: [
160
+ {
161
+ summary: evidenceExcerpt(sourceFile, node),
162
+ fingerprint
163
+ }
164
+ ],
165
+ remediation: {
166
+ summary: rule.remediation
167
+ },
168
+ metadata: {
169
+ nodeKind: ts.SyntaxKind[node.kind]
170
+ }
171
+ };
172
+ }
173
+ function childProcessRuleForCall(call, bindings) {
174
+ const target = call.expression;
175
+ if (ts.isIdentifier(target)) {
176
+ if (bindings.execImports.has(target.text)) {
177
+ return astSecurityRules.childProcessExec;
178
+ }
179
+ if (bindings.execSyncImports.has(target.text)) {
180
+ return astSecurityRules.childProcessExecSync;
181
+ }
182
+ return undefined;
183
+ }
184
+ if (!ts.isPropertyAccessExpression(target)) {
185
+ return undefined;
186
+ }
187
+ if (!ts.isIdentifier(target.expression) ||
188
+ !bindings.namespaceImports.has(target.expression.text)) {
189
+ return undefined;
190
+ }
191
+ if (target.name.text === 'exec') {
192
+ return astSecurityRules.childProcessExec;
193
+ }
194
+ if (target.name.text === 'execSync') {
195
+ return astSecurityRules.childProcessExecSync;
196
+ }
197
+ return undefined;
198
+ }
199
+ export function analyzeAstSource(filePath, content) {
200
+ const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true, scriptKind(filePath));
201
+ const bindings = collectBindings(sourceFile);
202
+ const findings = [];
203
+ const visit = (node) => {
204
+ if (ts.isCallExpression(node) &&
205
+ ts.isIdentifier(node.expression) &&
206
+ node.expression.text === 'eval') {
207
+ findings.push(createFinding(sourceFile, node, astSecurityRules.eval));
208
+ }
209
+ if (ts.isNewExpression(node) &&
210
+ ts.isIdentifier(node.expression) &&
211
+ node.expression.text === 'Function') {
212
+ findings.push(createFinding(sourceFile, node, astSecurityRules.functionConstructor));
213
+ }
214
+ if (ts.isCallExpression(node)) {
215
+ const childProcessRule = childProcessRuleForCall(node, bindings);
216
+ if (childProcessRule) {
217
+ findings.push(createFinding(sourceFile, node, childProcessRule));
218
+ }
219
+ }
220
+ ts.forEachChild(node, visit);
221
+ };
222
+ visit(sourceFile);
223
+ return findings;
224
+ }
225
+ //# sourceMappingURL=source-analysis.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-analysis.js","sourceRoot":"","sources":["../../../../src/analyzers/ast/source-analysis.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { Analyzer, AnalyzerContext, AnalyzerResult } from '../../contracts/analyzer.js';
2
+ export type RegistryLookup = (packageName: string, signal?: AbortSignal) => Promise<boolean>;
3
+ export declare class DependencyConfusionAnalyzer implements Analyzer {
4
+ private readonly lookup;
5
+ readonly id = "dependency-confusion";
6
+ readonly version = "1.0.0";
7
+ constructor(lookup?: RegistryLookup);
8
+ analyze(context: AnalyzerContext): Promise<AnalyzerResult>;
9
+ }
@@ -0,0 +1,98 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ function dependencies(manifest) {
4
+ const sections = [
5
+ 'dependencies',
6
+ 'devDependencies',
7
+ 'optionalDependencies',
8
+ 'peerDependencies'
9
+ ];
10
+ const output = [];
11
+ for (const section of sections) {
12
+ for (const [name, requirement] of Object.entries(manifest[section] ?? {})) {
13
+ output.push({
14
+ name,
15
+ requirement,
16
+ section
17
+ });
18
+ }
19
+ }
20
+ return output;
21
+ }
22
+ function internalSignal(name, requirement) {
23
+ return (requirement.startsWith('file:') ||
24
+ requirement.startsWith('workspace:') ||
25
+ requirement.startsWith('link:') ||
26
+ requirement.startsWith('git+') ||
27
+ requirement.startsWith('github:') ||
28
+ (name.startsWith('@') &&
29
+ (requirement === '*' ||
30
+ requirement === 'latest')));
31
+ }
32
+ async function defaultLookup(packageName, signal) {
33
+ const response = await fetch(`https://registry.npmjs.org/${encodeURIComponent(packageName)}`, {
34
+ method: 'HEAD',
35
+ headers: {
36
+ 'user-agent': 'toolip'
37
+ },
38
+ signal
39
+ });
40
+ if (response.status === 404) {
41
+ return false;
42
+ }
43
+ if (!response.ok) {
44
+ throw new Error(`npm registry lookup failed with HTTP ${response.status}.`);
45
+ }
46
+ return true;
47
+ }
48
+ export class DependencyConfusionAnalyzer {
49
+ lookup;
50
+ id = 'dependency-confusion';
51
+ version = '1.0.0';
52
+ constructor(lookup = defaultLookup) {
53
+ this.lookup = lookup;
54
+ }
55
+ async analyze(context) {
56
+ const startedAt = performance.now();
57
+ const manifest = JSON.parse(await readFile(path.join(context.root, 'package.json'), 'utf8'));
58
+ const candidates = dependencies(manifest).filter((item) => internalSignal(item.name, item.requirement));
59
+ const findings = [];
60
+ for (const candidate of candidates) {
61
+ const existsPublicly = await this.lookup(candidate.name, context.signal);
62
+ if (!existsPublicly) {
63
+ continue;
64
+ }
65
+ findings.push({
66
+ id: `TLP-CONFUSION-001:${candidate.name}`,
67
+ ruleId: 'TLP-CONFUSION-001',
68
+ title: `Internal dependency name exists publicly: ${candidate.name}`,
69
+ category: 'dependency-confusion',
70
+ severity: 'high',
71
+ confidence: 'medium',
72
+ message: `${candidate.name} uses ${candidate.requirement} in ` +
73
+ `${candidate.section}, but the same name exists on the public npm registry.`,
74
+ source: 'npm-registry',
75
+ evidence: [
76
+ {
77
+ summary: `${candidate.section}: ${candidate.name} = ${candidate.requirement}`,
78
+ fingerprint: `${candidate.name}:${candidate.requirement}`
79
+ }
80
+ ],
81
+ remediation: {
82
+ summary: 'Use an organization-controlled scope, enforce a private registry for the scope, pin registry configuration, and verify package provenance.'
83
+ },
84
+ metadata: candidate
85
+ });
86
+ }
87
+ return {
88
+ analyzer: this.id,
89
+ durationMs: Math.round(performance.now() - startedAt),
90
+ findings,
91
+ metadata: {
92
+ candidates: candidates.length,
93
+ publicCollisions: findings.length
94
+ }
95
+ };
96
+ }
97
+ }
98
+ //# sourceMappingURL=analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../../../../src/analyzers/dependency-confusion/analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,IAAI,MAAM,WAAW,CAAC;AAoB7B,SAAS,YAAY,CACnB,QAAyB;IAMzB,MAAM,QAAQ,GAAG;QACf,cAAc;QACd,iBAAiB;QACjB,sBAAsB;QACtB,kBAAkB;KACV,CAAC;IAEX,MAAM,MAAM,GAIP,EAAE,CAAC;IAER,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,KAAK,MAAM,CAAC,IAAI,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAC9C,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,CACxB,EAAE,CAAC;YACF,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI;gBACJ,WAAW;gBACX,OAAO;aACR,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,cAAc,CACrB,IAAY,EACZ,WAAmB;IAEnB,OAAO,CACL,WAAW,CAAC,UAAU,CAAC,OAAO,CAAC;QAC/B,WAAW,CAAC,UAAU,CAAC,YAAY,CAAC;QACpC,WAAW,CAAC,UAAU,CAAC,OAAO,CAAC;QAC/B,WAAW,CAAC,UAAU,CAAC,MAAM,CAAC;QAC9B,WAAW,CAAC,UAAU,CAAC,SAAS,CAAC;QACjC,CACE,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YACpB,CACE,WAAW,KAAK,GAAG;gBACnB,WAAW,KAAK,QAAQ,CACzB,CACF,CACF,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,aAAa,CAC1B,WAAmB,EACnB,MAAoB;IAEpB,MAAM,QAAQ,GAAG,MAAM,KAAK,CAC1B,8BAA8B,kBAAkB,CAC9C,WAAW,CACZ,EAAE,EACH;QACE,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,YAAY,EAAE,QAAQ;SACvB;QACD,MAAM;KACP,CACF,CAAC;IAEF,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QAC5B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CACb,wCAAwC,QAAQ,CAAC,MAAM,GAAG,CAC3D,CAAC;IACJ,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,OAAO,2BAA2B;IAOnB;IAJV,EAAE,GAAG,sBAAsB,CAAC;IAC5B,OAAO,GAAG,OAAO,CAAC;IAE3B,YACmB,SACf,aAAa;QADE,WAAM,GAAN,MAAM,CACR;IACd,CAAC;IAEJ,KAAK,CAAC,OAAO,CACX,OAAwB;QAExB,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QACpC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CACzB,MAAM,QAAQ,CACZ,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,cAAc,CAAC,EACvC,MAAM,CACP,CACiB,CAAC;QAErB,MAAM,UAAU,GACd,YAAY,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CACrC,cAAc,CACZ,IAAI,CAAC,IAAI,EACT,IAAI,CAAC,WAAW,CACjB,CACF,CAAC;QAEJ,MAAM,QAAQ,GAAc,EAAE,CAAC;QAE/B,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACnC,MAAM,cAAc,GAClB,MAAM,IAAI,CAAC,MAAM,CACf,SAAS,CAAC,IAAI,EACd,OAAO,CAAC,MAAM,CACf,CAAC;YAEJ,IAAI,CAAC,cAAc,EAAE,CAAC;gBACpB,SAAS;YACX,CAAC;YAED,QAAQ,CAAC,IAAI,CAAC;gBACZ,EAAE,EACA,qBAAqB,SAAS,CAAC,IAAI,EAAE;gBACvC,MAAM,EAAE,mBAAmB;gBAC3B,KAAK,EACH,6CAA6C,SAAS,CAAC,IAAI,EAAE;gBAC/D,QAAQ,EAAE,sBAAsB;gBAChC,QAAQ,EAAE,MAAM;gBAChB,UAAU,EAAE,QAAQ;gBACpB,OAAO,EACL,GAAG,SAAS,CAAC,IAAI,SAAS,SAAS,CAAC,WAAW,MAAM;oBACrD,GAAG,SAAS,CAAC,OAAO,wDAAwD;gBAC9E,MAAM,EAAE,cAAc;gBACtB,QAAQ,EAAE;oBACR;wBACE,OAAO,EACL,GAAG,SAAS,CAAC,OAAO,KAAK,SAAS,CAAC,IAAI,MAAM,SAAS,CAAC,WAAW,EAAE;wBACtE,WAAW,EACT,GAAG,SAAS,CAAC,IAAI,IAAI,SAAS,CAAC,WAAW,EAAE;qBAC/C;iBACF;gBACD,WAAW,EAAE;oBACX,OAAO,EACL,4IAA4I;iBAC/I;gBACD,QAAQ,EAAE,SAAS;aACpB,CAAC,CAAC;QACL,CAAC;QAED,OAAO;YACL,QAAQ,EAAE,IAAI,CAAC,EAAE;YACjB,UAAU,EAAE,IAAI,CAAC,KAAK,CACpB,WAAW,CAAC,GAAG,EAAE,GAAG,SAAS,CAC9B;YACD,QAAQ;YACR,QAAQ,EAAE;gBACR,UAAU,EAAE,UAAU,CAAC,MAAM;gBAC7B,gBAAgB,EAAE,QAAQ,CAAC,MAAM;aAClC;SACF,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,6 @@
1
+ import type { Analyzer, AnalyzerContext, AnalyzerResult } from '../../contracts/analyzer.js';
2
+ export declare class DockerfileAnalyzer implements Analyzer {
3
+ readonly id = "dockerfile-security";
4
+ readonly version = "1.0.0";
5
+ analyze(context: AnalyzerContext): Promise<AnalyzerResult>;
6
+ }
@@ -0,0 +1,103 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { createScannerContext } from '../../core/scanner-context.js';
3
+ const rules = [
4
+ {
5
+ id: 'TLP-DOCKER-001',
6
+ title: 'Container may run as root',
7
+ severity: 'high',
8
+ test: (_line, lines) => !lines.some((line) => /^USER\s+(?!root\b|0\b)/i.test(line.trim())),
9
+ message: 'No non-root USER instruction was found.',
10
+ remediation: 'Create and switch to a dedicated non-root user before the final command.'
11
+ },
12
+ {
13
+ id: 'TLP-DOCKER-002',
14
+ title: 'Secret-like value in Docker ARG or ENV',
15
+ severity: 'critical',
16
+ test: (line) => /^(ARG|ENV)\s+.*(TOKEN|SECRET|PASSWORD|API_KEY|PRIVATE_KEY)/i.test(line.trim()),
17
+ message: 'A secret-like variable is declared through ARG or ENV.',
18
+ remediation: 'Use runtime secret injection or BuildKit secret mounts instead of image metadata.'
19
+ },
20
+ {
21
+ id: 'TLP-DOCKER-003',
22
+ title: 'Unpinned base image tag',
23
+ severity: 'medium',
24
+ test: (line) => /^FROM\s+\S+(?::latest)?(?:\s|$)/i.test(line.trim()) && !/@sha256:/i.test(line),
25
+ message: 'The base image is not pinned by digest.',
26
+ remediation: 'Pin trusted base images by immutable digest and review updates deliberately.'
27
+ },
28
+ {
29
+ id: 'TLP-DOCKER-004',
30
+ title: 'Remote ADD instruction',
31
+ severity: 'high',
32
+ test: (line) => /^ADD\s+https?:\/\//i.test(line.trim()),
33
+ message: 'ADD downloads remote content during the image build.',
34
+ remediation: 'Download explicitly, verify checksums, and use COPY for local content.'
35
+ },
36
+ {
37
+ id: 'TLP-DOCKER-005',
38
+ title: 'Package installation without cleanup',
39
+ severity: 'low',
40
+ test: (line) => /apt-get\s+install/i.test(line) && !/rm\s+-rf\s+\/var\/lib\/apt\/lists/i.test(line),
41
+ message: 'apt package metadata may remain in the image layer.',
42
+ remediation: 'Combine installation and cleanup in the same RUN instruction.'
43
+ }
44
+ ];
45
+ export class DockerfileAnalyzer {
46
+ id = 'dockerfile-security';
47
+ version = '1.0.0';
48
+ async analyze(context) {
49
+ const startedAt = performance.now();
50
+ const scanner = await createScannerContext(context.root);
51
+ const findings = [];
52
+ let dockerfiles = 0;
53
+ for (const file of scanner.files) {
54
+ if (!/(^|\/)Dockerfile(?:\.[^/]+)?$/i.test(file.relativePath))
55
+ continue;
56
+ dockerfiles += 1;
57
+ const content = await readFile(file.absolutePath, 'utf8');
58
+ const lines = content.split(/\r?\n/);
59
+ for (const rule of rules) {
60
+ const matches = rule.id === 'TLP-DOCKER-001'
61
+ ? [lines[0] ?? '']
62
+ : lines.filter((line) => rule.test(line, lines));
63
+ if (rule.id === 'TLP-DOCKER-001' && !rule.test('', lines))
64
+ continue;
65
+ for (const match of matches) {
66
+ const lineNumber = Math.max(1, lines.indexOf(match) + 1);
67
+ findings.push({
68
+ id: `${rule.id}:${file.relativePath}:${lineNumber}`,
69
+ ruleId: rule.id,
70
+ title: rule.title,
71
+ category: 'container',
72
+ severity: rule.severity,
73
+ confidence: 'high',
74
+ message: rule.message,
75
+ source: 'dockerfile',
76
+ location: {
77
+ file: file.relativePath,
78
+ line: lineNumber,
79
+ column: 1
80
+ },
81
+ evidence: [{
82
+ summary: match.trim().slice(0, 200) || 'No non-root USER instruction',
83
+ fingerprint: `${file.relativePath}:${lineNumber}:${rule.id}`
84
+ }],
85
+ remediation: {
86
+ summary: rule.remediation
87
+ }
88
+ });
89
+ }
90
+ }
91
+ }
92
+ return {
93
+ analyzer: this.id,
94
+ durationMs: Math.round(performance.now() - startedAt),
95
+ findings,
96
+ metadata: {
97
+ dockerfiles,
98
+ findings: findings.length
99
+ }
100
+ };
101
+ }
102
+ }
103
+ //# sourceMappingURL=analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../../../../src/analyzers/docker/analyzer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { Analyzer, AnalyzerContext, AnalyzerResult } from '../../contracts/analyzer.js';
2
+ export declare class GitHistorySecretAnalyzer implements Analyzer {
3
+ private readonly maxCommits;
4
+ readonly id = "git-history-secrets";
5
+ readonly version = "1.0.1";
6
+ constructor(maxCommits?: number);
7
+ analyze(context: AnalyzerContext): Promise<AnalyzerResult>;
8
+ }