guardrail-security 1.0.1 → 2.0.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 (66) hide show
  1. package/dist/attack-surface/analyzer.d.ts.map +1 -1
  2. package/dist/attack-surface/analyzer.js +3 -2
  3. package/dist/license/engine.d.ts.map +1 -1
  4. package/dist/license/engine.js +3 -2
  5. package/dist/sbom/generator.d.ts +42 -0
  6. package/dist/sbom/generator.d.ts.map +1 -1
  7. package/dist/sbom/generator.js +168 -7
  8. package/dist/secrets/allowlist.d.ts +38 -0
  9. package/dist/secrets/allowlist.d.ts.map +1 -0
  10. package/dist/secrets/allowlist.js +131 -0
  11. package/dist/secrets/config-loader.d.ts +25 -0
  12. package/dist/secrets/config-loader.d.ts.map +1 -0
  13. package/dist/secrets/config-loader.js +103 -0
  14. package/dist/secrets/contextual-risk.d.ts +19 -0
  15. package/dist/secrets/contextual-risk.d.ts.map +1 -0
  16. package/dist/secrets/contextual-risk.js +88 -0
  17. package/dist/secrets/git-scanner.d.ts +29 -0
  18. package/dist/secrets/git-scanner.d.ts.map +1 -0
  19. package/dist/secrets/git-scanner.js +109 -0
  20. package/dist/secrets/guardian.d.ts +70 -57
  21. package/dist/secrets/guardian.d.ts.map +1 -1
  22. package/dist/secrets/guardian.js +532 -240
  23. package/dist/secrets/index.d.ts +4 -0
  24. package/dist/secrets/index.d.ts.map +1 -1
  25. package/dist/secrets/index.js +11 -1
  26. package/dist/secrets/patterns.d.ts +39 -10
  27. package/dist/secrets/patterns.d.ts.map +1 -1
  28. package/dist/secrets/patterns.js +129 -71
  29. package/dist/secrets/pre-commit.d.ts.map +1 -1
  30. package/dist/secrets/pre-commit.js +1 -1
  31. package/dist/secrets/vault-integration.d.ts.map +1 -1
  32. package/dist/secrets/vault-integration.js +1 -0
  33. package/dist/supply-chain/detector.d.ts.map +1 -1
  34. package/dist/supply-chain/detector.js +4 -3
  35. package/dist/supply-chain/vulnerability-db.d.ts +89 -16
  36. package/dist/supply-chain/vulnerability-db.d.ts.map +1 -1
  37. package/dist/supply-chain/vulnerability-db.js +404 -115
  38. package/dist/utils/semver.d.ts +37 -0
  39. package/dist/utils/semver.d.ts.map +1 -0
  40. package/dist/utils/semver.js +109 -0
  41. package/package.json +17 -4
  42. package/src/__tests__/license/engine.test.ts +0 -250
  43. package/src/__tests__/supply-chain/typosquat.test.ts +0 -191
  44. package/src/attack-surface/analyzer.ts +0 -152
  45. package/src/attack-surface/index.ts +0 -5
  46. package/src/index.ts +0 -21
  47. package/src/languages/index.ts +0 -91
  48. package/src/languages/java-analyzer.ts +0 -490
  49. package/src/languages/python-analyzer.ts +0 -498
  50. package/src/license/compatibility-matrix.ts +0 -366
  51. package/src/license/engine.ts +0 -345
  52. package/src/license/index.ts +0 -6
  53. package/src/sbom/generator.ts +0 -355
  54. package/src/sbom/index.ts +0 -5
  55. package/src/secrets/guardian.ts +0 -448
  56. package/src/secrets/index.ts +0 -10
  57. package/src/secrets/patterns.ts +0 -186
  58. package/src/secrets/pre-commit.ts +0 -158
  59. package/src/secrets/vault-integration.ts +0 -360
  60. package/src/secrets/vault-providers.ts +0 -446
  61. package/src/supply-chain/detector.ts +0 -252
  62. package/src/supply-chain/index.ts +0 -11
  63. package/src/supply-chain/malicious-db.ts +0 -103
  64. package/src/supply-chain/script-analyzer.ts +0 -194
  65. package/src/supply-chain/typosquat.ts +0 -302
  66. package/src/supply-chain/vulnerability-db.ts +0 -386
@@ -1 +1 @@
1
- {"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../../src/attack-surface/analyzer.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,GAAG,MAAM,CAAC;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,aAAa,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;IACjD,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;CACvC;AAED,MAAM,WAAW,2BAA2B;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE;QACP,gBAAgB,EAAE,MAAM,CAAC;QACzB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC/B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACtC,CAAC;IACF,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,WAAW,EAAE,kBAAkB,EAAE,CAAC;CACnC;AAED,qBAAa,qBAAqB;IAC1B,cAAc,CAClB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,2BAA2B,CAAC;YA0CzB,iBAAiB;YAKjB,gBAAgB;YA8BhB,gBAAgB;IAOxB,qBAAqB,CACzB,QAAQ,EAAE,2BAA2B,GACpC,OAAO,CAAC,MAAM,CAAC;CAWnB;AAED,eAAO,MAAM,qBAAqB,uBAA8B,CAAC"}
1
+ {"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../../src/attack-surface/analyzer.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,GAAG,MAAM,CAAC;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,aAAa,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;IACjD,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;CACvC;AAED,MAAM,WAAW,2BAA2B;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE;QACP,gBAAgB,EAAE,MAAM,CAAC;QACzB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC/B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACtC,CAAC;IACF,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,WAAW,EAAE,kBAAkB,EAAE,CAAC;CACnC;AAED,qBAAa,qBAAqB;IAC1B,cAAc,CAClB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,2BAA2B,CAAC;YA0CzB,iBAAiB;YAKjB,gBAAgB;YA8BhB,gBAAgB;IAOxB,qBAAqB,CACzB,QAAQ,EAAE,2BAA2B,GACpC,OAAO,CAAC,MAAM,CAAC;CAWnB;AAED,eAAO,MAAM,qBAAqB,uBAA8B,CAAC"}
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.attackSurfaceAnalyzer = exports.AttackSurfaceAnalyzer = void 0;
4
- const database_1 = require("@guardrail/database");
4
+ // Stub prisma for standalone use
5
+ const prisma = null;
5
6
  class AttackSurfaceAnalyzer {
6
7
  async analyzeProject(projectPath, projectId) {
7
8
  const entryPoints = await this.scanHTTPEndpoints(projectPath);
@@ -27,7 +28,7 @@ class AttackSurfaceAnalyzer {
27
28
  attackPaths,
28
29
  apiFindings,
29
30
  };
30
- await database_1.prisma.attackSurfaceAnalysis.create({
31
+ await prisma.attackSurfaceAnalysis.create({
31
32
  data: {
32
33
  projectId,
33
34
  summary: JSON.parse(JSON.stringify(result.summary)),
@@ -1 +1 @@
1
- {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/license/engine.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,SAAS,GAAG,OAAO,CAAC;CAC/B;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE;QACP,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACnC,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,YAAY,EAAE,kBAAkB,EAAE,CAAC;IACnC,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,aAAa,EAAE,iBAAiB,EAAE,CAAC;IACnC,aAAa,EAAE,WAAW,GAAG,SAAS,GAAG,WAAW,CAAC;CACtD;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,mBAAmB,EAAE,OAAO,CAAC;CAC9B;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,uBAAuB;IAC5B,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC;YAoCtG,mBAAmB;IAsCjC;;OAEG;YACW,wBAAwB;IAuCtC;;OAEG;IACH,OAAO,CAAC,6BAA6B;IAyBrC;;OAEG;IACH,OAAO,CAAC,oBAAoB;IA0B5B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAkBzB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IASzB;;OAEG;IACH,UAAU,IAAI,IAAI;IAIlB;;OAEG;IACH,aAAa,IAAI;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,IAAI,GAAG,IAAI,CAAA;KAAE;IAa3D,kBAAkB,CAAC,cAAc,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,mBAAmB;IAkBnF,OAAO,CAAC,sBAAsB;YAoBhB,wBAAwB;IAKhC,wBAAwB,CAAC,QAAQ,EAAE,qBAAqB,GAAG,OAAO,CAAC,MAAM,CAAC;CAiBjF;AAED,eAAO,MAAM,uBAAuB,yBAAgC,CAAC"}
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/license/engine.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,SAAS,GAAG,OAAO,CAAC;CAC/B;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE;QACP,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACnC,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,YAAY,EAAE,kBAAkB,EAAE,CAAC;IACnC,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,aAAa,EAAE,iBAAiB,EAAE,CAAC;IACnC,aAAa,EAAE,WAAW,GAAG,SAAS,GAAG,WAAW,CAAC;CACtD;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,mBAAmB,EAAE,OAAO,CAAC;CAC9B;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,uBAAuB;IAC5B,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC;YAoCtG,mBAAmB;IAsCjC;;OAEG;YACW,wBAAwB;IAuCtC;;OAEG;IACH,OAAO,CAAC,6BAA6B;IAyBrC;;OAEG;IACH,OAAO,CAAC,oBAAoB;IA0B5B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAkBzB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IASzB;;OAEG;IACH,UAAU,IAAI,IAAI;IAIlB;;OAEG;IACH,aAAa,IAAI;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,IAAI,GAAG,IAAI,CAAA;KAAE;IAa3D,kBAAkB,CAAC,cAAc,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,mBAAmB;IAkBnF,OAAO,CAAC,sBAAsB;YAoBhB,wBAAwB;IAKhC,wBAAwB,CAAC,QAAQ,EAAE,qBAAqB,GAAG,OAAO,CAAC,MAAM,CAAC;CAiBjF;AAED,eAAO,MAAM,uBAAuB,yBAAgC,CAAC"}
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.licenseComplianceEngine = exports.LicenseComplianceEngine = void 0;
4
- const database_1 = require("@guardrail/database");
4
+ // Stub prisma for standalone use
5
+ const prisma = null;
5
6
  const compatibility_matrix_1 = require("./compatibility-matrix");
6
7
  const fs_1 = require("fs");
7
8
  const path_1 = require("path");
@@ -35,7 +36,7 @@ class LicenseComplianceEngine {
35
36
  overallStatus,
36
37
  };
37
38
  // @ts-ignore - licenseAnalysis may not exist in schema yet
38
- const analysis = await database_1.prisma.licenseAnalysis.findUnique({
39
+ const analysis = await prisma.licenseAnalysis.findUnique({
39
40
  where: { id: projectId }
40
41
  });
41
42
  return result;
@@ -57,6 +57,24 @@ export interface SBOMGeneratorOptions {
57
57
  includeLicenses?: boolean;
58
58
  includeHashes?: boolean;
59
59
  outputPath?: string;
60
+ vex?: boolean;
61
+ sign?: boolean;
62
+ }
63
+ export interface VEXDocument {
64
+ '@context': string;
65
+ '@id': string;
66
+ author: string;
67
+ timestamp: string;
68
+ version: string;
69
+ statements: VEXStatement[];
70
+ }
71
+ export interface VEXStatement {
72
+ vulnerability: string;
73
+ products: string[];
74
+ status: 'not_affected' | 'affected' | 'fixed' | 'under_investigation';
75
+ justification?: string;
76
+ actionStatement?: string;
77
+ actionStatementTimestamp?: string;
60
78
  }
61
79
  export declare class SBOMGenerator {
62
80
  private readonly toolInfo;
@@ -64,6 +82,10 @@ export declare class SBOMGenerator {
64
82
  * Generate SBOM for a project
65
83
  */
66
84
  generate(projectPath: string, options: SBOMGeneratorOptions): Promise<SBOM>;
85
+ /**
86
+ * Generate SBOM for a container image using syft
87
+ */
88
+ generateContainerSBOM(imageName: string, options: SBOMGeneratorOptions): Promise<SBOM>;
67
89
  /**
68
90
  * Extract components from package.json
69
91
  */
@@ -103,6 +125,26 @@ export declare class SBOMGenerator {
103
125
  valid: boolean;
104
126
  errors: string[];
105
127
  };
128
+ /**
129
+ * Compute hashes for a package
130
+ */
131
+ private computePackageHashes;
132
+ /**
133
+ * Generate VEX document
134
+ */
135
+ private generateVEX;
136
+ /**
137
+ * Sign SBOM using cosign
138
+ */
139
+ private signSBOM;
140
+ /**
141
+ * Check if a tool is available
142
+ */
143
+ private checkToolAvailable;
144
+ /**
145
+ * Normalize container SBOM from syft output
146
+ */
147
+ private normalizeContainerSBOM;
106
148
  }
107
149
  export declare const sbomGenerator: SBOMGenerator;
108
150
  //# sourceMappingURL=generator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/sbom/generator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,MAAM,MAAM,UAAU,GAAG,WAAW,GAAG,MAAM,GAAG,MAAM,CAAC;AAEvD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,SAAS,GAAG,WAAW,GAAG,aAAa,GAAG,MAAM,GAAG,WAAW,CAAC;IACrE,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,CAAC,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAClD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kBAAkB,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACtD;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,IAAI;IACnB,MAAM,EAAE,UAAU,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE;QACR,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE;YAAE,MAAM,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;QAC3D,SAAS,EAAE;YACT,IAAI,EAAE,MAAM,CAAC;YACb,IAAI,EAAE,MAAM,CAAC;YACb,OAAO,EAAE,MAAM,CAAC;SACjB,CAAC;QACF,OAAO,CAAC,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;KAC9C,CAAC;IACF,UAAU,EAAE,aAAa,EAAE,CAAC;IAC5B,YAAY,EAAE,cAAc,EAAE,CAAC;CAChC;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,UAAU,CAAC;IACnB,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAIvB;IAEF;;OAEG;IACG,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IAqCjF;;OAEG;YACW,iBAAiB;IAiD/B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAqB5B;;OAEG;YACW,oBAAoB;IAelC;;OAEG;IACH,OAAO,CAAC,WAAW;IAInB;;OAEG;IACH,OAAO,CAAC,YAAY;IAQpB;;OAEG;YACW,SAAS;IAiBvB;;OAEG;IACH,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM;IAsCnC;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM;IA2C9B;;OAEG;IACH,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE;CAyB/D;AAGD,eAAO,MAAM,aAAa,eAAsB,CAAC"}
1
+ {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/sbom/generator.ts"],"names":[],"mappings":"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"}
@@ -9,6 +9,7 @@ exports.sbomGenerator = exports.SBOMGenerator = void 0;
9
9
  const fs_1 = require("fs");
10
10
  const path_1 = require("path");
11
11
  const crypto_1 = require("crypto");
12
+ const child_process_1 = require("child_process");
12
13
  class SBOMGenerator {
13
14
  toolInfo = {
14
15
  vendor: 'Guardrail AI',
@@ -46,9 +47,55 @@ class SBOMGenerator {
46
47
  };
47
48
  if (options.outputPath) {
48
49
  await this.writeSBOM(sbom, options.outputPath, options.format);
50
+ if (options.vex) {
51
+ const vexPath = options.outputPath.replace(/\.(json|xml)$/, '.vex.json');
52
+ await this.generateVEX(sbom, vexPath);
53
+ }
54
+ if (options.sign) {
55
+ await this.signSBOM(options.outputPath);
56
+ }
49
57
  }
50
58
  return sbom;
51
59
  }
60
+ /**
61
+ * Generate SBOM for a container image using syft
62
+ */
63
+ async generateContainerSBOM(imageName, options) {
64
+ if (!this.checkToolAvailable('syft')) {
65
+ throw new Error('syft is not installed. Install it with:\n' +
66
+ ' curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin\n' +
67
+ ' Or visit: https://github.com/anchore/syft#installation');
68
+ }
69
+ const format = options.format === 'spdx' ? 'spdx-json' : 'cyclonedx-json';
70
+ const tempFile = (0, path_1.join)(process.cwd(), `.sbom-${Date.now()}.json`);
71
+ try {
72
+ (0, child_process_1.execSync)(`syft ${imageName} -o ${format} --file ${tempFile}`, {
73
+ stdio: 'pipe',
74
+ encoding: 'utf-8',
75
+ });
76
+ const rawSBOM = JSON.parse((0, fs_1.readFileSync)(tempFile, 'utf-8'));
77
+ const sbom = this.normalizeContainerSBOM(rawSBOM, options.format, imageName);
78
+ if (options.outputPath) {
79
+ await this.writeSBOM(sbom, options.outputPath, options.format);
80
+ if (options.vex) {
81
+ const vexPath = options.outputPath.replace(/\.(json|xml)$/, '.vex.json');
82
+ await this.generateVEX(sbom, vexPath);
83
+ }
84
+ if (options.sign) {
85
+ await this.signSBOM(options.outputPath);
86
+ }
87
+ }
88
+ return sbom;
89
+ }
90
+ finally {
91
+ if ((0, fs_1.existsSync)(tempFile)) {
92
+ try {
93
+ require('fs').unlinkSync(tempFile);
94
+ }
95
+ catch { }
96
+ }
97
+ }
98
+ }
52
99
  /**
53
100
  * Extract components from package.json
54
101
  */
@@ -76,13 +123,9 @@ class SBOMGenerator {
76
123
  }
77
124
  // Generate hashes if requested
78
125
  if (options.includeHashes) {
79
- const packagePath = (0, path_1.join)(projectPath, 'node_modules', name, 'package.json');
80
- if ((0, fs_1.existsSync)(packagePath)) {
81
- const content = (0, fs_1.readFileSync)(packagePath, 'utf-8');
82
- component.hashes = [
83
- { algorithm: 'SHA-256', content: this.hashContent(content, 'sha256') },
84
- { algorithm: 'SHA-512', content: this.hashContent(content, 'sha512') },
85
- ];
126
+ const hashes = await this.computePackageHashes(projectPath, name);
127
+ if (hashes.length > 0) {
128
+ component.hashes = hashes;
86
129
  }
87
130
  }
88
131
  components.push(component);
@@ -265,6 +308,124 @@ class SBOMGenerator {
265
308
  errors,
266
309
  };
267
310
  }
311
+ /**
312
+ * Compute hashes for a package
313
+ */
314
+ async computePackageHashes(projectPath, packageName) {
315
+ const hashes = [];
316
+ const packagePath = (0, path_1.join)(projectPath, 'node_modules', packageName, 'package.json');
317
+ if ((0, fs_1.existsSync)(packagePath)) {
318
+ const content = (0, fs_1.readFileSync)(packagePath, 'utf-8');
319
+ hashes.push({ algorithm: 'SHA-256', content: this.hashContent(content, 'sha256') });
320
+ }
321
+ return hashes;
322
+ }
323
+ /**
324
+ * Generate VEX document
325
+ */
326
+ async generateVEX(sbom, outputPath) {
327
+ const vex = {
328
+ '@context': 'https://openvex.dev/ns',
329
+ '@id': `${sbom.serialNumber}/vex`,
330
+ author: this.toolInfo.vendor,
331
+ timestamp: new Date().toISOString(),
332
+ version: '1',
333
+ statements: sbom.components.map(component => ({
334
+ vulnerability: 'PLACEHOLDER',
335
+ products: [component.purl || `${component.name}@${component.version}`],
336
+ status: 'not_affected',
337
+ justification: 'No known vulnerabilities at time of SBOM generation',
338
+ })),
339
+ };
340
+ (0, fs_1.writeFileSync)(outputPath, JSON.stringify(vex, null, 2), 'utf-8');
341
+ }
342
+ /**
343
+ * Sign SBOM using cosign
344
+ */
345
+ async signSBOM(sbomPath) {
346
+ if (!this.checkToolAvailable('cosign')) {
347
+ throw new Error('cosign is not installed. Install it with:\n' +
348
+ ' brew install cosign (macOS)\n' +
349
+ ' Or visit: https://docs.sigstore.dev/cosign/installation/');
350
+ }
351
+ try {
352
+ (0, child_process_1.execSync)(`cosign sign-blob --yes ${sbomPath} --output-signature ${sbomPath}.sig`, {
353
+ stdio: 'pipe',
354
+ encoding: 'utf-8',
355
+ });
356
+ }
357
+ catch (error) {
358
+ throw new Error(`Failed to sign SBOM: ${error.message}`);
359
+ }
360
+ }
361
+ /**
362
+ * Check if a tool is available
363
+ */
364
+ checkToolAvailable(tool) {
365
+ try {
366
+ (0, child_process_1.execSync)(`${tool} --version`, { stdio: 'pipe' });
367
+ return true;
368
+ }
369
+ catch {
370
+ return false;
371
+ }
372
+ }
373
+ /**
374
+ * Normalize container SBOM from syft output
375
+ */
376
+ normalizeContainerSBOM(rawSBOM, format, imageName) {
377
+ if (format === 'cyclonedx') {
378
+ return {
379
+ format: 'cyclonedx',
380
+ specVersion: rawSBOM.specVersion || '1.5',
381
+ serialNumber: rawSBOM.serialNumber || `urn:uuid:${this.generateUUID()}`,
382
+ version: rawSBOM.version || 1,
383
+ metadata: {
384
+ timestamp: rawSBOM.metadata?.timestamp || new Date().toISOString(),
385
+ tools: [this.toolInfo],
386
+ component: {
387
+ type: 'container',
388
+ name: imageName,
389
+ version: 'latest',
390
+ },
391
+ },
392
+ components: (rawSBOM.components || []).map((c) => ({
393
+ type: c.type || 'library',
394
+ name: c.name,
395
+ version: c.version,
396
+ purl: c.purl,
397
+ licenses: (c.licenses || []).map((l) => l.license?.id || l.expression || 'unknown'),
398
+ hashes: c.hashes?.map((h) => ({ algorithm: h.alg, content: h.content })),
399
+ })),
400
+ dependencies: rawSBOM.dependencies || [],
401
+ };
402
+ }
403
+ else {
404
+ return {
405
+ format: 'spdx',
406
+ specVersion: '2.3',
407
+ serialNumber: `urn:uuid:${this.generateUUID()}`,
408
+ version: 1,
409
+ metadata: {
410
+ timestamp: new Date().toISOString(),
411
+ tools: [this.toolInfo],
412
+ component: {
413
+ type: 'container',
414
+ name: imageName,
415
+ version: 'latest',
416
+ },
417
+ },
418
+ components: (rawSBOM.packages || []).map((p) => ({
419
+ type: 'library',
420
+ name: p.name,
421
+ version: p.versionInfo,
422
+ purl: p.externalRefs?.find((r) => r.referenceType === 'purl')?.referenceLocator,
423
+ licenses: p.licenseConcluded ? [p.licenseConcluded] : [],
424
+ })),
425
+ dependencies: [],
426
+ };
427
+ }
428
+ }
268
429
  }
269
430
  exports.SBOMGenerator = SBOMGenerator;
270
431
  // Export singleton
@@ -0,0 +1,38 @@
1
+ /**
2
+ * allowlist.ts
3
+ * Manage allowlisted secret detections via SHA256 fingerprints
4
+ */
5
+ export declare class Allowlist {
6
+ private readonly projectPath;
7
+ private fingerprints;
8
+ constructor(projectPath: string);
9
+ /**
10
+ * Load allowlist from .guardrail/secrets.allowlist
11
+ */
12
+ private load;
13
+ /**
14
+ * Check if a fingerprint is allowlisted
15
+ */
16
+ isAllowlisted(fingerprint: string): boolean;
17
+ /**
18
+ * Add a fingerprint to the allowlist
19
+ */
20
+ add(fingerprint: string): void;
21
+ /**
22
+ * Add multiple fingerprints from a baseline file
23
+ */
24
+ addFromBaseline(baselinePath: string): number;
25
+ /**
26
+ * Save allowlist to disk
27
+ */
28
+ save(): void;
29
+ /**
30
+ * Get the allowlist file path
31
+ */
32
+ private getAllowlistPath;
33
+ /**
34
+ * Get count of allowlisted items
35
+ */
36
+ size(): number;
37
+ }
38
+ //# sourceMappingURL=allowlist.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"allowlist.d.ts","sourceRoot":"","sources":["../../src/secrets/allowlist.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,qBAAa,SAAS;IAGR,OAAO,CAAC,QAAQ,CAAC,WAAW;IAFxC,OAAO,CAAC,YAAY,CAAqB;gBAEZ,WAAW,EAAE,MAAM;IAIhD;;OAEG;IACH,OAAO,CAAC,IAAI;IA4BZ;;OAEG;IACH,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IAI3C;;OAEG;IACH,GAAG,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAO9B;;OAEG;IACH,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IAyC7C;;OAEG;IACH,IAAI,IAAI,IAAI;IAmBZ;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAIxB;;OAEG;IACH,IAAI,IAAI,MAAM;CAGf"}
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+ /**
3
+ * allowlist.ts
4
+ * Manage allowlisted secret detections via SHA256 fingerprints
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.Allowlist = void 0;
8
+ const fs_1 = require("fs");
9
+ const path_1 = require("path");
10
+ class Allowlist {
11
+ projectPath;
12
+ fingerprints = new Set();
13
+ constructor(projectPath) {
14
+ this.projectPath = projectPath;
15
+ this.load();
16
+ }
17
+ /**
18
+ * Load allowlist from .guardrail/secrets.allowlist
19
+ */
20
+ load() {
21
+ const allowlistPath = this.getAllowlistPath();
22
+ if (!(0, fs_1.existsSync)(allowlistPath)) {
23
+ return;
24
+ }
25
+ try {
26
+ const content = (0, fs_1.readFileSync)(allowlistPath, 'utf-8');
27
+ const lines = content.split('\n');
28
+ for (const line of lines) {
29
+ const trimmed = line.trim();
30
+ // Skip empty lines and comments
31
+ if (!trimmed || trimmed.startsWith('#')) {
32
+ continue;
33
+ }
34
+ // Validate SHA256 format (64 hex chars)
35
+ if (/^[a-f0-9]{64}$/i.test(trimmed)) {
36
+ this.fingerprints.add(trimmed.toLowerCase());
37
+ }
38
+ }
39
+ }
40
+ catch (err) {
41
+ // Silently ignore read errors
42
+ }
43
+ }
44
+ /**
45
+ * Check if a fingerprint is allowlisted
46
+ */
47
+ isAllowlisted(fingerprint) {
48
+ return this.fingerprints.has(fingerprint.toLowerCase());
49
+ }
50
+ /**
51
+ * Add a fingerprint to the allowlist
52
+ */
53
+ add(fingerprint) {
54
+ if (!/^[a-f0-9]{64}$/i.test(fingerprint)) {
55
+ throw new Error(`Invalid fingerprint format: ${fingerprint}`);
56
+ }
57
+ this.fingerprints.add(fingerprint.toLowerCase());
58
+ }
59
+ /**
60
+ * Add multiple fingerprints from a baseline file
61
+ */
62
+ addFromBaseline(baselinePath) {
63
+ if (!(0, fs_1.existsSync)(baselinePath)) {
64
+ throw new Error(`Baseline file not found: ${baselinePath}`);
65
+ }
66
+ let added = 0;
67
+ try {
68
+ const content = (0, fs_1.readFileSync)(baselinePath, 'utf-8');
69
+ // Try to parse as JSON first (scan results format)
70
+ try {
71
+ const json = JSON.parse(content);
72
+ if (json.findings && Array.isArray(json.findings)) {
73
+ for (const finding of json.findings) {
74
+ if (finding.fingerprint) {
75
+ this.add(finding.fingerprint);
76
+ added++;
77
+ }
78
+ }
79
+ return added;
80
+ }
81
+ }
82
+ catch {
83
+ // Not JSON, try line-by-line
84
+ }
85
+ // Parse as line-delimited fingerprints
86
+ const lines = content.split('\n');
87
+ for (const line of lines) {
88
+ const trimmed = line.trim();
89
+ if (trimmed && !trimmed.startsWith('#') && /^[a-f0-9]{64}$/i.test(trimmed)) {
90
+ this.add(trimmed);
91
+ added++;
92
+ }
93
+ }
94
+ }
95
+ catch (err) {
96
+ throw new Error(`Failed to read baseline file: ${err.message}`);
97
+ }
98
+ return added;
99
+ }
100
+ /**
101
+ * Save allowlist to disk
102
+ */
103
+ save() {
104
+ const allowlistPath = this.getAllowlistPath();
105
+ const dir = (0, path_1.dirname)(allowlistPath);
106
+ if (!(0, fs_1.existsSync)(dir)) {
107
+ (0, fs_1.mkdirSync)(dir, { recursive: true });
108
+ }
109
+ const lines = [
110
+ '# Guardrail Secrets Allowlist',
111
+ '# SHA256 fingerprints of approved/suppressed detections',
112
+ '# One fingerprint per line',
113
+ '',
114
+ ...Array.from(this.fingerprints).sort(),
115
+ ];
116
+ (0, fs_1.writeFileSync)(allowlistPath, lines.join('\n'), 'utf-8');
117
+ }
118
+ /**
119
+ * Get the allowlist file path
120
+ */
121
+ getAllowlistPath() {
122
+ return (0, path_1.join)(this.projectPath, '.guardrail', 'secrets.allowlist');
123
+ }
124
+ /**
125
+ * Get count of allowlisted items
126
+ */
127
+ size() {
128
+ return this.fingerprints.size;
129
+ }
130
+ }
131
+ exports.Allowlist = Allowlist;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * config-loader.ts
3
+ * Load and validate custom secret patterns from .guardrail/secrets.yaml
4
+ */
5
+ import { SecretPattern, RiskLevel } from './patterns';
6
+ export interface CustomPatternConfig {
7
+ name: string;
8
+ type: string;
9
+ regex: string;
10
+ minEntropy?: number;
11
+ description?: string;
12
+ risk?: RiskLevel;
13
+ }
14
+ export interface SecretsConfigFile {
15
+ patterns?: CustomPatternConfig[];
16
+ }
17
+ export declare class ConfigValidationError extends Error {
18
+ readonly details?: string[] | undefined;
19
+ constructor(message: string, details?: string[] | undefined);
20
+ }
21
+ /**
22
+ * Load and validate custom patterns from .guardrail/secrets.yaml
23
+ */
24
+ export declare function loadCustomPatterns(projectPath: string): SecretPattern[];
25
+ //# sourceMappingURL=config-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../../src/secrets/config-loader.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAE,aAAa,EAAc,SAAS,EAAE,MAAM,YAAY,CAAC;AAElE,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,mBAAmB,EAAE,CAAC;CAClC;AAED,qBAAa,qBAAsB,SAAQ,KAAK;aACD,OAAO,CAAC,EAAE,MAAM,EAAE;gBAAnD,OAAO,EAAE,MAAM,EAAkB,OAAO,CAAC,EAAE,MAAM,EAAE,YAAA;CAIhE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,aAAa,EAAE,CAqGvE"}
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ /**
3
+ * config-loader.ts
4
+ * Load and validate custom secret patterns from .guardrail/secrets.yaml
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.ConfigValidationError = void 0;
8
+ exports.loadCustomPatterns = loadCustomPatterns;
9
+ const fs_1 = require("fs");
10
+ const path_1 = require("path");
11
+ const yaml_1 = require("yaml");
12
+ class ConfigValidationError extends Error {
13
+ details;
14
+ constructor(message, details) {
15
+ super(message);
16
+ this.details = details;
17
+ this.name = 'ConfigValidationError';
18
+ }
19
+ }
20
+ exports.ConfigValidationError = ConfigValidationError;
21
+ /**
22
+ * Load and validate custom patterns from .guardrail/secrets.yaml
23
+ */
24
+ function loadCustomPatterns(projectPath) {
25
+ const configPath = (0, path_1.join)(projectPath, '.guardrail', 'secrets.yaml');
26
+ if (!(0, fs_1.existsSync)(configPath)) {
27
+ return [];
28
+ }
29
+ let rawContent;
30
+ try {
31
+ rawContent = (0, fs_1.readFileSync)(configPath, 'utf-8');
32
+ }
33
+ catch (err) {
34
+ throw new ConfigValidationError(`Failed to read secrets config: ${configPath}`, [err.message]);
35
+ }
36
+ let parsed;
37
+ try {
38
+ parsed = (0, yaml_1.parse)(rawContent);
39
+ }
40
+ catch (err) {
41
+ throw new ConfigValidationError('Invalid YAML syntax in secrets.yaml', [err.message]);
42
+ }
43
+ if (!parsed || typeof parsed !== 'object') {
44
+ throw new ConfigValidationError('secrets.yaml must contain an object at root');
45
+ }
46
+ const config = parsed;
47
+ if (!config.patterns) {
48
+ return [];
49
+ }
50
+ if (!Array.isArray(config.patterns)) {
51
+ throw new ConfigValidationError('patterns must be an array');
52
+ }
53
+ const errors = [];
54
+ const customPatterns = [];
55
+ config.patterns.forEach((pattern, idx) => {
56
+ const prefix = `patterns[${idx}]`;
57
+ // Validate required fields
58
+ if (!pattern.name || typeof pattern.name !== 'string') {
59
+ errors.push(`${prefix}.name is required and must be a string`);
60
+ }
61
+ if (!pattern.type || typeof pattern.type !== 'string') {
62
+ errors.push(`${prefix}.type is required and must be a string`);
63
+ }
64
+ if (!pattern.regex || typeof pattern.regex !== 'string') {
65
+ errors.push(`${prefix}.regex is required and must be a string`);
66
+ }
67
+ // Validate optional fields
68
+ if (pattern.minEntropy !== undefined) {
69
+ if (typeof pattern.minEntropy !== 'number' || pattern.minEntropy < 0 || pattern.minEntropy > 8) {
70
+ errors.push(`${prefix}.minEntropy must be a number between 0 and 8`);
71
+ }
72
+ }
73
+ if (pattern.risk !== undefined) {
74
+ if (!['high', 'medium', 'low'].includes(pattern.risk)) {
75
+ errors.push(`${prefix}.risk must be one of: high, medium, low`);
76
+ }
77
+ }
78
+ // Try to compile regex
79
+ let regex;
80
+ try {
81
+ regex = new RegExp(pattern.regex);
82
+ }
83
+ catch (err) {
84
+ errors.push(`${prefix}.regex is invalid: ${err.message}`);
85
+ return;
86
+ }
87
+ if (errors.length === 0) {
88
+ customPatterns.push({
89
+ type: pattern.type,
90
+ name: pattern.name,
91
+ pattern: regex,
92
+ minEntropy: pattern.minEntropy,
93
+ risk: pattern.risk || 'medium',
94
+ description: pattern.description || pattern.name,
95
+ examples: [],
96
+ });
97
+ }
98
+ });
99
+ if (errors.length > 0) {
100
+ throw new ConfigValidationError('Invalid custom patterns in secrets.yaml', errors);
101
+ }
102
+ return customPatterns;
103
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * contextual-risk.ts
3
+ * Adjust risk levels based on file context (examples, templates, production code)
4
+ */
5
+ import { RiskLevel } from './patterns';
6
+ export interface RiskContext {
7
+ filePath: string;
8
+ entropy: number;
9
+ originalRisk: RiskLevel;
10
+ }
11
+ /**
12
+ * Adjust risk based on file context
13
+ */
14
+ export declare function adjustRiskByContext(context: RiskContext): RiskLevel;
15
+ /**
16
+ * Get context description for reporting
17
+ */
18
+ export declare function getContextDescription(filePath: string): string;
19
+ //# sourceMappingURL=contextual-risk.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contextual-risk.d.ts","sourceRoot":"","sources":["../../src/secrets/contextual-risk.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,SAAS,CAAC;CACzB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,WAAW,GAAG,SAAS,CAyBnE;AA8CD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAY9D"}