Skip to content

Commit db0d856

Browse files
haasonsaasclaude
andcommitted
feat: comprehensive security vulnerability detection across 5 areas
- Enhanced security prompt with taint-flow model covering injection, auth/authz, secrets, deserialization/SSRF/XSS/CSRF, and supply-chain - New SecretScanner pre-analyzer with 24 regex patterns and entropy checks - New SupplyChainAnalyzer pre-analyzer covering Cargo, npm, pip, Go, GHA - 43 Semgrep-style YAML rules mapped to CWE/OWASP across 5 rule files - Enhanced CommentSynthesizer with 40+ security keywords and 50+ tags - All plugins enabled by default via PluginConfig Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent d705106 commit db0d856

12 files changed

Lines changed: 2325 additions & 25 deletions

File tree

rules/security/auth.yaml

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
rules:
2+
# ── Missing Authentication ─────────────────────────────────────────
3+
- id: sec.auth.missing
4+
description: >
5+
API endpoint or route handler lacking authentication middleware/decorator.
6+
Framework patterns to check:
7+
- Express: route handler without auth middleware argument
8+
- Django: view without @login_required or LoginRequiredMixin
9+
- Rails: controller without before_action :authenticate_user!
10+
- Spring: endpoint without @PreAuthorize, @Secured, @RolesAllowed
11+
- FastAPI: handler without Depends(get_current_user)
12+
- Axum/Actix: handler without auth extractor or .layer() middleware
13+
Flag state-changing endpoints (POST/PUT/DELETE) without auth as critical.
14+
scope: "**/*.{py,js,ts,rb,go,rs,java,kt,cs,php}"
15+
severity: error
16+
category: security
17+
tags: [auth, missing-auth, owasp-a07, cwe-306]
18+
source: diffscope-builtin
19+
20+
# ── IDOR / BOLA ────────────────────────────────────────────────────
21+
- id: sec.auth.idor
22+
description: >
23+
Insecure Direct Object Reference — user-supplied ID used in database
24+
query without ownership/authorization check.
25+
Pattern: request parameter (params[:id], req.params.id, path variable)
26+
flows into Model.find(id) / query("WHERE id = ?", id) without also
27+
filtering by authenticated user (current_user, req.user, claims.sub).
28+
Safe pattern: Model.where(id: id, owner: current_user).
29+
scope: "**/*.{py,js,ts,rb,go,rs,java,kt,cs,php}"
30+
severity: error
31+
category: security
32+
tags: [auth, idor, bola, owasp-a01, cwe-639]
33+
source: diffscope-builtin
34+
35+
# ── Privilege Escalation ───────────────────────────────────────────
36+
- id: sec.auth.privilege-escalation
37+
description: >
38+
Role or permission checks using client-controlled values (cookies,
39+
headers, query params) instead of server-side session data.
40+
Also flag: mass assignment accepting role/is_admin fields from user input,
41+
skip_before_action :authenticate, .permitAll() on admin paths.
42+
scope: "**/*.{py,js,ts,rb,go,rs,java,kt,cs,php}"
43+
severity: error
44+
category: security
45+
tags: [auth, privilege-escalation, owasp-a01, cwe-269]
46+
source: diffscope-builtin
47+
48+
# ── JWT Vulnerabilities ────────────────────────────────────────────
49+
- id: sec.auth.jwt
50+
description: >
51+
JWT implementation flaws:
52+
- jwt.decode() without signature verification (verify=False, verify_signature=False)
53+
- Accepting 'none' algorithm (alg: none)
54+
- Hardcoded JWT signing secrets (string literals in sign/verify calls)
55+
- Missing expiry validation (not checking 'exp' claim)
56+
- Using jwt.decode() instead of jwt.verify() (Node.js jsonwebtoken)
57+
Safe patterns: algorithm allowlist, key from env/vault, exp validation.
58+
scope: "**/*.{py,js,ts,rb,go,rs,java,kt,cs}"
59+
severity: error
60+
category: security
61+
tags: [auth, jwt, owasp-a07, cwe-347]
62+
source: diffscope-builtin
63+
64+
# ── Weak Password Storage ──────────────────────────────────────────
65+
- id: sec.auth.weak-password-hash
66+
description: >
67+
Passwords hashed with weak or unsuitable algorithms.
68+
Vulnerable: MD5, SHA1, SHA256 (without KDF), DES, plain ROT13.
69+
Acceptable: bcrypt (cost >= 10), argon2id, scrypt, PBKDF2 (>= 600k iterations).
70+
Flag hashlib.md5/sha1/sha256 used for password storage,
71+
Digest::MD5/SHA1 for passwords, crypto.createHash('md5') for passwords.
72+
scope: "**/*.{py,js,ts,rb,go,rs,java,kt,cs,php}"
73+
severity: error
74+
category: security
75+
tags: [auth, password, weak-hash, owasp-a07, cwe-916]
76+
source: diffscope-builtin
77+
78+
# ── OAuth Misconfiguration ─────────────────────────────────────────
79+
- id: sec.auth.oauth
80+
description: >
81+
OAuth implementation flaws:
82+
- Missing state parameter in authorization URL (CSRF on login)
83+
- Open redirect in redirect_uri (not validating against allowlist)
84+
- Storing tokens in localStorage (XSS-accessible)
85+
- Not validating token audience/issuer claims
86+
scope: "**/*.{py,js,ts,rb,go,rs,java,kt,cs}"
87+
severity: warning
88+
category: security
89+
tags: [auth, oauth, owasp-a07, cwe-352]
90+
source: diffscope-builtin
91+
92+
# ── Session Management ─────────────────────────────────────────────
93+
- id: sec.auth.session
94+
description: >
95+
Session security flaws:
96+
- Missing HttpOnly flag on session cookies
97+
- Missing Secure flag on session cookies
98+
- Missing SameSite attribute (or SameSite=None without Secure)
99+
- Session not regenerated after login (session fixation)
100+
- Hardcoded session secrets
101+
scope: "**/*.{py,js,ts,rb,go,rs,java,kt,cs,php}"
102+
severity: warning
103+
category: security
104+
tags: [auth, session, cookies, owasp-a07, cwe-384]
105+
source: diffscope-builtin
106+
107+
# ── CSRF ───────────────────────────────────────────────────────────
108+
- id: sec.auth.csrf
109+
description: >
110+
Missing or disabled CSRF protection on state-changing endpoints.
111+
Flag: @csrf_exempt (Django), .csrf().disable() (Spring), skip_before_action
112+
:verify_authenticity_token (Rails), missing csurf middleware (Express).
113+
Also flag state-changing operations on GET endpoints.
114+
Not applicable to: pure API endpoints using Bearer tokens (not cookies).
115+
scope: "**/*.{py,js,ts,rb,go,rs,java,kt,cs,php}"
116+
severity: warning
117+
category: security
118+
tags: [auth, csrf, owasp-a01, cwe-352]
119+
source: diffscope-builtin
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
rules:
2+
# ── Unsafe Deserialization ─────────────────────────────────────────
3+
- id: sec.deser.unsafe
4+
description: >
5+
Native deserialization of untrusted data, potentially enabling RCE.
6+
Language-specific dangerous functions:
7+
- Python: pickle.load/loads, cPickle, dill, shelve, marshal.load,
8+
yaml.load (without SafeLoader), yaml.unsafe_load, jsonpickle.decode,
9+
torch.load (PyTorch), HuggingFace unsafe download
10+
- Java: ObjectInputStream.readObject/readUnshared, XMLDecoder,
11+
XStream.fromXML (pre-1.4.7), BinaryFormatter
12+
- Ruby: YAML.load (use safe_load), Marshal.load,
13+
JSON.parse(create_additions: true)
14+
- JavaScript: node-serialize unserialize(), funcster, js-yaml !!js/function,
15+
cryo.parse()
16+
- PHP: unserialize()
17+
- .NET: BinaryFormatter.Deserialize, TypeNameHandling != None,
18+
JavaScriptSerializer with TypeResolver
19+
- Go: gob.Decode on untrusted input
20+
Safe alternatives: JSON, yaml.safe_load, ObjectInputStream with allowlist.
21+
scope: "**/*.{py,js,ts,rb,go,rs,java,kt,cs,php}"
22+
severity: error
23+
category: security
24+
tags: [deserialization, rce, owasp-a08, cwe-502]
25+
source: diffscope-builtin
26+
27+
# ── SSRF (Server-Side Request Forgery) ─────────────────────────────
28+
- id: sec.ssrf
29+
description: >
30+
User-controlled input used to construct outbound HTTP request URLs.
31+
Sinks: requests.get(url), fetch(url), axios.get(url), http.Get(url),
32+
reqwest::get(url), HttpURLConnection(url), Net::HTTP.get(URI(url)),
33+
RestTemplate.getForObject(url), WebClient.get().uri(url).
34+
Check for: URL parameters, redirect targets, webhook URLs, image URLs,
35+
callback URLs built from user input.
36+
Bypass awareness: DNS rebinding, redirect following, encoding tricks
37+
(hex IP, octal IP, IPv6 mapped), scheme abuse (file://, gopher://).
38+
Sanitizers: URL allowlisting, DNS resolution + IP blocklist validation,
39+
disabling redirects, blocking internal IP ranges
40+
(10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.169.254).
41+
scope: "**/*.{py,js,ts,rb,go,rs,java,kt,cs,php,scala}"
42+
severity: error
43+
category: security
44+
tags: [ssrf, owasp-a10, cwe-918]
45+
source: diffscope-builtin
46+
47+
# ── XXE (XML External Entity) ──────────────────────────────────────
48+
- id: sec.xxe
49+
description: >
50+
XML parsing without disabling external entity resolution.
51+
Sinks: DocumentBuilderFactory, SAXParser, XMLReader, etree.parse,
52+
lxml.etree.parse, xml.sax.parse without disabling external entities.
53+
Fix: set feature "http://apache.org/xml/features/disallow-doctype-decl" true,
54+
or use defusedxml (Python), set XMLConstants.FEATURE_SECURE_PROCESSING.
55+
scope: "**/*.{py,js,ts,rb,go,rs,java,kt,cs,php}"
56+
severity: error
57+
category: security
58+
tags: [xxe, xml, owasp-a05, cwe-611]
59+
source: diffscope-builtin
60+
61+
# ── Open Redirect ──────────────────────────────────────────────────
62+
- id: sec.redirect.open
63+
description: >
64+
Unvalidated redirect using user-controlled URL.
65+
Sinks: redirect(req.params.url), res.redirect(req.query.next),
66+
HttpResponseRedirect(request.GET['url']), redirect_to(params[:url]).
67+
Sanitizers: allowlist of permitted domains/paths, relative-URL-only validation.
68+
scope: "**/*.{py,js,ts,rb,go,rs,java,kt,cs,php}"
69+
severity: warning
70+
category: security
71+
tags: [redirect, open-redirect, owasp-a01, cwe-601]
72+
source: diffscope-builtin
73+
74+
# ── CORS Misconfiguration ──────────────────────────────────────────
75+
- id: sec.cors.misconfigured
76+
description: >
77+
Overly permissive CORS configuration.
78+
Flag: Access-Control-Allow-Origin: * with credentials,
79+
reflecting the Origin header without validation,
80+
regex-based origin matching with bypass potential.
81+
scope: "**/*.{py,js,ts,rb,go,rs,java,kt,cs,php}"
82+
severity: warning
83+
category: security
84+
tags: [cors, owasp-a05, cwe-942]
85+
source: diffscope-builtin

rules/security/injection.yaml

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
rules:
2+
# ── SQL Injection ──────────────────────────────────────────────────
3+
- id: sec.injection.sql
4+
description: >
5+
User-controlled input concatenated or interpolated into a SQL query string
6+
instead of using parameterized queries / prepared statements.
7+
Sinks: cursor.execute(f"..."), db.Query(fmt.Sprintf(...)), connection.query(str),
8+
ActiveRecord.where("... #{...}"), sqlx::query(format!(...)), SqlCommand(str).
9+
Sanitizers: parameterized queries (?/$1 placeholders), ORM filters, sqlx::query! macro.
10+
scope: "**/*.{py,js,ts,rb,go,rs,java,kt,cs,php,scala}"
11+
severity: error
12+
category: security
13+
tags: [injection, sql-injection, owasp-a03, cwe-89]
14+
source: diffscope-builtin
15+
16+
- id: sec.injection.sql.nosql
17+
description: >
18+
NoSQL injection via unsanitized input in MongoDB/DynamoDB/Elasticsearch queries.
19+
Check for $where, $regex, $gt/$lt operators built from user input,
20+
or JSON query objects constructed from request parameters.
21+
scope: "**/*.{py,js,ts,rb,go,java}"
22+
severity: error
23+
category: security
24+
tags: [injection, nosql-injection, owasp-a03, cwe-943]
25+
source: diffscope-builtin
26+
27+
# ── Command Injection ──────────────────────────────────────────────
28+
- id: sec.injection.command
29+
description: >
30+
User-controlled input passed to OS command execution functions.
31+
Sinks: os.system(), subprocess.Popen(shell=True), exec.Command("sh","-c",str),
32+
child_process.exec(str), Runtime.exec(str), system(str), Process.spawn(str).
33+
Sanitizers: argument arrays (not shell strings), shlex.quote(), allowlist validation.
34+
Flag shell=True with non-literal command strings.
35+
scope: "**/*.{py,js,ts,rb,go,rs,java,kt,cs,php,bash,sh}"
36+
severity: error
37+
category: security
38+
tags: [injection, command-injection, owasp-a03, cwe-78]
39+
source: diffscope-builtin
40+
41+
# ── XSS (Cross-Site Scripting) ─────────────────────────────────────
42+
- id: sec.injection.xss
43+
description: >
44+
User-controlled content rendered as HTML without output encoding.
45+
Sinks: innerHTML, outerHTML, document.write(), dangerouslySetInnerHTML,
46+
raw(), .html_safe, mark_safe(), Markup(), bypassSecurityTrust*().
47+
Safe alternatives: textContent, createElement, framework auto-escaping.
48+
Check template files for unescaped output: {{! }}, |safe, -%>, <%==.
49+
scope: "**/*.{js,jsx,ts,tsx,html,erb,ejs,hbs,vue,svelte,py,rb,php,java}"
50+
severity: error
51+
category: security
52+
tags: [injection, xss, owasp-a03, cwe-79]
53+
source: diffscope-builtin
54+
55+
# ── Template Injection (SSTI) ──────────────────────────────────────
56+
- id: sec.injection.template
57+
description: >
58+
Server-side template injection via user input in template strings.
59+
Sinks: Jinja2 Template(user_input), Flask render_template_string(user_input),
60+
Mako Template(user_input), ERB.new(user_input), Razor @Html.Raw(user_input).
61+
Check for user input flowing into template compilation (not just rendering).
62+
scope: "**/*.{py,rb,js,ts,java,cs,go}"
63+
severity: error
64+
category: security
65+
tags: [injection, ssti, template-injection, owasp-a03, cwe-1336]
66+
source: diffscope-builtin
67+
68+
# ── LDAP Injection ─────────────────────────────────────────────────
69+
- id: sec.injection.ldap
70+
description: >
71+
User input interpolated into LDAP search filters without escaping.
72+
Sinks: DirContext.search(), InitialDirContext.search(), LdapContext methods.
73+
Sanitizers: LDAP filter encoding, allowlist validation of search terms.
74+
scope: "**/*.{java,kt,cs,py,php}"
75+
severity: error
76+
category: security
77+
tags: [injection, ldap-injection, owasp-a03, cwe-90]
78+
source: diffscope-builtin
79+
80+
# ── Log Injection ──────────────────────────────────────────────────
81+
- id: sec.injection.log
82+
description: >
83+
User-controlled data written to logs without sanitization, enabling
84+
log forging or ANSI escape sequence injection.
85+
Check for request parameters, headers, or user input in log statements
86+
without newline/control character stripping.
87+
scope: "**/*.{py,js,ts,rb,go,rs,java,kt,cs}"
88+
severity: warning
89+
category: security
90+
tags: [injection, log-injection, owasp-a09, cwe-117]
91+
source: diffscope-builtin
92+
93+
# ── Path Traversal ─────────────────────────────────────────────────
94+
- id: sec.injection.path-traversal
95+
description: >
96+
User input used to construct file paths without validation, allowing
97+
directory traversal via ../ sequences or absolute paths.
98+
Sinks: open(user_path), fs.readFile(user_path), File.new(user_path),
99+
std::fs::read(user_path), os.Open(user_path).
100+
Sanitizers: path canonicalization + prefix check, basename extraction.
101+
scope: "**/*.{py,js,ts,rb,go,rs,java,kt,cs,php}"
102+
severity: error
103+
category: security
104+
tags: [injection, path-traversal, owasp-a01, cwe-22]
105+
source: diffscope-builtin
106+
107+
# ── Code Injection ─────────────────────────────────────────────────
108+
- id: sec.injection.code
109+
description: >
110+
User input passed to code evaluation functions.
111+
Sinks: eval(), exec(), Function(str), setTimeout(str), setInterval(str),
112+
compile(), __import__(), importlib with user strings.
113+
Almost never safe with user input — flag unconditionally.
114+
scope: "**/*.{py,js,ts,rb,php}"
115+
severity: error
116+
category: security
117+
tags: [injection, code-injection, owasp-a03, cwe-94]
118+
source: diffscope-builtin

0 commit comments

Comments
 (0)