@trust-assurance-protocol/owaspscan 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/dist/analysis/ast-analyzer.d.ts +13 -0
- package/dist/analysis/ast-analyzer.d.ts.map +1 -0
- package/dist/analysis/ast-analyzer.js +58 -0
- package/dist/analysis/ast-analyzer.js.map +1 -0
- package/dist/analysis/llm-verifier.d.ts +17 -0
- package/dist/analysis/llm-verifier.d.ts.map +1 -0
- package/dist/analysis/llm-verifier.js +152 -0
- package/dist/analysis/llm-verifier.js.map +1 -0
- package/dist/analysis/result-cache.d.ts +20 -0
- package/dist/analysis/result-cache.d.ts.map +1 -0
- package/dist/analysis/result-cache.js +70 -0
- package/dist/analysis/result-cache.js.map +1 -0
- package/dist/analysis/sinks.d.ts +12 -0
- package/dist/analysis/sinks.d.ts.map +1 -0
- package/dist/analysis/sinks.js +142 -0
- package/dist/analysis/sinks.js.map +1 -0
- package/dist/analysis/sources.d.ts +8 -0
- package/dist/analysis/sources.d.ts.map +1 -0
- package/dist/analysis/sources.js +114 -0
- package/dist/analysis/sources.js.map +1 -0
- package/dist/analysis/taint-engine.d.ts +5 -0
- package/dist/analysis/taint-engine.d.ts.map +1 -0
- package/dist/analysis/taint-engine.js +187 -0
- package/dist/analysis/taint-engine.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +227 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/config/loader.d.ts +10 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +81 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/schema.d.ts +23 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +17 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/mcp/server.d.ts +2 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +250 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/parsers/ast-parser.d.ts +38 -0
- package/dist/parsers/ast-parser.d.ts.map +1 -0
- package/dist/parsers/ast-parser.js +88 -0
- package/dist/parsers/ast-parser.js.map +1 -0
- package/dist/parsers/ast-queries.d.ts +63 -0
- package/dist/parsers/ast-queries.d.ts.map +1 -0
- package/dist/parsers/ast-queries.js +580 -0
- package/dist/parsers/ast-queries.js.map +1 -0
- package/dist/reporter/console.d.ts +8 -0
- package/dist/reporter/console.d.ts.map +1 -0
- package/dist/reporter/console.js +143 -0
- package/dist/reporter/console.js.map +1 -0
- package/dist/reporter/json.d.ts +3 -0
- package/dist/reporter/json.d.ts.map +1 -0
- package/dist/reporter/json.js +7 -0
- package/dist/reporter/json.js.map +1 -0
- package/dist/reporter/llm.d.ts +3 -0
- package/dist/reporter/llm.d.ts.map +1 -0
- package/dist/reporter/llm.js +66 -0
- package/dist/reporter/llm.js.map +1 -0
- package/dist/reporter/sarif.d.ts +3 -0
- package/dist/reporter/sarif.d.ts.map +1 -0
- package/dist/reporter/sarif.js +110 -0
- package/dist/reporter/sarif.js.map +1 -0
- package/dist/rules/owasp-a01/idor.d.ts +3 -0
- package/dist/rules/owasp-a01/idor.d.ts.map +1 -0
- package/dist/rules/owasp-a01/idor.js +48 -0
- package/dist/rules/owasp-a01/idor.js.map +1 -0
- package/dist/rules/owasp-a01/missing-auth-middleware.d.ts +3 -0
- package/dist/rules/owasp-a01/missing-auth-middleware.d.ts.map +1 -0
- package/dist/rules/owasp-a01/missing-auth-middleware.js +41 -0
- package/dist/rules/owasp-a01/missing-auth-middleware.js.map +1 -0
- package/dist/rules/owasp-a01/path-traversal.d.ts +3 -0
- package/dist/rules/owasp-a01/path-traversal.d.ts.map +1 -0
- package/dist/rules/owasp-a01/path-traversal.js +73 -0
- package/dist/rules/owasp-a01/path-traversal.js.map +1 -0
- package/dist/rules/owasp-a02/hardcoded-secrets.d.ts +3 -0
- package/dist/rules/owasp-a02/hardcoded-secrets.d.ts.map +1 -0
- package/dist/rules/owasp-a02/hardcoded-secrets.js +97 -0
- package/dist/rules/owasp-a02/hardcoded-secrets.js.map +1 -0
- package/dist/rules/owasp-a02/insecure-tls.d.ts +3 -0
- package/dist/rules/owasp-a02/insecure-tls.d.ts.map +1 -0
- package/dist/rules/owasp-a02/insecure-tls.js +75 -0
- package/dist/rules/owasp-a02/insecure-tls.js.map +1 -0
- package/dist/rules/owasp-a02/weak-hash.d.ts +3 -0
- package/dist/rules/owasp-a02/weak-hash.d.ts.map +1 -0
- package/dist/rules/owasp-a02/weak-hash.js +73 -0
- package/dist/rules/owasp-a02/weak-hash.js.map +1 -0
- package/dist/rules/owasp-a02/weak-random.d.ts +3 -0
- package/dist/rules/owasp-a02/weak-random.d.ts.map +1 -0
- package/dist/rules/owasp-a02/weak-random.js +70 -0
- package/dist/rules/owasp-a02/weak-random.js.map +1 -0
- package/dist/rules/owasp-a03/command-injection.d.ts +3 -0
- package/dist/rules/owasp-a03/command-injection.d.ts.map +1 -0
- package/dist/rules/owasp-a03/command-injection.js +79 -0
- package/dist/rules/owasp-a03/command-injection.js.map +1 -0
- package/dist/rules/owasp-a03/ldap-injection.d.ts +3 -0
- package/dist/rules/owasp-a03/ldap-injection.d.ts.map +1 -0
- package/dist/rules/owasp-a03/ldap-injection.js +56 -0
- package/dist/rules/owasp-a03/ldap-injection.js.map +1 -0
- package/dist/rules/owasp-a03/nosql-injection.d.ts +3 -0
- package/dist/rules/owasp-a03/nosql-injection.d.ts.map +1 -0
- package/dist/rules/owasp-a03/nosql-injection.js +61 -0
- package/dist/rules/owasp-a03/nosql-injection.js.map +1 -0
- package/dist/rules/owasp-a03/sql-injection.d.ts +3 -0
- package/dist/rules/owasp-a03/sql-injection.d.ts.map +1 -0
- package/dist/rules/owasp-a03/sql-injection.js +88 -0
- package/dist/rules/owasp-a03/sql-injection.js.map +1 -0
- package/dist/rules/owasp-a03/template-injection.d.ts +3 -0
- package/dist/rules/owasp-a03/template-injection.d.ts.map +1 -0
- package/dist/rules/owasp-a03/template-injection.js +64 -0
- package/dist/rules/owasp-a03/template-injection.js.map +1 -0
- package/dist/rules/owasp-a03/xss.d.ts +3 -0
- package/dist/rules/owasp-a03/xss.d.ts.map +1 -0
- package/dist/rules/owasp-a03/xss.js +74 -0
- package/dist/rules/owasp-a03/xss.js.map +1 -0
- package/dist/rules/owasp-a04/mass-assignment.d.ts +3 -0
- package/dist/rules/owasp-a04/mass-assignment.d.ts.map +1 -0
- package/dist/rules/owasp-a04/mass-assignment.js +63 -0
- package/dist/rules/owasp-a04/mass-assignment.js.map +1 -0
- package/dist/rules/owasp-a04/missing-rate-limit.d.ts +3 -0
- package/dist/rules/owasp-a04/missing-rate-limit.d.ts.map +1 -0
- package/dist/rules/owasp-a04/missing-rate-limit.js +48 -0
- package/dist/rules/owasp-a04/missing-rate-limit.js.map +1 -0
- package/dist/rules/owasp-a05/cors-wildcard.d.ts +3 -0
- package/dist/rules/owasp-a05/cors-wildcard.d.ts.map +1 -0
- package/dist/rules/owasp-a05/cors-wildcard.js +79 -0
- package/dist/rules/owasp-a05/cors-wildcard.js.map +1 -0
- package/dist/rules/owasp-a05/debug-mode.d.ts +3 -0
- package/dist/rules/owasp-a05/debug-mode.d.ts.map +1 -0
- package/dist/rules/owasp-a05/debug-mode.js +73 -0
- package/dist/rules/owasp-a05/debug-mode.js.map +1 -0
- package/dist/rules/owasp-a05/default-credentials.d.ts +3 -0
- package/dist/rules/owasp-a05/default-credentials.d.ts.map +1 -0
- package/dist/rules/owasp-a05/default-credentials.js +52 -0
- package/dist/rules/owasp-a05/default-credentials.js.map +1 -0
- package/dist/rules/owasp-a05/error-disclosure.d.ts +3 -0
- package/dist/rules/owasp-a05/error-disclosure.d.ts.map +1 -0
- package/dist/rules/owasp-a05/error-disclosure.js +70 -0
- package/dist/rules/owasp-a05/error-disclosure.js.map +1 -0
- package/dist/rules/owasp-a06/outdated-packages.d.ts +3 -0
- package/dist/rules/owasp-a06/outdated-packages.d.ts.map +1 -0
- package/dist/rules/owasp-a06/outdated-packages.js +75 -0
- package/dist/rules/owasp-a06/outdated-packages.js.map +1 -0
- package/dist/rules/owasp-a07/insecure-cookies.d.ts +3 -0
- package/dist/rules/owasp-a07/insecure-cookies.d.ts.map +1 -0
- package/dist/rules/owasp-a07/insecure-cookies.js +64 -0
- package/dist/rules/owasp-a07/insecure-cookies.js.map +1 -0
- package/dist/rules/owasp-a07/jwt-none-alg.d.ts +3 -0
- package/dist/rules/owasp-a07/jwt-none-alg.d.ts.map +1 -0
- package/dist/rules/owasp-a07/jwt-none-alg.js +81 -0
- package/dist/rules/owasp-a07/jwt-none-alg.js.map +1 -0
- package/dist/rules/owasp-a07/no-password-hashing.d.ts +3 -0
- package/dist/rules/owasp-a07/no-password-hashing.d.ts.map +1 -0
- package/dist/rules/owasp-a07/no-password-hashing.js +70 -0
- package/dist/rules/owasp-a07/no-password-hashing.js.map +1 -0
- package/dist/rules/owasp-a07/weak-session.d.ts +3 -0
- package/dist/rules/owasp-a07/weak-session.d.ts.map +1 -0
- package/dist/rules/owasp-a07/weak-session.js +64 -0
- package/dist/rules/owasp-a07/weak-session.js.map +1 -0
- package/dist/rules/owasp-a08/unsafe-deserialization.d.ts +3 -0
- package/dist/rules/owasp-a08/unsafe-deserialization.d.ts.map +1 -0
- package/dist/rules/owasp-a08/unsafe-deserialization.js +78 -0
- package/dist/rules/owasp-a08/unsafe-deserialization.js.map +1 -0
- package/dist/rules/owasp-a08/unsafe-eval.d.ts +3 -0
- package/dist/rules/owasp-a08/unsafe-eval.d.ts.map +1 -0
- package/dist/rules/owasp-a08/unsafe-eval.js +73 -0
- package/dist/rules/owasp-a08/unsafe-eval.js.map +1 -0
- package/dist/rules/owasp-a09/log-sensitive-data.d.ts +3 -0
- package/dist/rules/owasp-a09/log-sensitive-data.d.ts.map +1 -0
- package/dist/rules/owasp-a09/log-sensitive-data.js +73 -0
- package/dist/rules/owasp-a09/log-sensitive-data.js.map +1 -0
- package/dist/rules/owasp-a09/missing-error-handling.d.ts +3 -0
- package/dist/rules/owasp-a09/missing-error-handling.d.ts.map +1 -0
- package/dist/rules/owasp-a09/missing-error-handling.js +84 -0
- package/dist/rules/owasp-a09/missing-error-handling.js.map +1 -0
- package/dist/rules/owasp-a10/open-redirect.d.ts +3 -0
- package/dist/rules/owasp-a10/open-redirect.d.ts.map +1 -0
- package/dist/rules/owasp-a10/open-redirect.js +67 -0
- package/dist/rules/owasp-a10/open-redirect.js.map +1 -0
- package/dist/rules/owasp-a10/unvalidated-fetch.d.ts +3 -0
- package/dist/rules/owasp-a10/unvalidated-fetch.d.ts.map +1 -0
- package/dist/rules/owasp-a10/unvalidated-fetch.js +85 -0
- package/dist/rules/owasp-a10/unvalidated-fetch.js.map +1 -0
- package/dist/rules/registry.d.ts +20 -0
- package/dist/rules/registry.d.ts.map +1 -0
- package/dist/rules/registry.js +142 -0
- package/dist/rules/registry.js.map +1 -0
- package/dist/scanner/engine.d.ts +21 -0
- package/dist/scanner/engine.d.ts.map +1 -0
- package/dist/scanner/engine.js +260 -0
- package/dist/scanner/engine.js.map +1 -0
- package/dist/scanner/file-walker.d.ts +7 -0
- package/dist/scanner/file-walker.d.ts.map +1 -0
- package/dist/scanner/file-walker.js +81 -0
- package/dist/scanner/file-walker.js.map +1 -0
- package/dist/scanner/language-detect.d.ts +5 -0
- package/dist/scanner/language-detect.d.ts.map +1 -0
- package/dist/scanner/language-detect.js +91 -0
- package/dist/scanner/language-detect.js.map +1 -0
- package/dist/scanner/sca-scanner.d.ts +38 -0
- package/dist/scanner/sca-scanner.d.ts.map +1 -0
- package/dist/scanner/sca-scanner.js +223 -0
- package/dist/scanner/sca-scanner.js.map +1 -0
- package/dist/types/index.d.ts +114 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +25 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/pattern-matcher.d.ts +4 -0
- package/dist/utils/pattern-matcher.d.ts.map +1 -0
- package/dist/utils/pattern-matcher.js +72 -0
- package/dist/utils/pattern-matcher.js.map +1 -0
- package/dist/utils/scoring.d.ts +8 -0
- package/dist/utils/scoring.d.ts.map +1 -0
- package/dist/utils/scoring.js +76 -0
- package/dist/utils/scoring.js.map +1 -0
- package/dist/utils/suppression.d.ts +3 -0
- package/dist/utils/suppression.d.ts.map +1 -0
- package/dist/utils/suppression.js +33 -0
- package/dist/utils/suppression.js.map +1 -0
- package/package.json +94 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// OWASP A05:2021 — Security Misconfiguration
|
|
2
|
+
// Rule: Default or empty credentials in configuration
|
|
3
|
+
export const DefaultCredentials = {
|
|
4
|
+
id: 'OWASP-A05-004',
|
|
5
|
+
name: 'Default or Empty Credentials in Configuration',
|
|
6
|
+
owasp: 'A05:2021',
|
|
7
|
+
cwe: 'CWE-1392',
|
|
8
|
+
severity: 'CRITICAL',
|
|
9
|
+
languages: ['all'],
|
|
10
|
+
description: 'Default, empty, or well-known credentials (admin/admin, root/root, postgres/postgres) ' +
|
|
11
|
+
'hardcoded in database connections, admin panels, or service configurations. ' +
|
|
12
|
+
'Attackers actively scan for default credentials on exposed services.',
|
|
13
|
+
patterns: [
|
|
14
|
+
{
|
|
15
|
+
// Database URLs with common default credentials
|
|
16
|
+
pattern: /(?:mongodb|postgres|postgresql|mysql|redis|mariadb):\/\/(?:root|admin|postgres|sa|user|test|guest|default)(?::(?:root|admin|password|123456|password123|admin123|test|guest|''|""))?@/gi,
|
|
17
|
+
suppressIf: /(?:process\.env|os\.environ|getenv|\$\{|%\()/i,
|
|
18
|
+
snippetLines: 1,
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
// Explicit default password assignments
|
|
22
|
+
pattern: /(?:password|passwd|pwd)\s*[:=]\s*['"`](?:admin|password|123456|root|test|guest|default|changeme|letmein|qwerty|abc123|welcome|monkey|password123)['"`]/gi,
|
|
23
|
+
snippetLines: 1,
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
// Empty password
|
|
27
|
+
pattern: /(?:password|passwd|pwd)\s*[:=]\s*['"`]{2}/g,
|
|
28
|
+
requiresContext: /(?:db|database|mongo|postgres|mysql|redis|connect|auth|login)/i,
|
|
29
|
+
snippetLines: 3,
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
// JWT secret set to weak value
|
|
33
|
+
pattern: /(?:jwt[_-]?secret|secret[_-]?key|signing[_-]?secret)\s*[:=]\s*['"`](?:secret|mysecret|jwt_secret|your[_-]?secret|changeme|development|test|123456|password)[a-z0-9_]*['"`]/gi,
|
|
34
|
+
snippetLines: 1,
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
fix: 'Never use default, empty, or weak credentials. Generate strong random values for secrets.\n\n' +
|
|
38
|
+
'// BAD:\n' +
|
|
39
|
+
'const client = new MongoClient("mongodb://admin:password@localhost:27017");\n\n' +
|
|
40
|
+
'// GOOD:\n' +
|
|
41
|
+
'const client = new MongoClient(process.env.MONGODB_URI!);\n\n' +
|
|
42
|
+
'// Generate a strong JWT secret (run once, store in secrets manager):\n' +
|
|
43
|
+
'// node -e "console.log(require(\'crypto\').randomBytes(64).toString(\'hex\'))"\n\n' +
|
|
44
|
+
'// Store in .env (never commit to git):\n' +
|
|
45
|
+
'JWT_SECRET=<generated-64-byte-hex-value>',
|
|
46
|
+
references: [
|
|
47
|
+
'https://owasp.org/Top10/A05_2021-Security_Misconfiguration/',
|
|
48
|
+
'https://cwe.mitre.org/data/definitions/1392.html',
|
|
49
|
+
],
|
|
50
|
+
tags: ['misconfiguration', 'default-credentials', 'credentials', 'secrets'],
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=default-credentials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"default-credentials.js","sourceRoot":"","sources":["../../../src/rules/owasp-a05/default-credentials.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,sDAAsD;AAItD,MAAM,CAAC,MAAM,kBAAkB,GAAS;IACtC,EAAE,EAAE,eAAe;IACnB,IAAI,EAAE,+CAA+C;IACrD,KAAK,EAAE,UAAU;IACjB,GAAG,EAAE,UAAU;IACf,QAAQ,EAAE,UAAU;IACpB,SAAS,EAAE,CAAC,KAAK,CAAC;IAClB,WAAW,EACT,wFAAwF;QACxF,8EAA8E;QAC9E,sEAAsE;IACxE,QAAQ,EAAE;QACR;YACE,gDAAgD;YAChD,OAAO,EACL,yLAAyL;YAC3L,UAAU,EAAE,+CAA+C;YAC3D,YAAY,EAAE,CAAC;SAChB;QACD;YACE,wCAAwC;YACxC,OAAO,EACL,0JAA0J;YAC5J,YAAY,EAAE,CAAC;SAChB;QACD;YACE,iBAAiB;YACjB,OAAO,EACL,4CAA4C;YAC9C,eAAe,EAAE,gEAAgE;YACjF,YAAY,EAAE,CAAC;SAChB;QACD;YACE,+BAA+B;YAC/B,OAAO,EACL,8KAA8K;YAChL,YAAY,EAAE,CAAC;SAChB;KACF;IACD,GAAG,EACD,+FAA+F;QAC/F,WAAW;QACX,iFAAiF;QACjF,YAAY;QACZ,+DAA+D;QAC/D,yEAAyE;QACzE,qFAAqF;QACrF,2CAA2C;QAC3C,0CAA0C;IAC5C,UAAU,EAAE;QACV,6DAA6D;QAC7D,kDAAkD;KACnD;IACD,IAAI,EAAE,CAAC,kBAAkB,EAAE,qBAAqB,EAAE,aAAa,EAAE,SAAS,CAAC;CAC5E,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-disclosure.d.ts","sourceRoot":"","sources":["../../../src/rules/owasp-a05/error-disclosure.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAEjD,eAAO,MAAM,eAAe,EAAE,IAyE7B,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// OWASP A05:2021 — Security Misconfiguration
|
|
2
|
+
// Rule: Verbose error messages exposing internal details to clients
|
|
3
|
+
export const ErrorDisclosure = {
|
|
4
|
+
id: 'OWASP-A05-003',
|
|
5
|
+
name: 'Sensitive Information in Error Responses',
|
|
6
|
+
owasp: 'A05:2021',
|
|
7
|
+
cwe: 'CWE-209',
|
|
8
|
+
severity: 'MEDIUM',
|
|
9
|
+
languages: ['javascript', 'typescript', 'python', 'php', 'java', 'ruby'],
|
|
10
|
+
description: 'Error handlers sending stack traces, internal paths, database errors, or system details ' +
|
|
11
|
+
'to HTTP clients. This gives attackers a blueprint of your application stack — framework ' +
|
|
12
|
+
'versions, file paths, database schema. AI error handlers routinely send err.message or err.stack.',
|
|
13
|
+
patterns: [
|
|
14
|
+
{
|
|
15
|
+
// res.json / res.send with error.stack
|
|
16
|
+
pattern: /res\s*\.\s*(?:send|json|status\s*\([^)]+\)\s*\.\s*(?:send|json))\s*\([^)]*(?:err|error|e)\s*\.\s*stack/gi,
|
|
17
|
+
snippetLines: 3,
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
// res.json with full error object (may include stack)
|
|
21
|
+
pattern: /res\s*\.\s*(?:send|json)\s*\(\s*\{\s*(?:error|err|message|details)\s*:\s*(?:err|error|e)\s*\}/gi,
|
|
22
|
+
snippetLines: 3,
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
// PHP: print_r($e) or var_dump($e) to output
|
|
26
|
+
pattern: /(?:print_r|var_dump)\s*\(\s*\$(?:e|err|error|exception)\s*\)/gi,
|
|
27
|
+
snippetLines: 3,
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
// Python: traceback.print_exc() or traceback.format_exc() sent to response
|
|
31
|
+
pattern: /(?:traceback\.print_exc|traceback\.format_exc)\s*\(/gi,
|
|
32
|
+
requiresContext: /(?:return|response|render|jsonify|make_response)/i,
|
|
33
|
+
snippetLines: 5,
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
// Java: e.printStackTrace() — prints to stdout/response
|
|
37
|
+
pattern: /(?:e|ex|err|error|exception)\s*\.\s*printStackTrace\s*\(\s*\)/gi,
|
|
38
|
+
snippetLines: 3,
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
// Generic: sending exception message to client in JSON
|
|
42
|
+
pattern: /(?:message|error|detail)\s*:\s*(?:err|error|e|exception)\s*\.\s*message/gi,
|
|
43
|
+
requiresContext: /(?:res\.|response\.|return.*json|render.*json|send\()/i,
|
|
44
|
+
snippetLines: 5,
|
|
45
|
+
},
|
|
46
|
+
],
|
|
47
|
+
fix: 'Log errors server-side and return generic error messages to clients.\n\n' +
|
|
48
|
+
'// Express centralized error handler:\n' +
|
|
49
|
+
'app.use((err: Error, req: Request, res: Response, next: NextFunction) => {\n' +
|
|
50
|
+
' // Log full error internally (with request context)\n' +
|
|
51
|
+
' logger.error({ err, path: req.path, method: req.method }, "Request error");\n\n' +
|
|
52
|
+
' // Return generic message to client — no internals\n' +
|
|
53
|
+
' res.status(500).json({\n' +
|
|
54
|
+
' error: "An unexpected error occurred.",\n' +
|
|
55
|
+
' requestId: req.id, // correlate with server logs\n' +
|
|
56
|
+
' });\n' +
|
|
57
|
+
'});\n\n' +
|
|
58
|
+
'// Python/FastAPI:\n' +
|
|
59
|
+
'@app.exception_handler(Exception)\n' +
|
|
60
|
+
'async def generic_exception_handler(request, exc):\n' +
|
|
61
|
+
' logger.exception("Unhandled error")\n' +
|
|
62
|
+
' return JSONResponse(status_code=500, content={"error": "Internal server error"})',
|
|
63
|
+
references: [
|
|
64
|
+
'https://owasp.org/Top10/A05_2021-Security_Misconfiguration/',
|
|
65
|
+
'https://cwe.mitre.org/data/definitions/209.html',
|
|
66
|
+
'https://cheatsheetseries.owasp.org/cheatsheets/Error_Handling_Cheat_Sheet.html',
|
|
67
|
+
],
|
|
68
|
+
tags: ['error-disclosure', 'information-disclosure', 'misconfiguration', 'stack-trace'],
|
|
69
|
+
};
|
|
70
|
+
//# sourceMappingURL=error-disclosure.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-disclosure.js","sourceRoot":"","sources":["../../../src/rules/owasp-a05/error-disclosure.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,oEAAoE;AAIpE,MAAM,CAAC,MAAM,eAAe,GAAS;IACnC,EAAE,EAAE,eAAe;IACnB,IAAI,EAAE,0CAA0C;IAChD,KAAK,EAAE,UAAU;IACjB,GAAG,EAAE,SAAS;IACd,QAAQ,EAAE,QAAQ;IAClB,SAAS,EAAE,CAAC,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC;IACxE,WAAW,EACT,0FAA0F;QAC1F,0FAA0F;QAC1F,mGAAmG;IACrG,QAAQ,EAAE;QACR;YACE,uCAAuC;YACvC,OAAO,EACL,0GAA0G;YAC5G,YAAY,EAAE,CAAC;SAChB;QACD;YACE,sDAAsD;YACtD,OAAO,EACL,iGAAiG;YACnG,YAAY,EAAE,CAAC;SAChB;QACD;YACE,6CAA6C;YAC7C,OAAO,EACL,gEAAgE;YAClE,YAAY,EAAE,CAAC;SAChB;QACD;YACE,2EAA2E;YAC3E,OAAO,EACL,uDAAuD;YACzD,eAAe,EAAE,mDAAmD;YACpE,YAAY,EAAE,CAAC;SAChB;QACD;YACE,wDAAwD;YACxD,OAAO,EAAE,iEAAiE;YAC1E,YAAY,EAAE,CAAC;SAChB;QACD;YACE,uDAAuD;YACvD,OAAO,EACL,2EAA2E;YAC7E,eAAe,EAAE,wDAAwD;YACzE,YAAY,EAAE,CAAC;SAChB;KACF;IACD,GAAG,EACD,0EAA0E;QAC1E,yCAAyC;QACzC,8EAA8E;QAC9E,yDAAyD;QACzD,mFAAmF;QACnF,wDAAwD;QACxD,4BAA4B;QAC5B,+CAA+C;QAC/C,wDAAwD;QACxD,SAAS;QACT,SAAS;QACT,sBAAsB;QACtB,qCAAqC;QACrC,sDAAsD;QACtD,2CAA2C;QAC3C,sFAAsF;IACxF,UAAU,EAAE;QACV,6DAA6D;QAC7D,iDAAiD;QACjD,gFAAgF;KACjF;IACD,IAAI,EAAE,CAAC,kBAAkB,EAAE,wBAAwB,EAAE,kBAAkB,EAAE,aAAa,CAAC;CACxF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outdated-packages.d.ts","sourceRoot":"","sources":["../../../src/rules/owasp-a06/outdated-packages.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAEjD,eAAO,MAAM,gBAAgB,EAAE,IA0E9B,CAAC"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// OWASP A06:2021 — Vulnerable and Outdated Components
|
|
2
|
+
// Rule: Detects use of packages known to have severe vulnerabilities in common versions
|
|
3
|
+
export const OutdatedPackages = {
|
|
4
|
+
id: 'OWASP-A06-001',
|
|
5
|
+
name: 'Known Vulnerable Package or Deprecated API Usage',
|
|
6
|
+
owasp: 'A06:2021',
|
|
7
|
+
cwe: 'CWE-1104',
|
|
8
|
+
severity: 'HIGH',
|
|
9
|
+
languages: ['javascript', 'typescript', 'python'],
|
|
10
|
+
description: 'Usage of packages with well-known critical CVEs, or deprecated APIs that have ' +
|
|
11
|
+
'been superseded by secure alternatives. AI tools often suggest packages they were ' +
|
|
12
|
+
'trained on regardless of their current CVE status.',
|
|
13
|
+
patterns: [
|
|
14
|
+
{
|
|
15
|
+
// Node.js: require('eval') or similar dangerous packages
|
|
16
|
+
pattern: /(?:require|import)\s*\(\s*['"`]eval['"`]\s*\)/gi,
|
|
17
|
+
snippetLines: 1,
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
// node-serialize (RCE CVE-2017-5941)
|
|
21
|
+
pattern: /(?:require|import)\s*\(\s*['"`]node-serialize['"`]\s*\)/gi,
|
|
22
|
+
snippetLines: 1,
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
// js-yaml < 4 safeLoad was removed; yaml.load() without schema is dangerous
|
|
26
|
+
pattern: /yaml\s*\.\s*load\s*\(/gi,
|
|
27
|
+
suppressIf: /(?:yaml\.load\s*\([^,)]+,\s*\{[^}]*schema\s*:|yaml\.safeLoad|js-yaml.*4\.|FAILSAFE_SCHEMA|JSON_SCHEMA|DEFAULT_SAFE_SCHEMA)/i,
|
|
28
|
+
snippetLines: 3,
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
// Python pickle: deserialization of untrusted data
|
|
32
|
+
pattern: /pickle\s*\.\s*(?:loads|load)\s*\(/gi,
|
|
33
|
+
requiresContext: /(?:request\.|req\.|socket\.|recv\.|read\(|body|data|input)/i,
|
|
34
|
+
snippetLines: 3,
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
// Python PyYAML: yaml.load without Loader — executes arbitrary Python
|
|
38
|
+
pattern: /yaml\s*\.\s*load\s*\(\s*(?!.*Loader\s*=\s*yaml\.(?:Safe|Base|Full)?Loader)/gi,
|
|
39
|
+
snippetLines: 3,
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
// xmlrpc in Python — known security issues with untrusted servers
|
|
43
|
+
pattern: /import\s+xmlrpc/gi,
|
|
44
|
+
requiresContext: /(?:request\.|external|untrusted|user)/i,
|
|
45
|
+
snippetLines: 3,
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
// lodash < 4.17.21 prototype pollution: _.merge/_.set with user input
|
|
49
|
+
pattern: /_\s*\.\s*(?:merge|set|setWith|zipObjectDeep)\s*\([^)]*(?:req\.|request\.)(?:body|params|query)/gi,
|
|
50
|
+
snippetLines: 3,
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
fix: 'Run dependency audits regularly and update vulnerable packages.\n\n' +
|
|
54
|
+
'# Audit commands:\n' +
|
|
55
|
+
'npm audit # Node.js\n' +
|
|
56
|
+
'npm audit fix # Auto-fix where possible\n' +
|
|
57
|
+
'pip install pip-audit && pip-audit # Python\n' +
|
|
58
|
+
'bundle audit # Ruby\n\n' +
|
|
59
|
+
'# CI integration — fail on high/critical:\n' +
|
|
60
|
+
'npm audit --audit-level=high\n\n' +
|
|
61
|
+
'# YAML (Python) — always specify safe Loader:\n' +
|
|
62
|
+
'yaml.safe_load(stream) # instead of yaml.load()\n' +
|
|
63
|
+
'# or:\n' +
|
|
64
|
+
'yaml.load(stream, Loader=yaml.SafeLoader)\n\n' +
|
|
65
|
+
'# js-yaml (Node) — use safeLoad or load with schema:\n' +
|
|
66
|
+
'import YAML from "js-yaml";\n' +
|
|
67
|
+
'const data = YAML.load(input, { schema: YAML.FAILSAFE_SCHEMA });',
|
|
68
|
+
references: [
|
|
69
|
+
'https://owasp.org/Top10/A06_2021-Vulnerable_and_Outdated_Components/',
|
|
70
|
+
'https://cwe.mitre.org/data/definitions/1104.html',
|
|
71
|
+
'https://nvd.nist.gov/vuln/search',
|
|
72
|
+
],
|
|
73
|
+
tags: ['dependencies', 'vulnerable-components', 'supply-chain', 'cve'],
|
|
74
|
+
};
|
|
75
|
+
//# sourceMappingURL=outdated-packages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outdated-packages.js","sourceRoot":"","sources":["../../../src/rules/owasp-a06/outdated-packages.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,wFAAwF;AAIxF,MAAM,CAAC,MAAM,gBAAgB,GAAS;IACpC,EAAE,EAAE,eAAe;IACnB,IAAI,EAAE,kDAAkD;IACxD,KAAK,EAAE,UAAU;IACjB,GAAG,EAAE,UAAU;IACf,QAAQ,EAAE,MAAM;IAChB,SAAS,EAAE,CAAC,YAAY,EAAE,YAAY,EAAE,QAAQ,CAAC;IACjD,WAAW,EACT,gFAAgF;QAChF,oFAAoF;QACpF,oDAAoD;IACtD,QAAQ,EAAE;QACR;YACE,yDAAyD;YACzD,OAAO,EAAE,iDAAiD;YAC1D,YAAY,EAAE,CAAC;SAChB;QACD;YACE,qCAAqC;YACrC,OAAO,EAAE,2DAA2D;YACpE,YAAY,EAAE,CAAC;SAChB;QACD;YACE,4EAA4E;YAC5E,OAAO,EAAE,yBAAyB;YAClC,UAAU,EAAE,6HAA6H;YACzI,YAAY,EAAE,CAAC;SAChB;QACD;YACE,mDAAmD;YACnD,OAAO,EAAE,qCAAqC;YAC9C,eAAe,EAAE,6DAA6D;YAC9E,YAAY,EAAE,CAAC;SAChB;QACD;YACE,sEAAsE;YACtE,OAAO,EAAE,8EAA8E;YACvF,YAAY,EAAE,CAAC;SAChB;QACD;YACE,kEAAkE;YAClE,OAAO,EAAE,mBAAmB;YAC5B,eAAe,EAAE,wCAAwC;YACzD,YAAY,EAAE,CAAC;SAChB;QACD;YACE,sEAAsE;YACtE,OAAO,EACL,kGAAkG;YACpG,YAAY,EAAE,CAAC;SAChB;KACF;IACD,GAAG,EACD,qEAAqE;QACrE,qBAAqB;QACrB,0CAA0C;QAC1C,0DAA0D;QAC1D,gDAAgD;QAChD,yCAAyC;QACzC,6CAA6C;QAC7C,kCAAkC;QAClC,iDAAiD;QACjD,oDAAoD;QACpD,SAAS;QACT,+CAA+C;QAC/C,wDAAwD;QACxD,+BAA+B;QAC/B,kEAAkE;IACpE,UAAU,EAAE;QACV,sEAAsE;QACtE,kDAAkD;QAClD,kCAAkC;KACnC;IACD,IAAI,EAAE,CAAC,cAAc,EAAE,uBAAuB,EAAE,cAAc,EAAE,KAAK,CAAC;CACvE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"insecure-cookies.d.ts","sourceRoot":"","sources":["../../../src/rules/owasp-a07/insecure-cookies.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAEjD,eAAO,MAAM,eAAe,EAAE,IAiE7B,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// OWASP A07:2021 — Identification and Authentication Failures
|
|
2
|
+
// Rule: Cookies set without HttpOnly, Secure, or SameSite flags
|
|
3
|
+
export const InsecureCookies = {
|
|
4
|
+
id: 'OWASP-A07-004',
|
|
5
|
+
name: 'Insecure Cookie Attributes (Missing HttpOnly/Secure/SameSite)',
|
|
6
|
+
owasp: 'A07:2021',
|
|
7
|
+
cwe: 'CWE-614',
|
|
8
|
+
severity: 'MEDIUM',
|
|
9
|
+
languages: ['javascript', 'typescript', 'python', 'php', 'ruby'],
|
|
10
|
+
description: 'Session cookies or authentication cookies set without HttpOnly (accessible to JS), ' +
|
|
11
|
+
'Secure (sent over HTTP), or SameSite (CSRF vulnerable) flags. ' +
|
|
12
|
+
'AI tools routinely generate res.cookie("token", value) without security attributes.',
|
|
13
|
+
patterns: [
|
|
14
|
+
{
|
|
15
|
+
// Express: res.cookie without httpOnly
|
|
16
|
+
pattern: /res\s*\.\s*cookie\s*\(\s*['"`][^'"`]+['"`]\s*,\s*[^,)]+\s*(?:,\s*\{\s*(?![^}]*httpOnly\s*:\s*true)[^}]*\}|)\s*\)/gi,
|
|
17
|
+
suppressIf: /(?:httpOnly\s*:\s*true|secure\s*:\s*true)/i,
|
|
18
|
+
snippetLines: 3,
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
// PHP: setcookie without secure/httponly flags
|
|
22
|
+
pattern: /setcookie\s*\(\s*[^,]+,\s*[^,]+,\s*[^,)]+\s*\)/gi,
|
|
23
|
+
suppressIf: /(?:true\s*,\s*true|httponly|samesite)/i,
|
|
24
|
+
snippetLines: 3,
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
// Python: set_cookie without httponly/secure
|
|
28
|
+
pattern: /(?:response|resp)\s*\.\s*set_cookie\s*\([^)]*(?!httponly\s*=\s*True|secure\s*=\s*True)[^)]*\)/gi,
|
|
29
|
+
suppressIf: /(?:httponly\s*=\s*True|secure\s*=\s*True)/i,
|
|
30
|
+
snippetLines: 3,
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
// Explicit insecure=true in cookie options
|
|
34
|
+
pattern: /(?:secure\s*:\s*false|httpOnly\s*:\s*false)/gi,
|
|
35
|
+
requiresContext: /(?:cookie|session|token|auth)/i,
|
|
36
|
+
snippetLines: 3,
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
fix: 'Set security attributes on all authentication and session cookies.\n\n' +
|
|
40
|
+
'// Express:\n' +
|
|
41
|
+
'res.cookie("session_token", token, {\n' +
|
|
42
|
+
' httpOnly: true, // prevent JavaScript access (XSS protection)\n' +
|
|
43
|
+
' secure: true, // HTTPS only (never send over HTTP)\n' +
|
|
44
|
+
' sameSite: "strict", // CSRF protection\n' +
|
|
45
|
+
' maxAge: 3600000, // 1 hour expiry\n' +
|
|
46
|
+
' path: "/",\n' +
|
|
47
|
+
'});\n\n' +
|
|
48
|
+
'// Python / Flask:\n' +
|
|
49
|
+
'response.set_cookie(\n' +
|
|
50
|
+
' "session_token",\n' +
|
|
51
|
+
' token,\n' +
|
|
52
|
+
' httponly=True,\n' +
|
|
53
|
+
' secure=True,\n' +
|
|
54
|
+
' samesite="Strict",\n' +
|
|
55
|
+
' max_age=3600,\n' +
|
|
56
|
+
')',
|
|
57
|
+
references: [
|
|
58
|
+
'https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures/',
|
|
59
|
+
'https://cwe.mitre.org/data/definitions/614.html',
|
|
60
|
+
'https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html',
|
|
61
|
+
],
|
|
62
|
+
tags: ['cookies', 'session', 'authentication', 'xss', 'csrf'],
|
|
63
|
+
};
|
|
64
|
+
//# sourceMappingURL=insecure-cookies.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"insecure-cookies.js","sourceRoot":"","sources":["../../../src/rules/owasp-a07/insecure-cookies.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,gEAAgE;AAIhE,MAAM,CAAC,MAAM,eAAe,GAAS;IACnC,EAAE,EAAE,eAAe;IACnB,IAAI,EAAE,+DAA+D;IACrE,KAAK,EAAE,UAAU;IACjB,GAAG,EAAE,SAAS;IACd,QAAQ,EAAE,QAAQ;IAClB,SAAS,EAAE,CAAC,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC;IAChE,WAAW,EACT,qFAAqF;QACrF,gEAAgE;QAChE,qFAAqF;IACvF,QAAQ,EAAE;QACR;YACE,uCAAuC;YACvC,OAAO,EACL,oHAAoH;YACtH,UAAU,EAAE,4CAA4C;YACxD,YAAY,EAAE,CAAC;SAChB;QACD;YACE,+CAA+C;YAC/C,OAAO,EACL,kDAAkD;YACpD,UAAU,EAAE,wCAAwC;YACpD,YAAY,EAAE,CAAC;SAChB;QACD;YACE,6CAA6C;YAC7C,OAAO,EACL,iGAAiG;YACnG,UAAU,EAAE,4CAA4C;YACxD,YAAY,EAAE,CAAC;SAChB;QACD;YACE,2CAA2C;YAC3C,OAAO,EAAE,+CAA+C;YACxD,eAAe,EAAE,gCAAgC;YACjD,YAAY,EAAE,CAAC;SAChB;KACF;IACD,GAAG,EACD,wEAAwE;QACxE,eAAe;QACf,wCAAwC;QACxC,qEAAqE;QACrE,4DAA4D;QAC5D,4CAA4C;QAC5C,wCAAwC;QACxC,gBAAgB;QAChB,SAAS;QACT,sBAAsB;QACtB,wBAAwB;QACxB,wBAAwB;QACxB,cAAc;QACd,sBAAsB;QACtB,oBAAoB;QACpB,0BAA0B;QAC1B,qBAAqB;QACrB,GAAG;IACL,UAAU,EAAE;QACV,8EAA8E;QAC9E,iDAAiD;QACjD,oFAAoF;KACrF;IACD,IAAI,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,CAAC;CAC9D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwt-none-alg.d.ts","sourceRoot":"","sources":["../../../src/rules/owasp-a07/jwt-none-alg.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAEjD,eAAO,MAAM,gBAAgB,EAAE,IAsF9B,CAAC"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// OWASP A07:2021 — Identification and Authentication Failures
|
|
2
|
+
// Rule: JWT "none" algorithm vulnerability or insecure JWT configuration
|
|
3
|
+
export const JwtNoneAlgorithm = {
|
|
4
|
+
id: 'OWASP-A07-001',
|
|
5
|
+
name: 'JWT None Algorithm or Insecure JWT Configuration',
|
|
6
|
+
owasp: 'A07:2021',
|
|
7
|
+
cwe: 'CWE-347',
|
|
8
|
+
severity: 'CRITICAL',
|
|
9
|
+
languages: ['javascript', 'typescript', 'python', 'java', 'ruby', 'go'],
|
|
10
|
+
description: 'JWT libraries that accept the "none" algorithm (no signature) allow attackers to ' +
|
|
11
|
+
'forge tokens with any claims they want — bypassing authentication entirely. ' +
|
|
12
|
+
'Also detects JWTs verified without algorithm pinning (susceptible to algorithm confusion attacks).',
|
|
13
|
+
patterns: [
|
|
14
|
+
{
|
|
15
|
+
// jwt.sign/verify with algorithm: 'none'
|
|
16
|
+
pattern: /jwt\s*\.\s*(?:sign|verify|decode)\s*\([^)]*algorithm\s*s?\s*:\s*['"`]none['"`]/gi,
|
|
17
|
+
snippetLines: 3,
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
// jwt.verify without algorithms option (any algorithm accepted)
|
|
21
|
+
pattern: /jwt\s*\.\s*verify\s*\(\s*\w+\s*,\s*\w+\s*\)/g,
|
|
22
|
+
suppressIf: /(?:algorithms\s*:|algorithm\s*:)/i,
|
|
23
|
+
snippetLines: 3,
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
// jsonwebtoken: algorithms not specified in verify options
|
|
27
|
+
pattern: /(?:jsonwebtoken|jwt)\s*\.\s*verify\s*\(\s*[^,]+,\s*[^,{)]+\s*(?:,\s*(?!\{))?\s*\)/gi,
|
|
28
|
+
suppressIf: /(?:algorithms|algorithm)/i,
|
|
29
|
+
snippetLines: 3,
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
// PyJWT: decode without algorithms list
|
|
33
|
+
pattern: /jwt\s*\.\s*decode\s*\(\s*[^,]+,\s*[^,)]+\s*(?:,\s*(?!\{))?\s*\)/gi,
|
|
34
|
+
suppressIf: /algorithms\s*=/i,
|
|
35
|
+
snippetLines: 3,
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
// Python: algorithms=["none"] or verify=False
|
|
39
|
+
pattern: /(?:algorithms\s*=\s*\[\s*['"`]none['"`]|options\s*=\s*\{[^}]*['"`]verify[^}]*:\s*False)/gi,
|
|
40
|
+
snippetLines: 3,
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
// Weak JWT secret (too short)
|
|
44
|
+
pattern: /jwt\s*\.\s*sign\s*\([^,]+,\s*['"`][a-zA-Z0-9]{1,15}['"`]/gi,
|
|
45
|
+
snippetLines: 3,
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
// Missing expiry (no expiresIn)
|
|
49
|
+
pattern: /jwt\s*\.\s*sign\s*\(\s*\{[^}]+\}\s*,\s*[^,{)]+\s*\)/g,
|
|
50
|
+
suppressIf: /(?:expiresIn|exp\s*:|expires_in)/i,
|
|
51
|
+
snippetLines: 3,
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
fix: 'Always pin the expected algorithm and verify token expiry.\n\n' +
|
|
55
|
+
'// Node.js — jsonwebtoken:\n' +
|
|
56
|
+
'import jwt from "jsonwebtoken";\n\n' +
|
|
57
|
+
'// Signing:\n' +
|
|
58
|
+
'const token = jwt.sign(\n' +
|
|
59
|
+
' { userId: user.id, role: user.role },\n' +
|
|
60
|
+
' process.env.JWT_SECRET!,\n' +
|
|
61
|
+
' { algorithm: "HS256", expiresIn: "15m" } // short expiry\n' +
|
|
62
|
+
');\n\n' +
|
|
63
|
+
'// Verifying — MUST specify algorithms:\n' +
|
|
64
|
+
'const payload = jwt.verify(token, process.env.JWT_SECRET!, {\n' +
|
|
65
|
+
' algorithms: ["HS256"], // reject any other algorithm including "none"\n' +
|
|
66
|
+
'});\n\n' +
|
|
67
|
+
'// Python — PyJWT:\n' +
|
|
68
|
+
'payload = jwt.decode(\n' +
|
|
69
|
+
' token,\n' +
|
|
70
|
+
' secret,\n' +
|
|
71
|
+
' algorithms=["HS256"], # must specify allowed algorithms\n' +
|
|
72
|
+
')',
|
|
73
|
+
references: [
|
|
74
|
+
'https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures/',
|
|
75
|
+
'https://cwe.mitre.org/data/definitions/347.html',
|
|
76
|
+
'https://portswigger.net/web-security/jwt',
|
|
77
|
+
'https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/',
|
|
78
|
+
],
|
|
79
|
+
tags: ['jwt', 'authentication', 'auth', 'token', 'cryptography'],
|
|
80
|
+
};
|
|
81
|
+
//# sourceMappingURL=jwt-none-alg.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwt-none-alg.js","sourceRoot":"","sources":["../../../src/rules/owasp-a07/jwt-none-alg.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,yEAAyE;AAIzE,MAAM,CAAC,MAAM,gBAAgB,GAAS;IACpC,EAAE,EAAE,eAAe;IACnB,IAAI,EAAE,kDAAkD;IACxD,KAAK,EAAE,UAAU;IACjB,GAAG,EAAE,SAAS;IACd,QAAQ,EAAE,UAAU;IACpB,SAAS,EAAE,CAAC,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC;IACvE,WAAW,EACT,mFAAmF;QACnF,8EAA8E;QAC9E,oGAAoG;IACtG,QAAQ,EAAE;QACR;YACE,yCAAyC;YACzC,OAAO,EACL,kFAAkF;YACpF,YAAY,EAAE,CAAC;SAChB;QACD;YACE,gEAAgE;YAChE,OAAO,EACL,8CAA8C;YAChD,UAAU,EAAE,mCAAmC;YAC/C,YAAY,EAAE,CAAC;SAChB;QACD;YACE,2DAA2D;YAC3D,OAAO,EACL,qFAAqF;YACvF,UAAU,EAAE,2BAA2B;YACvC,YAAY,EAAE,CAAC;SAChB;QACD;YACE,wCAAwC;YACxC,OAAO,EACL,mEAAmE;YACrE,UAAU,EAAE,iBAAiB;YAC7B,YAAY,EAAE,CAAC;SAChB;QACD;YACE,8CAA8C;YAC9C,OAAO,EACL,2FAA2F;YAC7F,YAAY,EAAE,CAAC;SAChB;QACD;YACE,8BAA8B;YAC9B,OAAO,EACL,4DAA4D;YAC9D,YAAY,EAAE,CAAC;SAChB;QACD;YACE,gCAAgC;YAChC,OAAO,EACL,sDAAsD;YACxD,UAAU,EAAE,mCAAmC;YAC/C,YAAY,EAAE,CAAC;SAChB;KACF;IACD,GAAG,EACD,gEAAgE;QAChE,8BAA8B;QAC9B,qCAAqC;QACrC,eAAe;QACf,2BAA2B;QAC3B,2CAA2C;QAC3C,8BAA8B;QAC9B,8DAA8D;QAC9D,QAAQ;QACR,2CAA2C;QAC3C,gEAAgE;QAChE,2EAA2E;QAC3E,SAAS;QACT,sBAAsB;QACtB,yBAAyB;QACzB,cAAc;QACd,eAAe;QACf,gEAAgE;QAChE,GAAG;IACL,UAAU,EAAE;QACV,8EAA8E;QAC9E,iDAAiD;QACjD,0CAA0C;QAC1C,8EAA8E;KAC/E;IACD,IAAI,EAAE,CAAC,KAAK,EAAE,gBAAgB,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,CAAC;CACjE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-password-hashing.d.ts","sourceRoot":"","sources":["../../../src/rules/owasp-a07/no-password-hashing.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAEjD,eAAO,MAAM,iBAAiB,EAAE,IA0E/B,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// OWASP A07:2021 — Identification and Authentication Failures
|
|
2
|
+
// Rule: Passwords stored or compared without proper hashing
|
|
3
|
+
export const NoPasswordHashing = {
|
|
4
|
+
id: 'OWASP-A07-002',
|
|
5
|
+
name: 'Password Stored or Compared Without Secure Hashing',
|
|
6
|
+
owasp: 'A07:2021',
|
|
7
|
+
cwe: 'CWE-256',
|
|
8
|
+
severity: 'CRITICAL',
|
|
9
|
+
languages: ['javascript', 'typescript', 'python', 'php', 'java', 'ruby', 'go'],
|
|
10
|
+
description: 'Passwords stored in plaintext, or compared directly without using a constant-time ' +
|
|
11
|
+
'comparison of hashed values. A database breach immediately exposes all user passwords. ' +
|
|
12
|
+
'AI tools commonly generate password: req.body.password stored directly in DB models.',
|
|
13
|
+
patterns: [
|
|
14
|
+
{
|
|
15
|
+
// Mongoose/Sequelize: password field set directly from request without hashing
|
|
16
|
+
pattern: /password\s*:\s*req(?:uest)?\s*\.\s*body\s*\.\s*password\b/gi,
|
|
17
|
+
suppressIf: /(?:bcrypt|argon2|scrypt|pbkdf2|hash|crypto)/i,
|
|
18
|
+
snippetLines: 5,
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
// new User({ password: req.body.password })
|
|
22
|
+
pattern: /\{\s*[^}]*password\s*:\s*req(?:uest)?\s*\.\s*body\s*\.\s*password[^}]*\}/gi,
|
|
23
|
+
suppressIf: /(?:bcrypt|argon2|scrypt|pbkdf2|\.hash\s*\(|hashPassword)/i,
|
|
24
|
+
snippetLines: 5,
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
// Direct equality comparison: user.password === req.body.password
|
|
28
|
+
pattern: /(?:user|account|record)\s*\.\s*password\s*===?\s*(?:req|request)\s*\.\s*body\s*\.\s*password/gi,
|
|
29
|
+
snippetLines: 3,
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
// Python: user.password == request.form['password']
|
|
33
|
+
pattern: /(?:user|account)\s*\.\s*password\s*==\s*request\s*\.\s*(?:form|json|data|args)/gi,
|
|
34
|
+
snippetLines: 3,
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
// PHP: $user['password'] == $_POST['password'] (not password_verify)
|
|
38
|
+
pattern: /\$(?:user|row|record)\s*(?:\[['"`]password['"`]\]|->\s*password)\s*==\s*\$_(?:POST|GET|REQUEST)\s*\[['"`]password['"`]\]/gi,
|
|
39
|
+
snippetLines: 3,
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
// Java: .equals() comparison for password strings
|
|
43
|
+
pattern: /(?:password|passwd|pwd)\s*\.\s*equals\s*\(\s*(?:request|req)\.(?:getParameter|body)/gi,
|
|
44
|
+
snippetLines: 3,
|
|
45
|
+
},
|
|
46
|
+
],
|
|
47
|
+
fix: 'Use a password hashing function with a work factor (bcrypt, Argon2id, or scrypt). ' +
|
|
48
|
+
'NEVER compare passwords with == or ===.\n\n' +
|
|
49
|
+
'// Node.js registration:\n' +
|
|
50
|
+
'import bcrypt from "bcrypt";\n' +
|
|
51
|
+
'const SALT_ROUNDS = 12;\n' +
|
|
52
|
+
'const hashedPassword = await bcrypt.hash(req.body.password, SALT_ROUNDS);\n' +
|
|
53
|
+
'await User.create({ email: req.body.email, password: hashedPassword });\n\n' +
|
|
54
|
+
'// Node.js login verification:\n' +
|
|
55
|
+
'const user = await User.findOne({ email: req.body.email });\n' +
|
|
56
|
+
'if (!user) return res.status(401).json({ error: "Invalid credentials" });\n' +
|
|
57
|
+
'const valid = await bcrypt.compare(req.body.password, user.password);\n' +
|
|
58
|
+
'if (!valid) return res.status(401).json({ error: "Invalid credentials" });\n\n' +
|
|
59
|
+
'// Python:\n' +
|
|
60
|
+
'from passlib.hash import argon2\n' +
|
|
61
|
+
'hashed = argon2.hash(password) # store\n' +
|
|
62
|
+
'valid = argon2.verify(input_pwd, hashed) # verify',
|
|
63
|
+
references: [
|
|
64
|
+
'https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures/',
|
|
65
|
+
'https://cwe.mitre.org/data/definitions/256.html',
|
|
66
|
+
'https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html',
|
|
67
|
+
],
|
|
68
|
+
tags: ['password', 'hashing', 'authentication', 'plaintext', 'bcrypt'],
|
|
69
|
+
};
|
|
70
|
+
//# sourceMappingURL=no-password-hashing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-password-hashing.js","sourceRoot":"","sources":["../../../src/rules/owasp-a07/no-password-hashing.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,4DAA4D;AAI5D,MAAM,CAAC,MAAM,iBAAiB,GAAS;IACrC,EAAE,EAAE,eAAe;IACnB,IAAI,EAAE,oDAAoD;IAC1D,KAAK,EAAE,UAAU;IACjB,GAAG,EAAE,SAAS;IACd,QAAQ,EAAE,UAAU;IACpB,SAAS,EAAE,CAAC,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC;IAC9E,WAAW,EACT,oFAAoF;QACpF,yFAAyF;QACzF,sFAAsF;IACxF,QAAQ,EAAE;QACR;YACE,+EAA+E;YAC/E,OAAO,EACL,6DAA6D;YAC/D,UAAU,EAAE,8CAA8C;YAC1D,YAAY,EAAE,CAAC;SAChB;QACD;YACE,4CAA4C;YAC5C,OAAO,EACL,4EAA4E;YAC9E,UAAU,EAAE,2DAA2D;YACvE,YAAY,EAAE,CAAC;SAChB;QACD;YACE,kEAAkE;YAClE,OAAO,EACL,gGAAgG;YAClG,YAAY,EAAE,CAAC;SAChB;QACD;YACE,oDAAoD;YACpD,OAAO,EACL,kFAAkF;YACpF,YAAY,EAAE,CAAC;SAChB;QACD;YACE,qEAAqE;YACrE,OAAO,EACL,4HAA4H;YAC9H,YAAY,EAAE,CAAC;SAChB;QACD;YACE,kDAAkD;YAClD,OAAO,EACL,uFAAuF;YACzF,YAAY,EAAE,CAAC;SAChB;KACF;IACD,GAAG,EACD,oFAAoF;QACpF,6CAA6C;QAC7C,4BAA4B;QAC5B,gCAAgC;QAChC,2BAA2B;QAC3B,6EAA6E;QAC7E,6EAA6E;QAC7E,kCAAkC;QAClC,+DAA+D;QAC/D,6EAA6E;QAC7E,yEAAyE;QACzE,gFAAgF;QAChF,cAAc;QACd,mCAAmC;QACnC,mDAAmD;QACnD,mDAAmD;IACrD,UAAU,EAAE;QACV,8EAA8E;QAC9E,iDAAiD;QACjD,kFAAkF;KACnF;IACD,IAAI,EAAE,CAAC,UAAU,EAAE,SAAS,EAAE,gBAAgB,EAAE,WAAW,EAAE,QAAQ,CAAC;CACvE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"weak-session.d.ts","sourceRoot":"","sources":["../../../src/rules/owasp-a07/weak-session.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAEjD,eAAO,MAAM,iBAAiB,EAAE,IAkE/B,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// OWASP A07:2021 — Identification and Authentication Failures
|
|
2
|
+
// Rule: Insecure session configuration
|
|
3
|
+
export const WeakSessionConfig = {
|
|
4
|
+
id: 'OWASP-A07-003',
|
|
5
|
+
name: 'Insecure Session Configuration',
|
|
6
|
+
owasp: 'A07:2021',
|
|
7
|
+
cwe: 'CWE-732',
|
|
8
|
+
severity: 'HIGH',
|
|
9
|
+
languages: ['javascript', 'typescript', 'python'],
|
|
10
|
+
description: 'Session middleware configured with insecure defaults: missing secret, non-persistent ' +
|
|
11
|
+
'storage in production, or sessions not invalidated on logout. ' +
|
|
12
|
+
'AI tools often generate express-session with no secret or MemoryStore in production.',
|
|
13
|
+
patterns: [
|
|
14
|
+
{
|
|
15
|
+
// express-session with no secret or weak secret
|
|
16
|
+
pattern: /session\s*\(\s*\{\s*(?![^}]*secret\s*:)[^}]*\}\s*\)/gi,
|
|
17
|
+
snippetLines: 5,
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
// MemoryStore in production (causes memory leaks and doesn't scale)
|
|
21
|
+
pattern: /(?:store\s*:\s*new\s+MemoryStore|resave\s*:\s*true)/gi,
|
|
22
|
+
suppressIf: /(?:test|development|dev|spec)/i,
|
|
23
|
+
snippetLines: 3,
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
// Missing httpOnly or secure in session cookie
|
|
27
|
+
pattern: /cookie\s*:\s*\{\s*(?![^}]*(?:httpOnly|secure)\s*:\s*true)[^}]*\}/gi,
|
|
28
|
+
requiresContext: /(?:session|express-session|cookie-session)/i,
|
|
29
|
+
snippetLines: 5,
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
// Session secret in code (not from env)
|
|
33
|
+
pattern: /secret\s*:\s*['"`](?!.*process\.env)[a-zA-Z0-9_\-]{1,30}['"`]/gi,
|
|
34
|
+
requiresContext: /(?:session\s*\(|express-session)/i,
|
|
35
|
+
snippetLines: 5,
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
fix: 'Configure sessions with a strong secret, secure cookies, and a production-ready store.\n\n' +
|
|
39
|
+
'// Express:\n' +
|
|
40
|
+
'import session from "express-session";\n' +
|
|
41
|
+
'import RedisStore from "connect-redis";\n' +
|
|
42
|
+
'import { createClient } from "redis";\n\n' +
|
|
43
|
+
'const redisClient = createClient({ url: process.env.REDIS_URL });\n' +
|
|
44
|
+
'await redisClient.connect();\n\n' +
|
|
45
|
+
'app.use(session({\n' +
|
|
46
|
+
' secret: process.env.SESSION_SECRET!, // min 32 chars, from env\n' +
|
|
47
|
+
' resave: false,\n' +
|
|
48
|
+
' saveUninitialized: false,\n' +
|
|
49
|
+
' store: new RedisStore({ client: redisClient }), // not MemoryStore\n' +
|
|
50
|
+
' cookie: {\n' +
|
|
51
|
+
' httpOnly: true, // not accessible via JS\n' +
|
|
52
|
+
' secure: process.env.NODE_ENV === "production", // HTTPS only\n' +
|
|
53
|
+
' sameSite: "strict", // CSRF protection\n' +
|
|
54
|
+
' maxAge: 30 * 60 * 1000, // 30 minutes\n' +
|
|
55
|
+
' },\n' +
|
|
56
|
+
'}));',
|
|
57
|
+
references: [
|
|
58
|
+
'https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures/',
|
|
59
|
+
'https://cwe.mitre.org/data/definitions/732.html',
|
|
60
|
+
'https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html',
|
|
61
|
+
],
|
|
62
|
+
tags: ['session', 'authentication', 'cookies', 'configuration'],
|
|
63
|
+
};
|
|
64
|
+
//# sourceMappingURL=weak-session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"weak-session.js","sourceRoot":"","sources":["../../../src/rules/owasp-a07/weak-session.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,uCAAuC;AAIvC,MAAM,CAAC,MAAM,iBAAiB,GAAS;IACrC,EAAE,EAAE,eAAe;IACnB,IAAI,EAAE,gCAAgC;IACtC,KAAK,EAAE,UAAU;IACjB,GAAG,EAAE,SAAS;IACd,QAAQ,EAAE,MAAM;IAChB,SAAS,EAAE,CAAC,YAAY,EAAE,YAAY,EAAE,QAAQ,CAAC;IACjD,WAAW,EACT,uFAAuF;QACvF,gEAAgE;QAChE,sFAAsF;IACxF,QAAQ,EAAE;QACR;YACE,gDAAgD;YAChD,OAAO,EACL,uDAAuD;YACzD,YAAY,EAAE,CAAC;SAChB;QACD;YACE,oEAAoE;YACpE,OAAO,EACL,uDAAuD;YACzD,UAAU,EAAE,gCAAgC;YAC5C,YAAY,EAAE,CAAC;SAChB;QACD;YACE,+CAA+C;YAC/C,OAAO,EACL,oEAAoE;YACtE,eAAe,EAAE,6CAA6C;YAC9D,YAAY,EAAE,CAAC;SAChB;QACD;YACE,wCAAwC;YACxC,OAAO,EACL,iEAAiE;YACnE,eAAe,EAAE,mCAAmC;YACpD,YAAY,EAAE,CAAC;SAChB;KACF;IACD,GAAG,EACD,4FAA4F;QAC5F,eAAe;QACf,0CAA0C;QAC1C,2CAA2C;QAC3C,2CAA2C;QAC3C,qEAAqE;QACrE,kCAAkC;QAClC,qBAAqB;QACrB,oEAAoE;QACpE,oBAAoB;QACpB,+BAA+B;QAC/B,wEAAwE;QACxE,eAAe;QACf,iDAAiD;QACjD,oEAAoE;QACpE,8CAA8C;QAC9C,6CAA6C;QAC7C,QAAQ;QACR,MAAM;IACR,UAAU,EAAE;QACV,8EAA8E;QAC9E,iDAAiD;QACjD,oFAAoF;KACrF;IACD,IAAI,EAAE,CAAC,SAAS,EAAE,gBAAgB,EAAE,SAAS,EAAE,eAAe,CAAC;CAChE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unsafe-deserialization.d.ts","sourceRoot":"","sources":["../../../src/rules/owasp-a08/unsafe-deserialization.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAEjD,eAAO,MAAM,qBAAqB,EAAE,IAkFnC,CAAC"}
|