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.
Files changed (67) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +200 -0
  3. package/dist/bin/vibe-guard.d.ts +3 -0
  4. package/dist/bin/vibe-guard.d.ts.map +1 -0
  5. package/dist/bin/vibe-guard.js +119 -0
  6. package/dist/bin/vibe-guard.js.map +1 -0
  7. package/dist/index.d.ts +19 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +128 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/reporter.d.ts +13 -0
  12. package/dist/reporter.d.ts.map +1 -0
  13. package/dist/reporter.js +116 -0
  14. package/dist/reporter.js.map +1 -0
  15. package/dist/rules/directory-traversal.d.ts +14 -0
  16. package/dist/rules/directory-traversal.d.ts.map +1 -0
  17. package/dist/rules/directory-traversal.js +142 -0
  18. package/dist/rules/directory-traversal.js.map +1 -0
  19. package/dist/rules/exposed-secrets.d.ts +13 -0
  20. package/dist/rules/exposed-secrets.d.ts.map +1 -0
  21. package/dist/rules/exposed-secrets.js +137 -0
  22. package/dist/rules/exposed-secrets.js.map +1 -0
  23. package/dist/rules/hardcoded-sensitive-data.d.ts +13 -0
  24. package/dist/rules/hardcoded-sensitive-data.d.ts.map +1 -0
  25. package/dist/rules/hardcoded-sensitive-data.js +104 -0
  26. package/dist/rules/hardcoded-sensitive-data.js.map +1 -0
  27. package/dist/rules/index.d.ts +15 -0
  28. package/dist/rules/index.d.ts.map +1 -0
  29. package/dist/rules/index.js +54 -0
  30. package/dist/rules/index.js.map +1 -0
  31. package/dist/rules/insecure-dependencies.d.ts +16 -0
  32. package/dist/rules/insecure-dependencies.d.ts.map +1 -0
  33. package/dist/rules/insecure-dependencies.js +152 -0
  34. package/dist/rules/insecure-dependencies.js.map +1 -0
  35. package/dist/rules/insecure-http.d.ts +13 -0
  36. package/dist/rules/insecure-http.d.ts.map +1 -0
  37. package/dist/rules/insecure-http.js +91 -0
  38. package/dist/rules/insecure-http.js.map +1 -0
  39. package/dist/rules/missing-authentication.d.ts +14 -0
  40. package/dist/rules/missing-authentication.d.ts.map +1 -0
  41. package/dist/rules/missing-authentication.js +98 -0
  42. package/dist/rules/missing-authentication.js.map +1 -0
  43. package/dist/rules/missing-security-headers.d.ts +16 -0
  44. package/dist/rules/missing-security-headers.d.ts.map +1 -0
  45. package/dist/rules/missing-security-headers.js +158 -0
  46. package/dist/rules/missing-security-headers.js.map +1 -0
  47. package/dist/rules/open-cors.d.ts +11 -0
  48. package/dist/rules/open-cors.d.ts.map +1 -0
  49. package/dist/rules/open-cors.js +61 -0
  50. package/dist/rules/open-cors.js.map +1 -0
  51. package/dist/rules/sql-injection.d.ts +12 -0
  52. package/dist/rules/sql-injection.d.ts.map +1 -0
  53. package/dist/rules/sql-injection.js +95 -0
  54. package/dist/rules/sql-injection.js.map +1 -0
  55. package/dist/rules/unvalidated-input.d.ts +13 -0
  56. package/dist/rules/unvalidated-input.d.ts.map +1 -0
  57. package/dist/rules/unvalidated-input.js +128 -0
  58. package/dist/rules/unvalidated-input.js.map +1 -0
  59. package/dist/scanner.d.ts +15 -0
  60. package/dist/scanner.d.ts.map +1 -0
  61. package/dist/scanner.js +240 -0
  62. package/dist/scanner.js.map +1 -0
  63. package/dist/types/index.d.ts +66 -0
  64. package/dist/types/index.d.ts.map +1 -0
  65. package/dist/types/index.js +38 -0
  66. package/dist/types/index.js.map +1 -0
  67. package/package.json +72 -0
@@ -0,0 +1,152 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.InsecureDependenciesRule = void 0;
4
+ const types_1 = require("../types");
5
+ class InsecureDependenciesRule extends types_1.BaseRule {
6
+ constructor() {
7
+ super(...arguments);
8
+ this.name = 'insecure-dependencies';
9
+ this.description = 'Detects potentially insecure dependencies and packages';
10
+ this.severity = 'medium';
11
+ this.vulnerablePackages = [
12
+ // Known vulnerable packages
13
+ { name: 'lodash', versions: ['<4.17.21'], reason: 'Prototype pollution vulnerabilities' },
14
+ { name: 'moment', versions: ['*'], reason: 'Deprecated package, use date-fns or dayjs instead' },
15
+ { name: 'request', versions: ['*'], reason: 'Deprecated package with security issues' },
16
+ { name: 'node-uuid', versions: ['*'], reason: 'Deprecated, use uuid package instead' },
17
+ { name: 'growl', versions: ['<1.10.0'], reason: 'Command injection vulnerability' },
18
+ { name: 'handlebars', versions: ['<4.7.7'], reason: 'Template injection vulnerabilities' },
19
+ { name: 'serialize-javascript', versions: ['<3.1.0'], reason: 'XSS vulnerability' },
20
+ { name: 'minimist', versions: ['<1.2.6'], reason: 'Prototype pollution vulnerability' },
21
+ { name: 'yargs-parser', versions: ['<13.1.2'], reason: 'Prototype pollution vulnerability' },
22
+ { name: 'ini', versions: ['<1.3.6'], reason: 'Prototype pollution vulnerability' },
23
+ // Python packages
24
+ { name: 'django', versions: ['<3.2.13'], reason: 'Multiple security vulnerabilities' },
25
+ { name: 'flask', versions: ['<2.0.0'], reason: 'Security improvements in newer versions' },
26
+ { name: 'requests', versions: ['<2.20.0'], reason: 'SSL verification issues' },
27
+ { name: 'pyyaml', versions: ['<5.4'], reason: 'Arbitrary code execution vulnerability' },
28
+ { name: 'pillow', versions: ['<8.3.2'], reason: 'Multiple image processing vulnerabilities' },
29
+ // PHP packages
30
+ { name: 'symfony/symfony', versions: ['<4.4.35'], reason: 'Multiple security vulnerabilities' },
31
+ { name: 'laravel/framework', versions: ['<8.75.0'], reason: 'Security vulnerabilities' },
32
+ { name: 'monolog/monolog', versions: ['<2.3.5'], reason: 'Remote code execution vulnerability' }
33
+ ];
34
+ this.suspiciousPatterns = [
35
+ // Suspicious package names
36
+ { pattern: /(?:^|\s)(?:eval|exec|shell|cmd|system|proc|spawn)(?:-|_)?(?:js|py|php|rb)?\s*[:=]/gi, type: 'Suspicious package name' },
37
+ { pattern: /(?:^|\s)(?:backdoor|malware|virus|trojan|keylogger)\s*[:=]/gi, type: 'Malicious package name' },
38
+ // Typosquatting patterns (common misspellings)
39
+ { pattern: /(?:^|\s)(?:lodahs|momnet|expres|reactt|angualr|vuejs)\s*[:=]/gi, type: 'Potential typosquatting' },
40
+ // Suspicious version patterns
41
+ { pattern: /["'](?:\*|latest|>.*|>=.*\|\|.*|.*\.\*\.\*)["']/g, type: 'Overly permissive version range' },
42
+ // Development dependencies in production
43
+ { pattern: /"devDependencies"\s*:\s*\{[^}]*"(?:nodemon|webpack-dev-server|jest|mocha|chai|sinon)"/gi, type: 'Development dependency' }
44
+ ];
45
+ }
46
+ check(fileContent) {
47
+ const issues = [];
48
+ // Only check dependency files
49
+ if (!this.isDependencyFile(fileContent.path)) {
50
+ return issues;
51
+ }
52
+ // Check for vulnerable packages
53
+ this.checkVulnerablePackages(fileContent, issues);
54
+ // Check for suspicious patterns
55
+ this.checkSuspiciousPatterns(fileContent, issues);
56
+ return issues;
57
+ }
58
+ isDependencyFile(filePath) {
59
+ const dependencyFiles = [
60
+ /package\.json$/i,
61
+ /requirements\.txt$/i,
62
+ /Pipfile$/i,
63
+ /composer\.json$/i,
64
+ /Gemfile$/i,
65
+ /pom\.xml$/i,
66
+ /build\.gradle$/i,
67
+ /yarn\.lock$/i,
68
+ /package-lock\.json$/i
69
+ ];
70
+ return dependencyFiles.some(pattern => pattern.test(filePath));
71
+ }
72
+ checkVulnerablePackages(fileContent, issues) {
73
+ for (const pkg of this.vulnerablePackages) {
74
+ const pattern = new RegExp(`["']${pkg.name}["']\\s*:\\s*["']([^"']+)["']`, 'gi');
75
+ const matches = this.findMatches(fileContent.content, pattern);
76
+ for (const { match, line, column, lineContent } of matches) {
77
+ const version = match[1];
78
+ if (version && this.isVulnerableVersion(version, pkg.versions)) {
79
+ issues.push(this.createIssue(fileContent.path, line, column, lineContent, `Vulnerable dependency: ${pkg.name}@${version}`, `${pkg.reason}. Update to a secure version or find an alternative package.`));
80
+ }
81
+ }
82
+ }
83
+ }
84
+ checkSuspiciousPatterns(fileContent, issues) {
85
+ for (const { pattern, type } of this.suspiciousPatterns) {
86
+ const matches = this.findMatches(fileContent.content, pattern);
87
+ for (const { line, column, lineContent } of matches) {
88
+ // Skip development dependencies check if it's actually in devDependencies section
89
+ if (type === 'Development dependency' && this.isInDevDependencies(fileContent.content, line)) {
90
+ continue;
91
+ }
92
+ issues.push(this.createIssue(fileContent.path, line, column, lineContent, `Suspicious dependency pattern: ${type}`, `Review this dependency carefully. Ensure it's from a trusted source and serves a legitimate purpose.`));
93
+ }
94
+ }
95
+ }
96
+ isVulnerableVersion(version, vulnerableVersions) {
97
+ // Simple version checking - in a real implementation, you'd use semver
98
+ for (const vulnVersion of vulnerableVersions) {
99
+ if (vulnVersion === '*') {
100
+ return true;
101
+ }
102
+ if (vulnVersion.startsWith('<')) {
103
+ // This is a simplified check - real implementation would use proper semver comparison
104
+ const targetVersion = vulnVersion.substring(1);
105
+ if (this.compareVersions(version, targetVersion) < 0) {
106
+ return true;
107
+ }
108
+ }
109
+ if (version === vulnVersion) {
110
+ return true;
111
+ }
112
+ }
113
+ return false;
114
+ }
115
+ compareVersions(version1, version2) {
116
+ // Simplified version comparison - real implementation would handle all semver cases
117
+ const v1Parts = version1.replace(/[^\d.]/g, '').split('.').map(Number);
118
+ const v2Parts = version2.replace(/[^\d.]/g, '').split('.').map(Number);
119
+ for (let i = 0; i < Math.max(v1Parts.length, v2Parts.length); i++) {
120
+ const v1Part = v1Parts[i] || 0;
121
+ const v2Part = v2Parts[i] || 0;
122
+ if (v1Part < v2Part)
123
+ return -1;
124
+ if (v1Part > v2Part)
125
+ return 1;
126
+ }
127
+ return 0;
128
+ }
129
+ isInDevDependencies(content, lineNumber) {
130
+ const lines = content.split('\n');
131
+ // Look backwards from the current line to find the section
132
+ for (let i = lineNumber - 1; i >= 0; i--) {
133
+ const line = lines[i];
134
+ if (!line)
135
+ continue;
136
+ const trimmedLine = line.trim();
137
+ if (trimmedLine.includes('"devDependencies"')) {
138
+ return true;
139
+ }
140
+ if (trimmedLine.includes('"dependencies"') && !trimmedLine.includes('"devDependencies"')) {
141
+ return false;
142
+ }
143
+ // If we hit another top-level section, stop looking
144
+ if (trimmedLine.match(/^"[^"]+"\s*:\s*\{/) && !trimmedLine.includes('Dependencies')) {
145
+ break;
146
+ }
147
+ }
148
+ return false;
149
+ }
150
+ }
151
+ exports.InsecureDependenciesRule = InsecureDependenciesRule;
152
+ //# sourceMappingURL=insecure-dependencies.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"insecure-dependencies.js","sourceRoot":"","sources":["../../src/rules/insecure-dependencies.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { BaseRule, FileContent, SecurityIssue } from '../types';
2
+ export declare class InsecureHttpRule extends BaseRule {
3
+ readonly name = "insecure-http";
4
+ readonly description = "Detects insecure HTTP usage instead of HTTPS";
5
+ readonly severity: "medium";
6
+ private readonly httpPatterns;
7
+ private readonly safePatterns;
8
+ check(fileContent: FileContent): SecurityIssue[];
9
+ private isDevelopmentContext;
10
+ private isTestFile;
11
+ private extractUrl;
12
+ }
13
+ //# sourceMappingURL=insecure-http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"insecure-http.d.ts","sourceRoot":"","sources":["../../src/rules/insecure-http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEhE,qBAAa,gBAAiB,SAAQ,QAAQ;IAC5C,QAAQ,CAAC,IAAI,mBAAmB;IAChC,QAAQ,CAAC,WAAW,kDAAkD;IACtE,QAAQ,CAAC,QAAQ,EAAG,QAAQ,CAAU;IAEtC,OAAO,CAAC,QAAQ,CAAC,YAAY,CA4B3B;IAEF,OAAO,CAAC,QAAQ,CAAC,YAAY,CAY3B;IAEF,KAAK,CAAC,WAAW,EAAE,WAAW,GAAG,aAAa,EAAE;IAiChD,OAAO,CAAC,oBAAoB;IAI5B,OAAO,CAAC,UAAU;IAiBlB,OAAO,CAAC,UAAU;CAInB"}
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.InsecureHttpRule = void 0;
4
+ const types_1 = require("../types");
5
+ class InsecureHttpRule extends types_1.BaseRule {
6
+ constructor() {
7
+ super(...arguments);
8
+ this.name = 'insecure-http';
9
+ this.description = 'Detects insecure HTTP usage instead of HTTPS';
10
+ this.severity = 'medium';
11
+ this.httpPatterns = [
12
+ // Direct HTTP URLs
13
+ { pattern: /['"`]http:\/\/(?!localhost|127\.0\.0\.1|0\.0\.0\.0)[^'"`\s]+['"`]/gi, type: 'HTTP URL' },
14
+ // API endpoints
15
+ { pattern: /(?:api_url|endpoint|base_url)\s*[:=]\s*['"`]http:\/\/[^'"`\s]+['"`]/gi, type: 'HTTP API Endpoint' },
16
+ { pattern: /fetch\s*\(\s*['"`]http:\/\/[^'"`\s]+['"`]/gi, type: 'HTTP Fetch Request' },
17
+ { pattern: /axios\.(?:get|post|put|delete)\s*\(\s*['"`]http:\/\/[^'"`\s]+['"`]/gi, type: 'HTTP Axios Request' },
18
+ // Configuration
19
+ { pattern: /(?:protocol|scheme)\s*[:=]\s*['"`]http['"`]/gi, type: 'HTTP Protocol Configuration' },
20
+ { pattern: /secure\s*[:=]\s*false/gi, type: 'Insecure Configuration' },
21
+ // Express/Node.js specific
22
+ { pattern: /app\.listen\s*\(\s*\d+\s*,\s*['"`]0\.0\.0\.0['"`]/gi, type: 'HTTP Server Binding' },
23
+ { pattern: /createServer\s*\(\s*(?!.*https)/gi, type: 'HTTP Server Creation' },
24
+ // Cookie security
25
+ { pattern: /httpOnly\s*:\s*false/gi, type: 'Insecure Cookie Configuration' },
26
+ { pattern: /secure\s*:\s*false/gi, type: 'Insecure Cookie Security' },
27
+ // Mixed content
28
+ { pattern: /src\s*=\s*['"`]http:\/\/[^'"`\s]+['"`]/gi, type: 'Mixed Content Resource' },
29
+ { pattern: /href\s*=\s*['"`]http:\/\/[^'"`\s]+['"`]/gi, type: 'Mixed Content Link' },
30
+ // Framework specific
31
+ { pattern: /@RequestMapping.*http:/gi, type: 'HTTP Spring Mapping' },
32
+ { pattern: /ALLOWED_HOSTS\s*=\s*\[\s*['"`]\*['"`]/gi, type: 'Permissive Host Configuration' }
33
+ ];
34
+ this.safePatterns = [
35
+ /localhost/i,
36
+ /127\.0\.0\.1/,
37
+ /0\.0\.0\.0/,
38
+ /\.local/i,
39
+ /development/i,
40
+ /dev/i,
41
+ /staging/i,
42
+ /test/i,
43
+ /mock/i,
44
+ /example/i,
45
+ /placeholder/i
46
+ ];
47
+ }
48
+ check(fileContent) {
49
+ const issues = [];
50
+ for (const { pattern, type } of this.httpPatterns) {
51
+ const matches = this.findMatches(fileContent.content, pattern);
52
+ for (const { match, line, column, lineContent } of matches) {
53
+ const matchedText = match[0];
54
+ // Skip if it's in a development/test context
55
+ if (this.isDevelopmentContext(matchedText) || this.isDevelopmentContext(lineContent)) {
56
+ continue;
57
+ }
58
+ // Skip if the file appears to be a test or development file
59
+ if (this.isTestFile(fileContent.path)) {
60
+ continue;
61
+ }
62
+ issues.push(this.createIssue(fileContent.path, line, column, lineContent, `Insecure ${type} detected: ${this.extractUrl(matchedText)}`, `Use HTTPS instead of HTTP for secure communication. Replace 'http://' with 'https://' and ensure SSL/TLS certificates are properly configured.`));
63
+ }
64
+ }
65
+ return issues;
66
+ }
67
+ isDevelopmentContext(text) {
68
+ return this.safePatterns.some(pattern => pattern.test(text));
69
+ }
70
+ isTestFile(filePath) {
71
+ const testPatterns = [
72
+ /test/i,
73
+ /spec/i,
74
+ /\.test\./i,
75
+ /\.spec\./i,
76
+ /__tests__/i,
77
+ /tests\//i,
78
+ /spec\//i,
79
+ /dev/i,
80
+ /development/i,
81
+ /local/i
82
+ ];
83
+ return testPatterns.some(pattern => pattern.test(filePath));
84
+ }
85
+ extractUrl(text) {
86
+ const urlMatch = text.match(/http:\/\/[^'"`\s]+/);
87
+ return urlMatch ? urlMatch[0] : text;
88
+ }
89
+ }
90
+ exports.InsecureHttpRule = InsecureHttpRule;
91
+ //# sourceMappingURL=insecure-http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"insecure-http.js","sourceRoot":"","sources":["../../src/rules/insecure-http.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { BaseRule, FileContent, SecurityIssue } from '../types';
2
+ export declare class MissingAuthenticationRule extends BaseRule {
3
+ readonly name = "missing-authentication";
4
+ readonly description = "Detects potentially unprotected routes and endpoints";
5
+ readonly severity: "high";
6
+ private readonly routePatterns;
7
+ private readonly protectedPatterns;
8
+ private readonly publicEndpoints;
9
+ check(fileContent: FileContent): SecurityIssue[];
10
+ private extractRoute;
11
+ private isPublicEndpoint;
12
+ private hasAuthenticationContext;
13
+ }
14
+ //# sourceMappingURL=missing-authentication.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"missing-authentication.d.ts","sourceRoot":"","sources":["../../src/rules/missing-authentication.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEhE,qBAAa,yBAA0B,SAAQ,QAAQ;IACrD,QAAQ,CAAC,IAAI,4BAA4B;IACzC,QAAQ,CAAC,WAAW,0DAA0D;IAC9E,QAAQ,CAAC,QAAQ,EAAG,MAAM,CAAU;IAEpC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAgB5B;IAEF,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAahC;IAEF,OAAO,CAAC,QAAQ,CAAC,eAAe,CAgB9B;IAEF,KAAK,CAAC,WAAW,EAAE,WAAW,GAAG,aAAa,EAAE;IAiChD,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,gBAAgB;IAIxB,OAAO,CAAC,wBAAwB;CAWjC"}
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MissingAuthenticationRule = void 0;
4
+ const types_1 = require("../types");
5
+ class MissingAuthenticationRule extends types_1.BaseRule {
6
+ constructor() {
7
+ super(...arguments);
8
+ this.name = 'missing-authentication';
9
+ this.description = 'Detects potentially unprotected routes and endpoints';
10
+ this.severity = 'high';
11
+ this.routePatterns = [
12
+ // Express.js
13
+ { pattern: /app\.(get|post|put|delete|patch)\s*\(\s*['"`]([^'"`]+)['"`]\s*,\s*(?!.*auth|.*login|.*verify|.*middleware)/gi, framework: 'Express' },
14
+ { pattern: /router\.(get|post|put|delete|patch)\s*\(\s*['"`]([^'"`]+)['"`]\s*,\s*(?!.*auth|.*login|.*verify|.*middleware)/gi, framework: 'Express' },
15
+ // Next.js API routes
16
+ { pattern: /export\s+(?:default\s+)?(?:async\s+)?function\s+handler\s*\([^)]*\)\s*\{(?![\s\S]*auth|[\s\S]*login|[\s\S]*verify)/gi, framework: 'Next.js' },
17
+ // Flask
18
+ { pattern: /@app\.route\s*\(\s*['"`]([^'"`]+)['"`](?:[^)]*)\)\s*\n\s*def\s+\w+\s*\([^)]*\)\s*:(?![\s\S]*auth|[\s\S]*login|[\s\S]*verify)/gi, framework: 'Flask' },
19
+ // FastAPI
20
+ { pattern: /@app\.(get|post|put|delete|patch)\s*\(\s*['"`]([^'"`]+)['"`]\s*\)\s*\n\s*(?:async\s+)?def\s+\w+\s*\([^)]*\)\s*:(?![\s\S]*auth|[\s\S]*login|[\s\S]*verify)/gi, framework: 'FastAPI' },
21
+ // Laravel
22
+ { pattern: /Route::(get|post|put|delete|patch)\s*\(\s*['"`]([^'"`]+)['"`]\s*,\s*(?!.*auth|.*login|.*verify|.*middleware)/gi, framework: 'Laravel' }
23
+ ];
24
+ this.protectedPatterns = [
25
+ /auth/i,
26
+ /login/i,
27
+ /verify/i,
28
+ /middleware/i,
29
+ /guard/i,
30
+ /protect/i,
31
+ /secure/i,
32
+ /jwt/i,
33
+ /token/i,
34
+ /session/i,
35
+ /permission/i,
36
+ /role/i
37
+ ];
38
+ this.publicEndpoints = [
39
+ /\/public/i,
40
+ /\/health/i,
41
+ /\/ping/i,
42
+ /\/status/i,
43
+ /\/docs/i,
44
+ /\/swagger/i,
45
+ /\/api-docs/i,
46
+ /\/favicon/i,
47
+ /\/robots\.txt/i,
48
+ /\/sitemap/i,
49
+ /\/login/i,
50
+ /\/register/i,
51
+ /\/signup/i,
52
+ /\/forgot-password/i,
53
+ /\/reset-password/i
54
+ ];
55
+ }
56
+ check(fileContent) {
57
+ const issues = [];
58
+ for (const { pattern, framework } of this.routePatterns) {
59
+ const matches = this.findMatches(fileContent.content, pattern);
60
+ for (const { match, line, column, lineContent } of matches) {
61
+ const route = this.extractRoute(match);
62
+ // Skip if it's a known public endpoint
63
+ if (this.isPublicEndpoint(route)) {
64
+ continue;
65
+ }
66
+ // Skip if the surrounding code suggests authentication
67
+ if (this.hasAuthenticationContext(fileContent.content, line)) {
68
+ continue;
69
+ }
70
+ issues.push(this.createIssue(fileContent.path, line, column, lineContent, `Potentially unprotected ${framework} route: ${route}`, `Add authentication middleware or verify that this endpoint should be publicly accessible. Consider using authentication guards, middleware, or decorators.`));
71
+ }
72
+ }
73
+ return issues;
74
+ }
75
+ extractRoute(match) {
76
+ // Try to find the route path in the match
77
+ for (let i = 1; i < match.length; i++) {
78
+ const matchGroup = match[i];
79
+ if (matchGroup && matchGroup.startsWith('/')) {
80
+ return matchGroup;
81
+ }
82
+ }
83
+ return match[0] || '';
84
+ }
85
+ isPublicEndpoint(route) {
86
+ return this.publicEndpoints.some(pattern => pattern.test(route));
87
+ }
88
+ hasAuthenticationContext(content, lineNumber) {
89
+ const lines = content.split('\n');
90
+ const contextRange = 10; // Check 10 lines before and after
91
+ const startLine = Math.max(0, lineNumber - contextRange - 1);
92
+ const endLine = Math.min(lines.length, lineNumber + contextRange);
93
+ const contextLines = lines.slice(startLine, endLine).join('\n');
94
+ return this.protectedPatterns.some(pattern => pattern.test(contextLines));
95
+ }
96
+ }
97
+ exports.MissingAuthenticationRule = MissingAuthenticationRule;
98
+ //# sourceMappingURL=missing-authentication.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"missing-authentication.js","sourceRoot":"","sources":["../../src/rules/missing-authentication.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { BaseRule, FileContent, SecurityIssue } from '../types';
2
+ export declare class MissingSecurityHeadersRule extends BaseRule {
3
+ readonly name = "missing-security-headers";
4
+ readonly description = "Detects missing HTTP security headers";
5
+ readonly severity: "medium";
6
+ private readonly securityHeaders;
7
+ private readonly serverPatterns;
8
+ check(fileContent: FileContent): SecurityIssue[];
9
+ private isWebApplicationFile;
10
+ private hasServerCode;
11
+ private checkMissingHeaders;
12
+ private hasSecurityHeader;
13
+ private findReportLocation;
14
+ private getHeaderRecommendations;
15
+ }
16
+ //# sourceMappingURL=missing-security-headers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"missing-security-headers.d.ts","sourceRoot":"","sources":["../../src/rules/missing-security-headers.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,2CAA2C;IAC/D,QAAQ,CAAC,QAAQ,EAAG,QAAQ,CAAU;IAEtC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAS9B;IAEF,OAAO,CAAC,QAAQ,CAAC,cAAc,CA4B7B;IAEF,KAAK,CAAC,WAAW,EAAE,WAAW,GAAG,aAAa,EAAE;IAoBhD,OAAO,CAAC,oBAAoB;IA8B5B,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,mBAAmB;IA2B3B,OAAO,CAAC,iBAAiB;IA0BzB,OAAO,CAAC,kBAAkB;IAiB1B,OAAO,CAAC,wBAAwB;CAqBjC"}
@@ -0,0 +1,158 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MissingSecurityHeadersRule = void 0;
4
+ const types_1 = require("../types");
5
+ class MissingSecurityHeadersRule extends types_1.BaseRule {
6
+ constructor() {
7
+ super(...arguments);
8
+ this.name = 'missing-security-headers';
9
+ this.description = 'Detects missing HTTP security headers';
10
+ this.severity = 'medium';
11
+ this.securityHeaders = [
12
+ 'Content-Security-Policy',
13
+ 'X-Frame-Options',
14
+ 'X-Content-Type-Options',
15
+ 'X-XSS-Protection',
16
+ 'Strict-Transport-Security',
17
+ 'Referrer-Policy',
18
+ 'Permissions-Policy',
19
+ 'X-Permitted-Cross-Domain-Policies'
20
+ ];
21
+ this.serverPatterns = [
22
+ // Express.js patterns
23
+ { pattern: /app\.(?:get|post|put|delete|patch|use)\s*\(/gi, type: 'Express route handler' },
24
+ { pattern: /router\.(?:get|post|put|delete|patch|use)\s*\(/gi, type: 'Express router' },
25
+ { pattern: /app\.listen\s*\(/gi, type: 'Express server' },
26
+ // Next.js API routes
27
+ { pattern: /export\s+(?:default\s+)?(?:async\s+)?function\s+handler/gi, type: 'Next.js API handler' },
28
+ { pattern: /export\s+(?:const|let|var)\s+\w+\s*=\s*(?:async\s+)?\([^)]*req[^)]*res[^)]*\)/gi, type: 'Next.js API function' },
29
+ // Node.js HTTP server
30
+ { pattern: /createServer\s*\(\s*(?:async\s+)?\([^)]*req[^)]*res[^)]*\)/gi, type: 'Node.js HTTP server' },
31
+ { pattern: /http\.createServer/gi, type: 'HTTP server creation' },
32
+ // Framework response patterns
33
+ { pattern: /res\.(?:send|json|render|redirect)/gi, type: 'Response method' },
34
+ { pattern: /response\.(?:send|json|render|redirect)/gi, type: 'Response method' },
35
+ // Flask patterns
36
+ { pattern: /@app\.route/gi, type: 'Flask route' },
37
+ { pattern: /return\s+(?:render_template|jsonify|redirect)/gi, type: 'Flask response' },
38
+ // Django patterns
39
+ { pattern: /def\s+\w+\s*\([^)]*request[^)]*\)/gi, type: 'Django view function' },
40
+ { pattern: /HttpResponse\s*\(/gi, type: 'Django HTTP response' },
41
+ // PHP patterns
42
+ { pattern: /header\s*\(\s*['"`][^'"`]*['"`]/gi, type: 'PHP header function' }
43
+ ];
44
+ }
45
+ check(fileContent) {
46
+ const issues = [];
47
+ // Only check server/web application files
48
+ if (!this.isWebApplicationFile(fileContent.path)) {
49
+ return issues;
50
+ }
51
+ // Check if file contains server/route patterns
52
+ const hasServerCode = this.hasServerCode(fileContent.content);
53
+ if (!hasServerCode) {
54
+ return issues;
55
+ }
56
+ // Check for missing security headers
57
+ this.checkMissingHeaders(fileContent, issues);
58
+ return issues;
59
+ }
60
+ isWebApplicationFile(filePath) {
61
+ const webFiles = [
62
+ /\.js$/i,
63
+ /\.ts$/i,
64
+ /\.jsx$/i,
65
+ /\.tsx$/i,
66
+ /\.py$/i,
67
+ /\.php$/i,
68
+ /\.rb$/i,
69
+ /\.go$/i,
70
+ /\.java$/i,
71
+ /\.cs$/i
72
+ ];
73
+ // Skip test files
74
+ const testPatterns = [
75
+ /test/i,
76
+ /spec/i,
77
+ /\.test\./i,
78
+ /\.spec\./i,
79
+ /__tests__/i
80
+ ];
81
+ if (testPatterns.some(pattern => pattern.test(filePath))) {
82
+ return false;
83
+ }
84
+ return webFiles.some(pattern => pattern.test(filePath));
85
+ }
86
+ hasServerCode(content) {
87
+ return this.serverPatterns.some(({ pattern }) => pattern.test(content));
88
+ }
89
+ checkMissingHeaders(fileContent, issues) {
90
+ const content = fileContent.content;
91
+ const missingHeaders = [];
92
+ for (const header of this.securityHeaders) {
93
+ if (!this.hasSecurityHeader(content, header)) {
94
+ missingHeaders.push(header);
95
+ }
96
+ }
97
+ if (missingHeaders.length > 0) {
98
+ // Find a good location to report the issue (first route handler or server setup)
99
+ const location = this.findReportLocation(fileContent);
100
+ if (location) {
101
+ issues.push(this.createIssue(fileContent.path, location.line, location.column, location.lineContent, `Missing security headers: ${missingHeaders.join(', ')}`, `Add security headers to protect against common attacks. Consider using helmet.js for Express or implementing headers manually: ${this.getHeaderRecommendations(missingHeaders)}`));
102
+ }
103
+ }
104
+ }
105
+ hasSecurityHeader(content, header) {
106
+ const headerPatterns = [
107
+ // Express.js patterns
108
+ new RegExp(`res\\.(?:set|header)\\s*\\(\\s*['"\`]${header}['"\`]`, 'gi'),
109
+ new RegExp(`res\\.setHeader\\s*\\(\\s*['"\`]${header}['"\`]`, 'gi'),
110
+ // Helmet.js patterns
111
+ /helmet\s*\(\s*\)/gi,
112
+ /helmet\./gi,
113
+ // Manual header setting
114
+ new RegExp(`['"\`]${header}['"\`]\\s*:\\s*['"\`]`, 'gi'),
115
+ // PHP patterns
116
+ new RegExp(`header\\s*\\(\\s*['"\`]${header}:`, 'gi'),
117
+ // Python Flask patterns
118
+ new RegExp(`response\\.headers\\[['"\`]${header}['"\`]\\]`, 'gi'),
119
+ // Django patterns
120
+ new RegExp(`response\\[['"\`]${header}['"\`]\\]`, 'gi')
121
+ ];
122
+ return headerPatterns.some(pattern => pattern.test(content));
123
+ }
124
+ findReportLocation(fileContent) {
125
+ for (const { pattern } of this.serverPatterns) {
126
+ const matches = this.findMatches(fileContent.content, pattern);
127
+ if (matches.length > 0) {
128
+ const firstMatch = matches[0];
129
+ if (firstMatch) {
130
+ return {
131
+ line: firstMatch.line,
132
+ column: firstMatch.column,
133
+ lineContent: firstMatch.lineContent
134
+ };
135
+ }
136
+ }
137
+ }
138
+ return null;
139
+ }
140
+ getHeaderRecommendations(missingHeaders) {
141
+ const recommendations = [];
142
+ if (missingHeaders.includes('Content-Security-Policy')) {
143
+ recommendations.push("CSP: \"default-src 'self'\"");
144
+ }
145
+ if (missingHeaders.includes('X-Frame-Options')) {
146
+ recommendations.push("X-Frame-Options: 'DENY'");
147
+ }
148
+ if (missingHeaders.includes('X-Content-Type-Options')) {
149
+ recommendations.push("X-Content-Type-Options: 'nosniff'");
150
+ }
151
+ if (missingHeaders.includes('Strict-Transport-Security')) {
152
+ recommendations.push("HSTS: 'max-age=31536000; includeSubDomains'");
153
+ }
154
+ return recommendations.slice(0, 2).join(', ') + (recommendations.length > 2 ? '...' : '');
155
+ }
156
+ }
157
+ exports.MissingSecurityHeadersRule = MissingSecurityHeadersRule;
158
+ //# sourceMappingURL=missing-security-headers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"missing-security-headers.js","sourceRoot":"","sources":["../../src/rules/missing-security-headers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { BaseRule, FileContent, SecurityIssue } from '../types';
2
+ export declare class OpenCorsRule extends BaseRule {
3
+ readonly name = "open-cors";
4
+ readonly description = "Detects overly permissive CORS configurations";
5
+ readonly severity: "high";
6
+ private readonly corsPatterns;
7
+ private readonly safePatterns;
8
+ check(fileContent: FileContent): SecurityIssue[];
9
+ private isDevelopmentContext;
10
+ }
11
+ //# sourceMappingURL=open-cors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open-cors.d.ts","sourceRoot":"","sources":["../../src/rules/open-cors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEhE,qBAAa,YAAa,SAAQ,QAAQ;IACxC,QAAQ,CAAC,IAAI,eAAe;IAC5B,QAAQ,CAAC,WAAW,mDAAmD;IACvE,QAAQ,CAAC,QAAQ,EAAG,MAAM,CAAU;IAEpC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAoB3B;IAEF,OAAO,CAAC,QAAQ,CAAC,YAAY,CAO3B;IAEF,KAAK,CAAC,WAAW,EAAE,WAAW,GAAG,aAAa,EAAE;IA0BhD,OAAO,CAAC,oBAAoB;CAW7B"}