vibe-guard 1.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.
- package/LICENSE +21 -0
- package/README.md +200 -0
- package/dist/bin/vibe-guard.d.ts +3 -0
- package/dist/bin/vibe-guard.d.ts.map +1 -0
- package/dist/bin/vibe-guard.js +119 -0
- package/dist/bin/vibe-guard.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +128 -0
- package/dist/index.js.map +1 -0
- package/dist/reporter.d.ts +13 -0
- package/dist/reporter.d.ts.map +1 -0
- package/dist/reporter.js +116 -0
- package/dist/reporter.js.map +1 -0
- package/dist/rules/directory-traversal.d.ts +14 -0
- package/dist/rules/directory-traversal.d.ts.map +1 -0
- package/dist/rules/directory-traversal.js +142 -0
- package/dist/rules/directory-traversal.js.map +1 -0
- package/dist/rules/exposed-secrets.d.ts +13 -0
- package/dist/rules/exposed-secrets.d.ts.map +1 -0
- package/dist/rules/exposed-secrets.js +137 -0
- package/dist/rules/exposed-secrets.js.map +1 -0
- package/dist/rules/hardcoded-sensitive-data.d.ts +13 -0
- package/dist/rules/hardcoded-sensitive-data.d.ts.map +1 -0
- package/dist/rules/hardcoded-sensitive-data.js +104 -0
- package/dist/rules/hardcoded-sensitive-data.js.map +1 -0
- package/dist/rules/index.d.ts +15 -0
- package/dist/rules/index.d.ts.map +1 -0
- package/dist/rules/index.js +54 -0
- package/dist/rules/index.js.map +1 -0
- package/dist/rules/insecure-dependencies.d.ts +16 -0
- package/dist/rules/insecure-dependencies.d.ts.map +1 -0
- package/dist/rules/insecure-dependencies.js +152 -0
- package/dist/rules/insecure-dependencies.js.map +1 -0
- package/dist/rules/insecure-http.d.ts +13 -0
- package/dist/rules/insecure-http.d.ts.map +1 -0
- package/dist/rules/insecure-http.js +91 -0
- package/dist/rules/insecure-http.js.map +1 -0
- package/dist/rules/missing-authentication.d.ts +14 -0
- package/dist/rules/missing-authentication.d.ts.map +1 -0
- package/dist/rules/missing-authentication.js +98 -0
- package/dist/rules/missing-authentication.js.map +1 -0
- package/dist/rules/missing-security-headers.d.ts +16 -0
- package/dist/rules/missing-security-headers.d.ts.map +1 -0
- package/dist/rules/missing-security-headers.js +158 -0
- package/dist/rules/missing-security-headers.js.map +1 -0
- package/dist/rules/open-cors.d.ts +11 -0
- package/dist/rules/open-cors.d.ts.map +1 -0
- package/dist/rules/open-cors.js +61 -0
- package/dist/rules/open-cors.js.map +1 -0
- package/dist/rules/sql-injection.d.ts +12 -0
- package/dist/rules/sql-injection.d.ts.map +1 -0
- package/dist/rules/sql-injection.js +95 -0
- package/dist/rules/sql-injection.js.map +1 -0
- package/dist/rules/unvalidated-input.d.ts +13 -0
- package/dist/rules/unvalidated-input.d.ts.map +1 -0
- package/dist/rules/unvalidated-input.js +128 -0
- package/dist/rules/unvalidated-input.js.map +1 -0
- package/dist/scanner.d.ts +15 -0
- package/dist/scanner.d.ts.map +1 -0
- package/dist/scanner.js +240 -0
- package/dist/scanner.js.map +1 -0
- package/dist/types/index.d.ts +66 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +38 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +72 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { BaseRule, FileContent, SecurityIssue } from '../types';
|
|
2
|
+
export declare class DirectoryTraversalRule extends BaseRule {
|
|
3
|
+
readonly name = "directory-traversal";
|
|
4
|
+
readonly description = "Detects potential directory traversal vulnerabilities";
|
|
5
|
+
readonly severity: "high";
|
|
6
|
+
private readonly traversalPatterns;
|
|
7
|
+
private readonly safePatterns;
|
|
8
|
+
check(fileContent: FileContent): SecurityIssue[];
|
|
9
|
+
private hasSafePathHandling;
|
|
10
|
+
private isCommentOrTest;
|
|
11
|
+
private isImportStatement;
|
|
12
|
+
private isTestContext;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=directory-traversal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"directory-traversal.d.ts","sourceRoot":"","sources":["../../src/rules/directory-traversal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEhE,qBAAa,sBAAuB,SAAQ,QAAQ;IAClD,QAAQ,CAAC,IAAI,yBAAyB;IACtC,QAAQ,CAAC,WAAW,2DAA2D;IAC/E,QAAQ,CAAC,QAAQ,EAAG,MAAM,CAAU;IAEpC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CA+BhC;IAEF,OAAO,CAAC,QAAQ,CAAC,YAAY,CAe3B;IAEF,KAAK,CAAC,WAAW,EAAE,WAAW,GAAG,aAAa,EAAE;IAyChD,OAAO,CAAC,mBAAmB;IAY3B,OAAO,CAAC,eAAe;IA0BvB,OAAO,CAAC,iBAAiB;IAczB,OAAO,CAAC,aAAa;CAuBtB"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DirectoryTraversalRule = void 0;
|
|
4
|
+
const types_1 = require("../types");
|
|
5
|
+
class DirectoryTraversalRule extends types_1.BaseRule {
|
|
6
|
+
constructor() {
|
|
7
|
+
super(...arguments);
|
|
8
|
+
this.name = 'directory-traversal';
|
|
9
|
+
this.description = 'Detects potential directory traversal vulnerabilities';
|
|
10
|
+
this.severity = 'high';
|
|
11
|
+
this.traversalPatterns = [
|
|
12
|
+
// Direct path traversal patterns
|
|
13
|
+
{ pattern: /(?:readFile|writeFile|createReadStream|createWriteStream|unlink|rmdir|mkdir|stat|access)\s*\(\s*(?:req\.|request\.|input\.|params\.|query\.)[^)]*(?!\s*(?:path\.resolve|path\.join|path\.normalize))/gi, type: 'File operation with user input' },
|
|
14
|
+
// Express static file serving
|
|
15
|
+
{ pattern: /express\.static\s*\(\s*(?:req\.|request\.|input\.|params\.|query\.)/gi, type: 'Express static serving with user input' },
|
|
16
|
+
{ pattern: /res\.sendFile\s*\(\s*(?:req\.|request\.|input\.|params\.|query\.)/gi, type: 'Express sendFile with user input' },
|
|
17
|
+
// Path concatenation
|
|
18
|
+
{ pattern: /['"`][^'"`]*\/['"`]\s*\+\s*(?:req\.|request\.|input\.|params\.|query\.)/gi, type: 'Path concatenation with user input' },
|
|
19
|
+
{ pattern: /\$\{[^}]*(?:req\.|request\.|input\.|params\.|query\.)[^}]*\}/g, type: 'Template literal path with user input' },
|
|
20
|
+
// Dangerous path patterns (but not in imports/requires)
|
|
21
|
+
{ pattern: /(?<!(?:import|require|from)\s+['"`][^'"`]*)\.\.\//g, type: 'Hardcoded directory traversal sequence' },
|
|
22
|
+
// Framework-specific patterns
|
|
23
|
+
{ pattern: /File\s*\(\s*(?:req\.|request\.|input\.|params\.|query\.)/gi, type: 'File constructor with user input' },
|
|
24
|
+
{ pattern: /FileInputStream\s*\(\s*(?:request\.getParameter|request\.getAttribute)/gi, type: 'Java FileInputStream with user input' },
|
|
25
|
+
{ pattern: /fopen\s*\(\s*(?:\$_GET|\$_POST|\$_REQUEST)/gi, type: 'PHP fopen with user input' },
|
|
26
|
+
{ pattern: /file_get_contents\s*\(\s*(?:\$_GET|\$_POST|\$_REQUEST)/gi, type: 'PHP file_get_contents with user input' },
|
|
27
|
+
// Python patterns
|
|
28
|
+
{ pattern: /open\s*\(\s*(?:request\.|flask\.request\.)/gi, type: 'Python file open with user input' },
|
|
29
|
+
{ pattern: /os\.path\.join\s*\([^)]*(?:request\.|flask\.request\.)/gi, type: 'Python path join with user input' },
|
|
30
|
+
// Node.js path operations
|
|
31
|
+
{ pattern: /path\.join\s*\([^)]*(?:req\.|request\.|input\.|params\.|query\.)(?![^)]*(?:path\.resolve|path\.normalize))/gi, type: 'Path join without normalization' },
|
|
32
|
+
// Include/require with user input
|
|
33
|
+
{ pattern: /(?:require|import)\s*\(\s*(?:req\.|request\.|input\.|params\.|query\.)/gi, type: 'Module import with user input' },
|
|
34
|
+
{ pattern: /(?:include|require|include_once|require_once)\s*\(\s*(?:\$_GET|\$_POST|\$_REQUEST)/gi, type: 'PHP include with user input' }
|
|
35
|
+
];
|
|
36
|
+
this.safePatterns = [
|
|
37
|
+
/path\.resolve/i,
|
|
38
|
+
/path\.normalize/i,
|
|
39
|
+
/path\.basename/i,
|
|
40
|
+
/sanitize/i,
|
|
41
|
+
/validate/i,
|
|
42
|
+
/whitelist/i,
|
|
43
|
+
/allowedPaths/i,
|
|
44
|
+
/isValidPath/i,
|
|
45
|
+
/checkPath/i,
|
|
46
|
+
/\.replace\s*\(\s*\/\.\.\//gi,
|
|
47
|
+
/\.replace\s*\(\s*\/\.\.\\/gi,
|
|
48
|
+
/filter/i,
|
|
49
|
+
/startsWith/i,
|
|
50
|
+
/includes.*allowed/i
|
|
51
|
+
];
|
|
52
|
+
}
|
|
53
|
+
check(fileContent) {
|
|
54
|
+
const issues = [];
|
|
55
|
+
for (const { pattern, type } of this.traversalPatterns) {
|
|
56
|
+
const matches = this.findMatches(fileContent.content, pattern);
|
|
57
|
+
for (const { line, column, lineContent } of matches) {
|
|
58
|
+
// Skip if safe path handling is present
|
|
59
|
+
if (this.hasSafePathHandling(fileContent.content, line)) {
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
// Skip if it's in a comment or test file
|
|
63
|
+
if (this.isCommentOrTest(lineContent, fileContent.path)) {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
// Skip if it's an import/require statement
|
|
67
|
+
if (this.isImportStatement(lineContent)) {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
// Skip if it's a hardcoded traversal in a test context
|
|
71
|
+
if (type === 'Hardcoded directory traversal sequence' && this.isTestContext(fileContent.content, line)) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
issues.push(this.createIssue(fileContent.path, line, column, lineContent, `Potential directory traversal vulnerability: ${type}`, `Validate and sanitize file paths. Use path.resolve(), path.normalize(), or whitelist allowed directories. Never trust user input for file paths.`));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return issues;
|
|
78
|
+
}
|
|
79
|
+
hasSafePathHandling(content, lineNumber) {
|
|
80
|
+
const lines = content.split('\n');
|
|
81
|
+
const contextRange = 5; // Check 5 lines before and after
|
|
82
|
+
const startLine = Math.max(0, lineNumber - contextRange - 1);
|
|
83
|
+
const endLine = Math.min(lines.length, lineNumber + contextRange);
|
|
84
|
+
const contextLines = lines.slice(startLine, endLine).join('\n');
|
|
85
|
+
return this.safePatterns.some(pattern => pattern.test(contextLines));
|
|
86
|
+
}
|
|
87
|
+
isCommentOrTest(line, filePath) {
|
|
88
|
+
// Check if line is a comment
|
|
89
|
+
const commentPatterns = [
|
|
90
|
+
/^\s*\/\//, // JavaScript comment
|
|
91
|
+
/^\s*#/, // Python/Shell comment
|
|
92
|
+
/^\s*\*/ // Multi-line comment
|
|
93
|
+
];
|
|
94
|
+
if (commentPatterns.some(pattern => pattern.test(line))) {
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
// Check if it's a test file
|
|
98
|
+
const testPatterns = [
|
|
99
|
+
/test/i,
|
|
100
|
+
/spec/i,
|
|
101
|
+
/\.test\./i,
|
|
102
|
+
/\.spec\./i,
|
|
103
|
+
/__tests__/i,
|
|
104
|
+
/tests\//i,
|
|
105
|
+
/spec\//i
|
|
106
|
+
];
|
|
107
|
+
return testPatterns.some(pattern => pattern.test(filePath));
|
|
108
|
+
}
|
|
109
|
+
isImportStatement(line) {
|
|
110
|
+
const importPatterns = [
|
|
111
|
+
/^\s*import\s+.*from\s+['"`]/,
|
|
112
|
+
/^\s*import\s+['"`]/,
|
|
113
|
+
/^\s*const\s+.*=\s+require\s*\(\s*['"`]/,
|
|
114
|
+
/^\s*let\s+.*=\s+require\s*\(\s*['"`]/,
|
|
115
|
+
/^\s*var\s+.*=\s+require\s*\(\s*['"`]/,
|
|
116
|
+
/^\s*export\s+.*from\s+['"`]/,
|
|
117
|
+
/^\s*from\s+['"`]/
|
|
118
|
+
];
|
|
119
|
+
return importPatterns.some(pattern => pattern.test(line));
|
|
120
|
+
}
|
|
121
|
+
isTestContext(content, lineNumber) {
|
|
122
|
+
const lines = content.split('\n');
|
|
123
|
+
const contextRange = 3;
|
|
124
|
+
const startLine = Math.max(0, lineNumber - contextRange - 1);
|
|
125
|
+
const endLine = Math.min(lines.length, lineNumber + contextRange);
|
|
126
|
+
const contextLines = lines.slice(startLine, endLine).join('\n');
|
|
127
|
+
const testPatterns = [
|
|
128
|
+
/test/i,
|
|
129
|
+
/spec/i,
|
|
130
|
+
/describe/i,
|
|
131
|
+
/it\(/i,
|
|
132
|
+
/expect/i,
|
|
133
|
+
/assert/i,
|
|
134
|
+
/mock/i,
|
|
135
|
+
/example/i,
|
|
136
|
+
/demo/i
|
|
137
|
+
];
|
|
138
|
+
return testPatterns.some(pattern => pattern.test(contextLines));
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
exports.DirectoryTraversalRule = DirectoryTraversalRule;
|
|
142
|
+
//# sourceMappingURL=directory-traversal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"directory-traversal.js","sourceRoot":"","sources":["../../src/rules/directory-traversal.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BaseRule, FileContent, SecurityIssue } from '../types';
|
|
2
|
+
export declare class ExposedSecretsRule extends BaseRule {
|
|
3
|
+
readonly name = "exposed-secrets";
|
|
4
|
+
readonly description = "Detects exposed API keys, tokens, and credentials";
|
|
5
|
+
readonly severity: "critical";
|
|
6
|
+
private readonly secretPatterns;
|
|
7
|
+
private readonly falsePositivePatterns;
|
|
8
|
+
check(fileContent: FileContent): SecurityIssue[];
|
|
9
|
+
private isFalsePositive;
|
|
10
|
+
private isValidBase64Secret;
|
|
11
|
+
private maskSecret;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=exposed-secrets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exposed-secrets.d.ts","sourceRoot":"","sources":["../../src/rules/exposed-secrets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEhE,qBAAa,kBAAmB,SAAQ,QAAQ;IAC9C,QAAQ,CAAC,IAAI,qBAAqB;IAClC,QAAQ,CAAC,WAAW,uDAAuD;IAC3E,QAAQ,CAAC,QAAQ,EAAG,UAAU,CAAU;IAExC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAiC7B;IAEF,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAoBpC;IAEF,KAAK,CAAC,WAAW,EAAE,WAAW,GAAG,aAAa,EAAE;IAiChD,OAAO,CAAC,eAAe;IAyBvB,OAAO,CAAC,mBAAmB;IAiC3B,OAAO,CAAC,UAAU;CAWnB"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ExposedSecretsRule = void 0;
|
|
4
|
+
const types_1 = require("../types");
|
|
5
|
+
class ExposedSecretsRule extends types_1.BaseRule {
|
|
6
|
+
constructor() {
|
|
7
|
+
super(...arguments);
|
|
8
|
+
this.name = 'exposed-secrets';
|
|
9
|
+
this.description = 'Detects exposed API keys, tokens, and credentials';
|
|
10
|
+
this.severity = 'critical';
|
|
11
|
+
this.secretPatterns = [
|
|
12
|
+
// API Keys
|
|
13
|
+
{ pattern: /(?:api[_-]?key|apikey)\s*[:=]\s*['"`]([a-zA-Z0-9_\-]{20,})/gi, type: 'API Key' },
|
|
14
|
+
{ pattern: /(?:secret[_-]?key|secretkey)\s*[:=]\s*['"`]([a-zA-Z0-9_\-]{20,})/gi, type: 'Secret Key' },
|
|
15
|
+
{ pattern: /(?:access[_-]?token|accesstoken)\s*[:=]\s*['"`]([a-zA-Z0-9_\-]{20,})/gi, type: 'Access Token' },
|
|
16
|
+
// AWS
|
|
17
|
+
{ pattern: /AKIA[0-9A-Z]{16}/g, type: 'AWS Access Key' },
|
|
18
|
+
{ pattern: /(?:aws[_-]?secret|AWS_SECRET)\s*[:=]\s*['"`]([a-zA-Z0-9/+=]{40})/gi, type: 'AWS Secret' },
|
|
19
|
+
// GitHub
|
|
20
|
+
{ pattern: /ghp_[a-zA-Z0-9]{36}/g, type: 'GitHub Personal Access Token' },
|
|
21
|
+
{ pattern: /ghs_[a-zA-Z0-9]{36}/g, type: 'GitHub App Token' },
|
|
22
|
+
{ pattern: /ghr_[a-zA-Z0-9]{36}/g, type: 'GitHub Refresh Token' },
|
|
23
|
+
// Google
|
|
24
|
+
{ pattern: /AIza[0-9A-Za-z_\-]{35}/g, type: 'Google API Key' },
|
|
25
|
+
// Slack
|
|
26
|
+
{ pattern: /xox[baprs]-[0-9a-zA-Z\-]{10,}/g, type: 'Slack Token' },
|
|
27
|
+
// JWT
|
|
28
|
+
{ pattern: /eyJ[a-zA-Z0-9_\-]*\.eyJ[a-zA-Z0-9_\-]*\.[a-zA-Z0-9_\-]*/g, type: 'JWT Token' },
|
|
29
|
+
// Database URLs
|
|
30
|
+
{ pattern: /(?:mongodb|mysql|postgres|redis):\/\/[^\s'"]+/gi, type: 'Database URL' },
|
|
31
|
+
// Base64 encoded secrets (more specific pattern)
|
|
32
|
+
{ pattern: /(?:secret|token|key|auth|password)\s*[:=]\s*['"`]([A-Za-z0-9+/]{40,}={0,2})['"`]/gi, type: 'Base64 Encoded Secret' },
|
|
33
|
+
// Generic patterns (more specific to avoid variable names)
|
|
34
|
+
{ pattern: /(?:password|passwd|pwd)\s*[:=]\s*['"`]([^'"`\s]{8,})/gi, type: 'Password' },
|
|
35
|
+
{ pattern: /(?:^|[^a-zA-Z0-9_])(?:token|auth)\s*[:=]\s*['"`]([a-zA-Z0-9_\-]{20,})/gi, type: 'Auth Token' }
|
|
36
|
+
];
|
|
37
|
+
this.falsePositivePatterns = [
|
|
38
|
+
/example/i,
|
|
39
|
+
/demo/i,
|
|
40
|
+
/placeholder/i,
|
|
41
|
+
/your[_-]?key/i,
|
|
42
|
+
/your[_-]?token/i,
|
|
43
|
+
/your[_-]?secret/i,
|
|
44
|
+
/\$\{.*\}/, // Environment variables
|
|
45
|
+
/%.*%/, // Windows environment variables
|
|
46
|
+
/\{\{.*\}\}/, // Template variables
|
|
47
|
+
/^xxx+$/i, // Only xxx repeated
|
|
48
|
+
/^aaa+$/i, // Only aaa repeated
|
|
49
|
+
/^000+$/, // Only zeros repeated
|
|
50
|
+
/^111+$/, // Only ones repeated
|
|
51
|
+
/^123+$/, // Only 123 repeated
|
|
52
|
+
/test/i, // Test values
|
|
53
|
+
/mock/i, // Mock values
|
|
54
|
+
/sample/i, // Sample values
|
|
55
|
+
/dummy/i, // Dummy values
|
|
56
|
+
/^(.)\1{7,}$/ // Any character repeated 8+ times
|
|
57
|
+
];
|
|
58
|
+
}
|
|
59
|
+
check(fileContent) {
|
|
60
|
+
const issues = [];
|
|
61
|
+
for (const { pattern, type } of this.secretPatterns) {
|
|
62
|
+
const matches = this.findMatches(fileContent.content, pattern);
|
|
63
|
+
for (const { match, line, column, lineContent } of matches) {
|
|
64
|
+
const matchedText = match[0];
|
|
65
|
+
// Skip false positives
|
|
66
|
+
if (this.isFalsePositive(matchedText)) {
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
// Additional validation for Base64 secrets
|
|
70
|
+
if (type === 'Base64 Encoded Secret' && !this.isValidBase64Secret(matchedText)) {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
issues.push(this.createIssue(fileContent.path, line, column, lineContent, `Exposed ${type} detected: ${this.maskSecret(matchedText)}`, `Remove hardcoded secrets and use environment variables or secure secret management instead. Consider using tools like dotenv for local development.`));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return issues;
|
|
77
|
+
}
|
|
78
|
+
isFalsePositive(text) {
|
|
79
|
+
// Check against false positive patterns first
|
|
80
|
+
if (this.falsePositivePatterns.some(pattern => pattern.test(text))) {
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
// Extract the actual secret value from the match
|
|
84
|
+
const secretMatch = text.match(/['"`]([^'"`]+)['"`]/);
|
|
85
|
+
if (secretMatch && secretMatch[1]) {
|
|
86
|
+
const secretValue = secretMatch[1];
|
|
87
|
+
// Check if it's all the same character repeated
|
|
88
|
+
if (/^(.)\1{7,}$/.test(secretValue)) {
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
// Check if it's a simple pattern like 123456789...
|
|
92
|
+
if (/^(012|123|234|345|456|567|678|789|890)+$/.test(secretValue)) {
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
isValidBase64Secret(text) {
|
|
99
|
+
try {
|
|
100
|
+
// Extract the base64 part from the match
|
|
101
|
+
const base64Match = text.match(/([A-Za-z0-9+/]{32,}={0,2})/);
|
|
102
|
+
if (!base64Match || !base64Match[1])
|
|
103
|
+
return false;
|
|
104
|
+
const base64String = base64Match[1];
|
|
105
|
+
// Check if it's valid base64
|
|
106
|
+
const decoded = Buffer.from(base64String, 'base64').toString('utf-8');
|
|
107
|
+
// Skip if it decodes to common false positives
|
|
108
|
+
if (/^(test|example|demo|placeholder|sample|dummy)/i.test(decoded)) {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
// Skip if it's too short when decoded (likely not a real secret)
|
|
112
|
+
if (decoded.length < 8) {
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
// Skip if it contains only repeated characters
|
|
116
|
+
if (/^(.)\1+$/.test(decoded)) {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
// If we can't decode it, it's probably not valid base64
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
maskSecret(secret) {
|
|
127
|
+
if (secret.length <= 8) {
|
|
128
|
+
return '*'.repeat(secret.length);
|
|
129
|
+
}
|
|
130
|
+
const start = secret.substring(0, 4);
|
|
131
|
+
const end = secret.substring(secret.length - 4);
|
|
132
|
+
const middle = '*'.repeat(Math.min(secret.length - 8, 10));
|
|
133
|
+
return `${start}${middle}${end}`;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
exports.ExposedSecretsRule = ExposedSecretsRule;
|
|
137
|
+
//# sourceMappingURL=exposed-secrets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exposed-secrets.js","sourceRoot":"","sources":["../../src/rules/exposed-secrets.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BaseRule, FileContent, SecurityIssue } from '../types';
|
|
2
|
+
export declare class HardcodedSensitiveDataRule extends BaseRule {
|
|
3
|
+
readonly name = "hardcoded-sensitive-data";
|
|
4
|
+
readonly description = "Detects hardcoded sensitive information in configuration files";
|
|
5
|
+
readonly severity: "critical";
|
|
6
|
+
private readonly sensitivePatterns;
|
|
7
|
+
private readonly falsePositivePatterns;
|
|
8
|
+
check(fileContent: FileContent): SecurityIssue[];
|
|
9
|
+
private isSensitiveFile;
|
|
10
|
+
private isFalsePositive;
|
|
11
|
+
private maskSensitiveData;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=hardcoded-sensitive-data.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hardcoded-sensitive-data.d.ts","sourceRoot":"","sources":["../../src/rules/hardcoded-sensitive-data.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEhE,qBAAa,0BAA2B,SAAQ,QAAQ;IACtD,QAAQ,CAAC,IAAI,8BAA8B;IAC3C,QAAQ,CAAC,WAAW,oEAAoE;IACxF,QAAQ,CAAC,QAAQ,EAAG,UAAU,CAAU;IAExC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAwBhC;IAEF,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAgBpC;IAEF,KAAK,CAAC,WAAW,EAAE,WAAW,GAAG,aAAa,EAAE;IAiChD,OAAO,CAAC,eAAe;IAwBvB,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,iBAAiB;CAW1B"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HardcodedSensitiveDataRule = void 0;
|
|
4
|
+
const types_1 = require("../types");
|
|
5
|
+
class HardcodedSensitiveDataRule extends types_1.BaseRule {
|
|
6
|
+
constructor() {
|
|
7
|
+
super(...arguments);
|
|
8
|
+
this.name = 'hardcoded-sensitive-data';
|
|
9
|
+
this.description = 'Detects hardcoded sensitive information in configuration files';
|
|
10
|
+
this.severity = 'critical';
|
|
11
|
+
this.sensitivePatterns = [
|
|
12
|
+
// Database connections
|
|
13
|
+
{ pattern: /(?:database_url|db_url|connection_string)\s*[:=]\s*['"`]([^'"`\s]+)['"`]/gi, type: 'Database Connection' },
|
|
14
|
+
{ pattern: /(?:mongodb|mysql|postgres|redis):\/\/[^'"`\s]+/gi, type: 'Database URL' },
|
|
15
|
+
// Encryption keys
|
|
16
|
+
{ pattern: /(?:encryption_key|secret_key|private_key)\s*[:=]\s*['"`]([a-zA-Z0-9+/=]{20,})['"`]/gi, type: 'Encryption Key' },
|
|
17
|
+
{ pattern: /-----BEGIN\s+(?:RSA\s+)?PRIVATE\s+KEY-----/gi, type: 'Private Key' },
|
|
18
|
+
// Configuration secrets
|
|
19
|
+
{ pattern: /(?:app_secret|session_secret|jwt_secret)\s*[:=]\s*['"`]([^'"`\s]{16,})['"`]/gi, type: 'Application Secret' },
|
|
20
|
+
{ pattern: /(?:salt|hash_salt)\s*[:=]\s*['"`]([^'"`\s]{8,})['"`]/gi, type: 'Cryptographic Salt' },
|
|
21
|
+
// Third-party service keys
|
|
22
|
+
{ pattern: /(?:stripe_secret|stripe_key)\s*[:=]\s*['"`](sk_[a-zA-Z0-9_]+)['"`]/gi, type: 'Stripe Secret Key' },
|
|
23
|
+
{ pattern: /(?:sendgrid_api_key)\s*[:=]\s*['"`](SG\.[a-zA-Z0-9_\-\.]+)['"`]/gi, type: 'SendGrid API Key' },
|
|
24
|
+
{ pattern: /(?:twilio_auth_token)\s*[:=]\s*['"`]([a-zA-Z0-9]{32})['"`]/gi, type: 'Twilio Auth Token' },
|
|
25
|
+
// Generic sensitive patterns
|
|
26
|
+
{ pattern: /(?:admin_password|root_password|db_password)\s*[:=]\s*['"`]([^'"`\s]{6,})['"`]/gi, type: 'Admin Password' },
|
|
27
|
+
{ pattern: /(?:webhook_secret|signing_secret)\s*[:=]\s*['"`]([^'"`\s]{16,})['"`]/gi, type: 'Webhook Secret' },
|
|
28
|
+
// Configuration file patterns
|
|
29
|
+
{ pattern: /password\s*[:=]\s*['"`](?!.*(?:password|secret|key|token))[^'"`\s]{8,}['"`]/gi, type: 'Configuration Password' }
|
|
30
|
+
];
|
|
31
|
+
this.falsePositivePatterns = [
|
|
32
|
+
/example/i,
|
|
33
|
+
/sample/i,
|
|
34
|
+
/demo/i,
|
|
35
|
+
/placeholder/i,
|
|
36
|
+
/your[_-]?(?:key|secret|password)/i,
|
|
37
|
+
/\$\{.*\}/, // Environment variables
|
|
38
|
+
/%.*%/, // Windows environment variables
|
|
39
|
+
/\{\{.*\}\}/, // Template variables
|
|
40
|
+
/^[x]+$/i, // Only x's
|
|
41
|
+
/^[*]+$/, // Only asterisks
|
|
42
|
+
/^[0]+$/, // Only zeros
|
|
43
|
+
/^[1]+$/, // Only ones
|
|
44
|
+
/test/i,
|
|
45
|
+
/mock/i,
|
|
46
|
+
/fake/i
|
|
47
|
+
];
|
|
48
|
+
}
|
|
49
|
+
check(fileContent) {
|
|
50
|
+
const issues = [];
|
|
51
|
+
// Focus on configuration files and certain code files
|
|
52
|
+
if (!this.isSensitiveFile(fileContent.path)) {
|
|
53
|
+
return issues;
|
|
54
|
+
}
|
|
55
|
+
for (const { pattern, type } of this.sensitivePatterns) {
|
|
56
|
+
const matches = this.findMatches(fileContent.content, pattern);
|
|
57
|
+
for (const { match, line, column, lineContent } of matches) {
|
|
58
|
+
const matchedText = match[0];
|
|
59
|
+
// Skip false positives
|
|
60
|
+
if (this.isFalsePositive(matchedText)) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
issues.push(this.createIssue(fileContent.path, line, column, lineContent, `Hardcoded ${type} found: ${this.maskSensitiveData(matchedText)}`, `Move sensitive data to environment variables or secure configuration management. Use process.env.VARIABLE_NAME or a secrets management service.`));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return issues;
|
|
67
|
+
}
|
|
68
|
+
isSensitiveFile(filePath) {
|
|
69
|
+
const sensitiveFiles = [
|
|
70
|
+
/\.env/i,
|
|
71
|
+
/\.config/i,
|
|
72
|
+
/\.conf/i,
|
|
73
|
+
/\.ini/i,
|
|
74
|
+
/\.properties/i,
|
|
75
|
+
/\.yaml/i,
|
|
76
|
+
/\.yml/i,
|
|
77
|
+
/\.json/i,
|
|
78
|
+
/\.toml/i,
|
|
79
|
+
/config\./i,
|
|
80
|
+
/settings\./i,
|
|
81
|
+
/constants\./i,
|
|
82
|
+
/\.js$/i,
|
|
83
|
+
/\.ts$/i,
|
|
84
|
+
/\.py$/i,
|
|
85
|
+
/\.php$/i,
|
|
86
|
+
/\.rb$/i
|
|
87
|
+
];
|
|
88
|
+
return sensitiveFiles.some(pattern => pattern.test(filePath));
|
|
89
|
+
}
|
|
90
|
+
isFalsePositive(text) {
|
|
91
|
+
return this.falsePositivePatterns.some(pattern => pattern.test(text));
|
|
92
|
+
}
|
|
93
|
+
maskSensitiveData(data) {
|
|
94
|
+
if (data.length <= 8) {
|
|
95
|
+
return '*'.repeat(data.length);
|
|
96
|
+
}
|
|
97
|
+
const start = data.substring(0, 4);
|
|
98
|
+
const end = data.substring(data.length - 4);
|
|
99
|
+
const middle = '*'.repeat(Math.min(data.length - 8, 10));
|
|
100
|
+
return `${start}${middle}${end}`;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
exports.HardcodedSensitiveDataRule = HardcodedSensitiveDataRule;
|
|
104
|
+
//# sourceMappingURL=hardcoded-sensitive-data.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hardcoded-sensitive-data.js","sourceRoot":"","sources":["../../src/rules/hardcoded-sensitive-data.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { BaseRule } from '../types';
|
|
2
|
+
import { ExposedSecretsRule } from './exposed-secrets';
|
|
3
|
+
import { MissingAuthenticationRule } from './missing-authentication';
|
|
4
|
+
import { OpenCorsRule } from './open-cors';
|
|
5
|
+
import { HardcodedSensitiveDataRule } from './hardcoded-sensitive-data';
|
|
6
|
+
import { InsecureHttpRule } from './insecure-http';
|
|
7
|
+
import { SqlInjectionRule } from './sql-injection';
|
|
8
|
+
import { UnvalidatedInputRule } from './unvalidated-input';
|
|
9
|
+
import { DirectoryTraversalRule } from './directory-traversal';
|
|
10
|
+
import { InsecureDependenciesRule } from './insecure-dependencies';
|
|
11
|
+
import { MissingSecurityHeadersRule } from './missing-security-headers';
|
|
12
|
+
export declare function getAllRules(): BaseRule[];
|
|
13
|
+
export { ExposedSecretsRule, MissingAuthenticationRule, OpenCorsRule, HardcodedSensitiveDataRule, InsecureHttpRule, SqlInjectionRule, UnvalidatedInputRule, DirectoryTraversalRule, InsecureDependenciesRule, MissingSecurityHeadersRule, };
|
|
14
|
+
export * from '../types';
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rules/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AAExE,wBAAgB,WAAW,IAAI,QAAQ,EAAE,CAaxC;AAED,OAAO,EACL,kBAAkB,EAClB,yBAAyB,EACzB,YAAY,EACZ,0BAA0B,EAC1B,gBAAgB,EAChB,gBAAgB,EAChB,oBAAoB,EACpB,sBAAsB,EACtB,wBAAwB,EACxB,0BAA0B,GAE3B,CAAC;AAEF,cAAc,UAAU,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.MissingSecurityHeadersRule = exports.InsecureDependenciesRule = exports.DirectoryTraversalRule = exports.UnvalidatedInputRule = exports.SqlInjectionRule = exports.InsecureHttpRule = exports.HardcodedSensitiveDataRule = exports.OpenCorsRule = exports.MissingAuthenticationRule = exports.ExposedSecretsRule = void 0;
|
|
18
|
+
exports.getAllRules = getAllRules;
|
|
19
|
+
const exposed_secrets_1 = require("./exposed-secrets");
|
|
20
|
+
Object.defineProperty(exports, "ExposedSecretsRule", { enumerable: true, get: function () { return exposed_secrets_1.ExposedSecretsRule; } });
|
|
21
|
+
const missing_authentication_1 = require("./missing-authentication");
|
|
22
|
+
Object.defineProperty(exports, "MissingAuthenticationRule", { enumerable: true, get: function () { return missing_authentication_1.MissingAuthenticationRule; } });
|
|
23
|
+
const open_cors_1 = require("./open-cors");
|
|
24
|
+
Object.defineProperty(exports, "OpenCorsRule", { enumerable: true, get: function () { return open_cors_1.OpenCorsRule; } });
|
|
25
|
+
const hardcoded_sensitive_data_1 = require("./hardcoded-sensitive-data");
|
|
26
|
+
Object.defineProperty(exports, "HardcodedSensitiveDataRule", { enumerable: true, get: function () { return hardcoded_sensitive_data_1.HardcodedSensitiveDataRule; } });
|
|
27
|
+
const insecure_http_1 = require("./insecure-http");
|
|
28
|
+
Object.defineProperty(exports, "InsecureHttpRule", { enumerable: true, get: function () { return insecure_http_1.InsecureHttpRule; } });
|
|
29
|
+
const sql_injection_1 = require("./sql-injection");
|
|
30
|
+
Object.defineProperty(exports, "SqlInjectionRule", { enumerable: true, get: function () { return sql_injection_1.SqlInjectionRule; } });
|
|
31
|
+
const unvalidated_input_1 = require("./unvalidated-input");
|
|
32
|
+
Object.defineProperty(exports, "UnvalidatedInputRule", { enumerable: true, get: function () { return unvalidated_input_1.UnvalidatedInputRule; } });
|
|
33
|
+
const directory_traversal_1 = require("./directory-traversal");
|
|
34
|
+
Object.defineProperty(exports, "DirectoryTraversalRule", { enumerable: true, get: function () { return directory_traversal_1.DirectoryTraversalRule; } });
|
|
35
|
+
const insecure_dependencies_1 = require("./insecure-dependencies");
|
|
36
|
+
Object.defineProperty(exports, "InsecureDependenciesRule", { enumerable: true, get: function () { return insecure_dependencies_1.InsecureDependenciesRule; } });
|
|
37
|
+
const missing_security_headers_1 = require("./missing-security-headers");
|
|
38
|
+
Object.defineProperty(exports, "MissingSecurityHeadersRule", { enumerable: true, get: function () { return missing_security_headers_1.MissingSecurityHeadersRule; } });
|
|
39
|
+
function getAllRules() {
|
|
40
|
+
return [
|
|
41
|
+
new exposed_secrets_1.ExposedSecretsRule(),
|
|
42
|
+
new missing_authentication_1.MissingAuthenticationRule(),
|
|
43
|
+
new open_cors_1.OpenCorsRule(),
|
|
44
|
+
new hardcoded_sensitive_data_1.HardcodedSensitiveDataRule(),
|
|
45
|
+
new insecure_http_1.InsecureHttpRule(),
|
|
46
|
+
new sql_injection_1.SqlInjectionRule(),
|
|
47
|
+
new unvalidated_input_1.UnvalidatedInputRule(),
|
|
48
|
+
new directory_traversal_1.DirectoryTraversalRule(),
|
|
49
|
+
new insecure_dependencies_1.InsecureDependenciesRule(),
|
|
50
|
+
new missing_security_headers_1.MissingSecurityHeadersRule(),
|
|
51
|
+
];
|
|
52
|
+
}
|
|
53
|
+
__exportStar(require("../types"), exports);
|
|
54
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/rules/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAYA,kCAaC;AAxBD,uDAAuD;AA2BrD,mGA3BO,oCAAkB,OA2BP;AA1BpB,qEAAqE;AA2BnE,0GA3BO,kDAAyB,OA2BP;AA1B3B,2CAA2C;AA2BzC,6FA3BO,wBAAY,OA2BP;AA1Bd,yEAAwE;AA2BtE,2GA3BO,qDAA0B,OA2BP;AA1B5B,mDAAmD;AA2BjD,iGA3BO,gCAAgB,OA2BP;AA1BlB,mDAAmD;AA2BjD,iGA3BO,gCAAgB,OA2BP;AA1BlB,2DAA2D;AA2BzD,qGA3BO,wCAAoB,OA2BP;AA1BtB,+DAA+D;AA2B7D,uGA3BO,4CAAsB,OA2BP;AA1BxB,mEAAmE;AA2BjE,yGA3BO,gDAAwB,OA2BP;AA1B1B,yEAAwE;AA2BtE,2GA3BO,qDAA0B,OA2BP;AAzB5B,SAAgB,WAAW;IACzB,OAAO;QACL,IAAI,oCAAkB,EAAE;QACxB,IAAI,kDAAyB,EAAE;QAC/B,IAAI,wBAAY,EAAE;QAClB,IAAI,qDAA0B,EAAE;QAChC,IAAI,gCAAgB,EAAE;QACtB,IAAI,gCAAgB,EAAE;QACtB,IAAI,wCAAoB,EAAE;QAC1B,IAAI,4CAAsB,EAAE;QAC5B,IAAI,gDAAwB,EAAE;QAC9B,IAAI,qDAA0B,EAAE;KACjC,CAAC;AACJ,CAAC;AAgBD,2CAAyB"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { BaseRule, FileContent, SecurityIssue } from '../types';
|
|
2
|
+
export declare class InsecureDependenciesRule extends BaseRule {
|
|
3
|
+
readonly name = "insecure-dependencies";
|
|
4
|
+
readonly description = "Detects potentially insecure dependencies and packages";
|
|
5
|
+
readonly severity: "medium";
|
|
6
|
+
private readonly vulnerablePackages;
|
|
7
|
+
private readonly suspiciousPatterns;
|
|
8
|
+
check(fileContent: FileContent): SecurityIssue[];
|
|
9
|
+
private isDependencyFile;
|
|
10
|
+
private checkVulnerablePackages;
|
|
11
|
+
private checkSuspiciousPatterns;
|
|
12
|
+
private isVulnerableVersion;
|
|
13
|
+
private compareVersions;
|
|
14
|
+
private isInDevDependencies;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=insecure-dependencies.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"insecure-dependencies.d.ts","sourceRoot":"","sources":["../../src/rules/insecure-dependencies.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEhE,qBAAa,wBAAyB,SAAQ,QAAQ;IACpD,QAAQ,CAAC,IAAI,2BAA2B;IACxC,QAAQ,CAAC,WAAW,4DAA4D;IAChF,QAAQ,CAAC,QAAQ,EAAG,QAAQ,CAAU;IAEtC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAwBjC;IAEF,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAajC;IAEF,KAAK,CAAC,WAAW,EAAE,WAAW,GAAG,aAAa,EAAE;IAiBhD,OAAO,CAAC,gBAAgB;IAgBxB,OAAO,CAAC,uBAAuB;IAsB/B,OAAO,CAAC,uBAAuB;IAsB/B,OAAO,CAAC,mBAAmB;IAuB3B,OAAO,CAAC,eAAe;IAgBvB,OAAO,CAAC,mBAAmB;CA0B5B"}
|