Skip to content

Commit e52a16d

Browse files
haasonsaasclaude
andcommitted
feat: expand security rules from 41 to 102 across 10 categories
New rule files: - crypto.yaml (10): weak ciphers, insecure TLS, bad randomness, key sizes, hardcoded IVs, unauthenticated encryption, cert validation, timing attacks - data-exposure.yaml (8): PII in logs, verbose errors, debug mode, sensitive URLs, missing security headers, server info disclosure, directory listing - unsafe-code.yaml (8): Rust unsafe, C/C++ memory, ReDoS, prototype pollution, mass assignment, race conditions, integer overflow, resource leaks - infra.yaml (9): Docker root/ADD/secrets, K8s privileged/secrets, Terraform public resources, IAM overpermission, Helm secrets, exposed ports - api.yaml (8): rate limiting, excessive data, pagination, GraphQL depth, API key in URL, input validation, function-level auth, file upload Expanded existing files: - injection.yaml: +6 rules (GraphQL, HTTP header/CRLF, email, XML, regex/ReDoS) - secrets.yaml: +13 providers (Azure, Datadog, New Relic, Supabase, DigitalOcean, Shopify, Discord, Databricks, Linear, PyPI, Mailgun, Doppler) Code changes: - Security prompt covers all 10 categories with source/sink/sanitizer guidance - SecretScanner: 12 new regex patterns (36 total) with 6 new tests - CommentSynthesizer: 50+ new category keywords, confidence boosters, and tags Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent db0d856 commit e52a16d

10 files changed

Lines changed: 1447 additions & 1 deletion

File tree

rules/security/api.yaml

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
rules:
2+
# ── Missing Rate Limiting ────────────────────────────────────────
3+
- id: sec.api.missing-rate-limit
4+
description: >
5+
API endpoint without rate limiting, enabling brute-force attacks and abuse.
6+
Especially critical on: login/auth endpoints, password reset, OTP verification,
7+
signup/registration, expensive operations (search, export, AI inference).
8+
Flag: new API route handlers without rate-limit middleware.
9+
Per framework:
10+
- Express: missing express-rate-limit or similar middleware
11+
- Django: missing django-ratelimit decorator
12+
- FastAPI: missing slowapi limiter
13+
- Spring: missing @RateLimiter, no Resilience4j/Bucket4j
14+
- Go: no rate.Limiter or middleware
15+
Safe: token bucket, sliding window, distributed rate limiting (Redis-backed).
16+
scope: "**/*.{py,js,ts,rb,go,rs,java,kt,cs,php}"
17+
severity: warning
18+
category: security
19+
tags: [api, rate-limiting, brute-force, owasp-a04, cwe-770]
20+
source: diffscope-builtin
21+
22+
# ── Excessive Data Exposure ──────────────────────────────────────
23+
- id: sec.api.excessive-data
24+
description: >
25+
API response returning more data than the client needs, leaking sensitive
26+
fields. Flag: returning full database objects/models directly as JSON
27+
without DTO/serializer field selection, SELECT * in API-backing queries,
28+
user objects returned with password_hash/email/phone to unauthorized callers.
29+
Safe: explicit field selection in serializers, DTO/ViewModel pattern,
30+
GraphQL field-level authorization, response schemas.
31+
scope: "**/*.{py,js,ts,rb,go,rs,java,kt,cs,php}"
32+
severity: warning
33+
category: security
34+
tags: [api, data-exposure, owasp-a03, cwe-213]
35+
source: diffscope-builtin
36+
37+
# ── Missing Pagination / Unbounded Query ─────────────────────────
38+
- id: sec.api.no-pagination
39+
description: >
40+
API endpoint returning unbounded result sets without pagination limits.
41+
Can cause OOM, slow responses, and be used for data exfiltration.
42+
Flag: database queries without LIMIT, ORM .all() without pagination,
43+
list endpoints without page/limit/offset parameters, missing max page size.
44+
Safe: cursor-based or offset-based pagination with enforced max page size
45+
(e.g., max 100 per page), streaming for large exports.
46+
scope: "**/*.{py,js,ts,rb,go,rs,java,kt,cs,php}"
47+
severity: warning
48+
category: security
49+
tags: [api, pagination, dos, owasp-a04, cwe-770]
50+
source: diffscope-builtin
51+
52+
# ── GraphQL: Missing Depth/Complexity Limits ─────────────────────
53+
- id: sec.api.graphql-depth
54+
description: >
55+
GraphQL API without query depth or complexity limits, enabling
56+
denial-of-service via deeply nested or expensive queries.
57+
Flag: GraphQL server setup without depth limiting middleware,
58+
missing complexity analysis, no query cost calculation,
59+
introspection enabled in production, no persisted queries.
60+
Safe: graphql-depth-limit, graphql-validation-complexity, Apollo costAnalysis
61+
directive, persisted queries only, disable introspection in production.
62+
scope: "**/*.{py,js,ts,rb,go,rs,java,kt,cs}"
63+
severity: warning
64+
category: security
65+
tags: [api, graphql, dos, owasp-a04, cwe-770]
66+
source: diffscope-builtin
67+
68+
# ── API Key in Query String ──────────────────────────────────────
69+
- id: sec.api.key-in-url
70+
description: >
71+
API key or authentication token passed in URL query parameters.
72+
URLs are logged by proxies, CDNs, web servers, and stored in browser history.
73+
Flag: ?api_key=, ?token=, ?access_token=, ?key= in API client code,
74+
route handlers reading auth from req.query instead of Authorization header.
75+
Safe: Authorization: Bearer header, API key in X-API-Key header.
76+
scope: "**/*.{py,js,ts,rb,go,rs,java,kt,cs,php}"
77+
severity: warning
78+
category: security
79+
tags: [api, authentication, api-key, owasp-a07, cwe-598]
80+
source: diffscope-builtin
81+
82+
# ── Missing Input Validation ─────────────────────────────────────
83+
- id: sec.api.no-input-validation
84+
description: >
85+
API endpoint accepting user input without schema validation.
86+
Flag: POST/PUT/PATCH handlers without request body validation,
87+
missing Pydantic/marshmallow models (Python), no Joi/Zod schema (Node.js),
88+
no @Valid/@Validated annotation (Spring), request parameters used directly
89+
without type checking or constraint validation.
90+
Safe: schema validation (JSON Schema, OpenAPI, Pydantic, Joi, Zod),
91+
type-safe deserialization, input length limits, enum validation.
92+
scope: "**/*.{py,js,ts,rb,go,rs,java,kt,cs,php}"
93+
severity: warning
94+
category: security
95+
tags: [api, input-validation, owasp-a03, cwe-20]
96+
source: diffscope-builtin
97+
98+
# ── Broken Function-Level Authorization ──────────────────────────
99+
- id: sec.api.broken-function-auth
100+
description: >
101+
Admin or privileged API endpoints accessible by regular users.
102+
Flag: admin routes without role/permission middleware, API endpoints
103+
that check authentication but not authorization (is_authenticated but
104+
no is_admin/has_permission), mixed user/admin routes in same controller
105+
without per-route authorization.
106+
Safe: role-based middleware per route, policy-based authorization,
107+
separate admin API with distinct auth, RBAC decorators.
108+
scope: "**/*.{py,js,ts,rb,go,rs,java,kt,cs,php}"
109+
severity: error
110+
category: security
111+
tags: [api, authorization, rbac, owasp-a01, cwe-285]
112+
source: diffscope-builtin
113+
114+
# ── Insecure File Upload ─────────────────────────────────────────
115+
- id: sec.api.insecure-upload
116+
description: >
117+
File upload endpoint without proper validation, enabling malicious file upload.
118+
Flag: accepting uploads without file type validation, relying only on
119+
Content-Type header (attacker-controlled), storing uploads in web-accessible
120+
directories, no file size limits, allowing executable extensions (.php, .jsp,
121+
.py, .sh, .exe, .bat), no filename sanitization.
122+
Safe: validate file magic bytes, allowlist extensions, store outside webroot,
123+
generate random filenames, enforce size limits, virus scan.
124+
scope: "**/*.{py,js,ts,rb,go,rs,java,kt,cs,php}"
125+
severity: error
126+
category: security
127+
tags: [api, file-upload, owasp-a04, cwe-434]
128+
source: diffscope-builtin

rules/security/crypto.yaml

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
rules:
2+
# ── Weak Cipher Algorithm ────────────────────────────────────────
3+
- id: sec.crypto.weak-cipher
4+
description: >
5+
Use of a known-broken or weak cipher algorithm.
6+
Vulnerable: DES, 3DES (TDEA), RC4, RC2, Blowfish, IDEA, ECB mode for any cipher.
7+
Per language:
8+
- Python: Crypto.Cipher.DES, Crypto.Cipher.ARC4, algorithms.TripleDES, mode=ECB
9+
- Java: Cipher.getInstance("DES"), Cipher.getInstance("RC4"), "AES/ECB/*"
10+
- Go: des.NewCipher, rc4.NewCipher, cipher.NewECBEncrypter
11+
- Rust: des crate, rc4 crate, ecb mode
12+
- JavaScript: crypto.createCipheriv('des-*'), createCipheriv('rc4')
13+
- C#: DESCryptoServiceProvider, RC2CryptoServiceProvider
14+
Safe alternatives: AES-256-GCM, ChaCha20-Poly1305, XChaCha20-Poly1305.
15+
scope: "**/*.{py,js,ts,rb,go,rs,java,kt,cs,php,c,cpp}"
16+
severity: error
17+
category: security
18+
tags: [crypto, weak-cipher, owasp-a02, cwe-327]
19+
source: diffscope-builtin
20+
21+
# ── Insecure TLS Configuration ───────────────────────────────────
22+
- id: sec.crypto.weak-tls
23+
description: >
24+
TLS configuration allowing insecure protocol versions or cipher suites.
25+
Vulnerable: SSLv2, SSLv3, TLS 1.0, TLS 1.1, ssl.PROTOCOL_TLSv1, PROTOCOL_SSLv23
26+
without disabling old versions, MinVersion < tls.VersionTLS12 (Go),
27+
SecurityProtocolType.Ssl3/Tls (C#), ssl_protocols TLSv1 (nginx/Apache).
28+
Also flag: verify_mode = ssl.CERT_NONE, InsecureSkipVerify: true (Go),
29+
NODE_TLS_REJECT_UNAUTHORIZED=0, CURLOPT_SSL_VERIFYPEER => false.
30+
Safe: TLS 1.2+ with AEAD cipher suites, certificate pinning.
31+
scope: "**/*.{py,js,ts,rb,go,rs,java,kt,cs,php,conf,yaml,yml,toml}"
32+
severity: error
33+
category: security
34+
tags: [crypto, tls, ssl, owasp-a02, cwe-326]
35+
source: diffscope-builtin
36+
37+
# ── Insecure Randomness ──────────────────────────────────────────
38+
- id: sec.crypto.insecure-random
39+
description: >
40+
Use of non-cryptographic PRNG for security-sensitive operations.
41+
Vulnerable (when used for tokens, keys, nonces, passwords, session IDs):
42+
- Python: random.random(), random.randint(), random.choice() — use secrets module
43+
- JavaScript: Math.random() — use crypto.getRandomValues() or crypto.randomUUID()
44+
- Java: java.util.Random — use java.security.SecureRandom
45+
- Go: math/rand — use crypto/rand
46+
- Ruby: rand, Random.new — use SecureRandom
47+
- Rust: rand::thread_rng() is OK, but rand::rngs::SmallRng is not for crypto
48+
- C/C++: rand(), srand() — use platform CSPRNG
49+
- PHP: rand(), mt_rand() — use random_bytes(), random_int()
50+
Safe: os.urandom, secrets.token_*, SecureRandom, crypto/rand, CSPRNG.
51+
scope: "**/*.{py,js,ts,rb,go,rs,java,kt,cs,php,c,cpp}"
52+
severity: error
53+
category: security
54+
tags: [crypto, random, prng, owasp-a02, cwe-330]
55+
source: diffscope-builtin
56+
57+
# ── Weak Key Size ────────────────────────────────────────────────
58+
- id: sec.crypto.weak-key-size
59+
description: >
60+
Cryptographic key size below recommended minimum.
61+
Minimum key sizes: RSA >= 2048 (prefer 4096), EC >= 256 bits (P-256+),
62+
AES >= 128 (prefer 256), HMAC key >= hash output length.
63+
Flag: RSA 1024, DSA 1024, DH 1024, EC P-192, AES-64.
64+
Per language: generate_private_key(1024), KeyPairGenerator with < 2048,
65+
rsa.GenerateKey(rand, 1024), openssl genrsa 1024.
66+
scope: "**/*.{py,js,ts,rb,go,rs,java,kt,cs,php,c,cpp}"
67+
severity: error
68+
category: security
69+
tags: [crypto, key-size, owasp-a02, cwe-326]
70+
source: diffscope-builtin
71+
72+
# ── Broken Hash for Integrity ────────────────────────────────────
73+
- id: sec.crypto.broken-hash
74+
description: >
75+
Use of broken hash algorithms for integrity verification or digital signatures.
76+
Vulnerable: MD5, SHA1 for checksums, file integrity, digital signatures, HMAC.
77+
(Note: MD5/SHA1 for password hashing is covered by sec.auth.weak-password-hash.)
78+
Flag: hashlib.md5() for file verification, MessageDigest.getInstance("MD5"),
79+
crypto.createHash('sha1') for HMAC, Digest::MD5 for signatures.
80+
Safe: SHA-256, SHA-384, SHA-512, SHA-3, BLAKE2, BLAKE3.
81+
scope: "**/*.{py,js,ts,rb,go,rs,java,kt,cs,php,c,cpp}"
82+
severity: warning
83+
category: security
84+
tags: [crypto, broken-hash, md5, sha1, owasp-a02, cwe-328]
85+
source: diffscope-builtin
86+
87+
# ── Hardcoded IV / Nonce ─────────────────────────────────────────
88+
- id: sec.crypto.hardcoded-iv
89+
description: >
90+
Initialization vector (IV) or nonce is hardcoded, static, or reused.
91+
IV/nonce must be unique per encryption operation. Reuse with CTR/GCM modes
92+
leads to catastrophic key recovery. Flag: string/byte literals assigned to
93+
iv/nonce variables, IV = b'\x00' * 16, static final byte[] IV.
94+
Safe: generate random IV per operation, store IV alongside ciphertext.
95+
scope: "**/*.{py,js,ts,rb,go,rs,java,kt,cs,php,c,cpp}"
96+
severity: error
97+
category: security
98+
tags: [crypto, iv-reuse, nonce, owasp-a02, cwe-329]
99+
source: diffscope-builtin
100+
101+
# ── Unauthenticated Encryption ───────────────────────────────────
102+
- id: sec.crypto.missing-mac
103+
description: >
104+
Encryption without authentication (no MAC/AEAD), enabling bit-flipping
105+
and padding oracle attacks. Vulnerable: AES-CBC without HMAC,
106+
AES-CTR without MAC, any stream cipher without authentication.
107+
Flag: CBC/CTR mode usage without a paired HMAC-then-encrypt or encrypt-then-MAC.
108+
Safe: AES-GCM, AES-CCM, ChaCha20-Poly1305, XChaCha20-Poly1305, NaCl secretbox.
109+
scope: "**/*.{py,js,ts,rb,go,rs,java,kt,cs,php,c,cpp}"
110+
severity: warning
111+
category: security
112+
tags: [crypto, authenticated-encryption, mac, owasp-a02, cwe-353]
113+
source: diffscope-builtin
114+
115+
# ── Disabled Certificate Validation ──────────────────────────────
116+
- id: sec.crypto.cert-validation
117+
description: >
118+
TLS certificate validation disabled, enabling MITM attacks.
119+
Flag per language:
120+
- Python: verify=False (requests), ssl.CERT_NONE, check_hostname=False
121+
- Go: InsecureSkipVerify: true, tls.Config with no verification
122+
- Java: TrustAllCerts, X509TrustManager accepting all, HostnameVerifier accepting all
123+
- Node.js: rejectUnauthorized: false, NODE_TLS_REJECT_UNAUTHORIZED=0
124+
- Ruby: verify_mode = OpenSSL::SSL::VERIFY_NONE
125+
- Rust: danger_accept_invalid_certs(true) (reqwest)
126+
- C#: ServerCertificateValidationCallback returning true
127+
- PHP: CURLOPT_SSL_VERIFYPEER => false, verify_peer => false
128+
scope: "**/*.{py,js,ts,rb,go,rs,java,kt,cs,php}"
129+
severity: error
130+
category: security
131+
tags: [crypto, certificate, tls, mitm, owasp-a02, cwe-295]
132+
source: diffscope-builtin
133+
134+
# ── Timing Attack on Secret Comparison ───────────────────────────
135+
- id: sec.crypto.timing-attack
136+
description: >
137+
Non-constant-time comparison of secrets, tokens, or MACs.
138+
Flag: == or != operator comparing HMAC digests, API keys, tokens, passwords.
139+
Safe alternatives per language:
140+
- Python: hmac.compare_digest(), secrets.compare_digest()
141+
- Go: subtle.ConstantTimeCompare()
142+
- Java: MessageDigest.isEqual()
143+
- Node.js: crypto.timingSafeEqual()
144+
- Ruby: Rack::Utils.secure_compare(), ActiveSupport::SecurityUtils.secure_compare()
145+
- Rust: constant_time_eq crate, subtle crate ConstantTimeEq
146+
scope: "**/*.{py,js,ts,rb,go,rs,java,kt,cs,php}"
147+
severity: warning
148+
category: security
149+
tags: [crypto, timing-attack, side-channel, owasp-a02, cwe-208]
150+
source: diffscope-builtin
151+
152+
# ── Weak Key Derivation ──────────────────────────────────────────
153+
- id: sec.crypto.weak-kdf
154+
description: >
155+
Key derivation function with insufficient work factor or using a
156+
non-standard approach. Flag: PBKDF2 with < 600,000 iterations (OWASP 2023),
157+
single-pass SHA/MD5 as KDF, custom "key stretching" implementations,
158+
scrypt with N < 2^15 or r < 8, argon2 with < 3 iterations.
159+
Safe: argon2id (>=3 iterations, >=64MB), bcrypt (cost >= 12),
160+
scrypt (N >= 2^17, r >= 8), PBKDF2-SHA256 (>= 600k iterations).
161+
scope: "**/*.{py,js,ts,rb,go,rs,java,kt,cs,php}"
162+
severity: warning
163+
category: security
164+
tags: [crypto, kdf, key-derivation, owasp-a02, cwe-916]
165+
source: diffscope-builtin

0 commit comments

Comments
 (0)