feat: add security-review skill for AI-powered codebase vulnerability scanning (#1211)

* feat: add security-review skill for AI-powered codebase vulnerability scanning

* chore: regenerate README tables

* fix: address Copilot review comments on reference files
This commit is contained in:
Mrigank Singh
2026-03-30 06:14:48 +05:30
committed by GitHub
parent 04a7e6c306
commit 7e375eac04
7 changed files with 1154 additions and 0 deletions

View File

@@ -0,0 +1,221 @@
# Language-Specific Vulnerability Patterns
Load the relevant section during Step 1 (Scope Resolution) after identifying languages.
---
## JavaScript / TypeScript (Node.js, React, Next.js, Express)
### Critical APIs/calls to flag
```js
eval() // arbitrary code execution
Function('return ...') // same as eval
child_process.exec() // command injection if user input reaches it
fs.readFile // path traversal if user controls path
fs.writeFile // path traversal if user controls path
```
### Express.js specific
```js
// Missing helmet (security headers)
const app = express()
// Should have: app.use(helmet())
// Body size limits missing (DoS)
app.use(express.json())
// Should have: app.use(express.json({ limit: '10kb' }))
// CORS misconfiguration
app.use(cors({ origin: '*' })) // too permissive
app.use(cors({ origin: req.headers.origin })) // reflects any origin
// Trust proxy without validation
app.set('trust proxy', true) // only safe behind known proxy
```
### React specific
```jsx
<div dangerouslySetInnerHTML={{ __html: userContent }} /> // XSS
<a href={userUrl}>link</a> // javascript: URL injection
```
### Next.js specific
```js
// Server Actions without auth
export async function deleteUser(id) { // missing: auth check
await db.users.delete(id)
}
// API Routes missing method validation
export default function handler(req, res) {
// Should check: if (req.method !== 'POST') return res.status(405)
doSensitiveAction()
}
```
---
## Python (Django, Flask, FastAPI)
### Django specific
```python
# Raw SQL
User.objects.raw(f"SELECT * FROM users WHERE name = '{name}'") # SQLi
# Missing CSRF
@csrf_exempt # Only OK for APIs with token auth
# Debug mode in production
DEBUG = True # in settings.py — exposes stack traces
# SECRET_KEY
SECRET_KEY = 'django-insecure-...' # must be changed for production
# ALLOWED_HOSTS
ALLOWED_HOSTS = ['*'] # too permissive
```
### Flask specific
```python
# Debug mode
app.run(debug=True) # never in production
# Secret key
app.secret_key = 'dev' # weak
# eval/exec with user input
eval(request.args.get('expr'))
# render_template_string with user input (SSTI)
render_template_string(f"Hello {name}") # Server-Side Template Injection
```
### FastAPI specific
```python
# Missing auth dependency
@app.delete("/users/{user_id}") # No Depends(get_current_user)
async def delete_user(user_id: int):
...
# Arbitrary file read
@app.get("/files/{filename}")
async def read_file(filename: str):
return FileResponse(f"uploads/{filename}") # path traversal
```
---
## Java (Spring Boot)
### Spring Boot specific
```java
// SQL Injection
String query = "SELECT * FROM users WHERE name = '" + name + "'";
jdbcTemplate.query(query, ...);
// XXE
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
// Missing: dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true)
// Deserialization
ObjectInputStream ois = new ObjectInputStream(inputStream);
Object obj = ois.readObject(); // only safe with allowlist
// Spring Security — permitAll on sensitive endpoint
.antMatchers("/admin/**").permitAll()
// Actuator endpoints exposed
management.endpoints.web.exposure.include=* # in application.properties
```
---
## PHP
```php
// Direct user input in queries
$result = mysql_query("SELECT * FROM users WHERE id = " . $_GET['id']);
// File inclusion
include($_GET['page'] . ".php"); // local/remote file inclusion
// eval
eval($_POST['code']);
// extract() with user input
extract($_POST); // overwrites any variable
// Loose comparison
if ($password == "admin") {} // use === instead
// Unserialize
unserialize($_COOKIE['data']); // remote code execution
```
---
## Go
```go
// Command injection
exec.Command("sh", "-c", userInput)
// SQL injection
db.Query("SELECT * FROM users WHERE name = '" + name + "'")
// Path traversal
filePath := filepath.Join("/uploads/", userInput) // sanitize userInput first
// Insecure TLS
http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}
// Goroutine leak / missing context cancellation
go func() {
// No done channel or context
for { ... }
}()
```
---
## Ruby on Rails
```ruby
# SQL injection (safe alternatives use placeholders)
User.where("name = '#{params[:name]}'") # VULNERABLE
User.where("name = ?", params[:name]) # SAFE
# Mass assignment without strong params
@user.update(params[:user]) # should be params.require(:user).permit(...)
# eval / send with user input
eval(params[:code])
send(params[:method]) # arbitrary method call
# Redirect to user-supplied URL (open redirect)
redirect_to params[:url]
# YAML.load (allows arbitrary object creation)
YAML.load(user_input) # use YAML.safe_load instead
```
---
## Rust
```rust
// Unsafe blocks — flag for manual review
unsafe {
// Reason for unsafety should be documented
}
// Integer overflow (debug builds panic, release silently wraps)
let result = a + b; // use checked_add/saturating_add for financial math
// Unwrap/expect in production code (panics on None/Err)
let value = option.unwrap(); // prefer ? or match
// Deserializing arbitrary types
serde_json::from_str::<serde_json::Value>(&user_input) // generally safe
// But: bincode::deserialize from untrusted input — can be exploited
```

View File

@@ -0,0 +1,194 @@
# Security Report Format
Use this template for all `/security-review` output. Generated during Step 7.
---
## Report Structure
### Header
```
╔══════════════════════════════════════════════════════════╗
║ 🔐 SECURITY REVIEW REPORT ║
║ Generated by: /security-review skill ║
╚══════════════════════════════════════════════════════════╝
Project: <project name or path>
Scan Date: <today's date>
Scope: <files/directories scanned>
Languages Detected: <list>
Frameworks Detected: <list>
```
---
### Executive Summary Table
Always show this first — at a glance overview:
```
┌────────────────────────────────────────────────┐
│ FINDINGS SUMMARY │
├──────────────┬──────────────────────────────── ┤
│ 🔴 CRITICAL │ <n> findings │
│ 🟠 HIGH │ <n> findings │
│ 🟡 MEDIUM │ <n> findings │
│ 🔵 LOW │ <n> findings │
│ ⚪ INFO │ <n> findings │
├──────────────┼─────────────────────────────────┤
│ TOTAL │ <n> findings │
└──────────────┴─────────────────────────────────┘
Dependency Audit: <n> vulnerable packages found
Secrets Scan: <n> exposed credentials found
```
---
### Findings (Grouped by Category)
For EACH finding, use this card format:
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[SEVERITY EMOJI] [SEVERITY] — [VULNERABILITY TYPE]
Confidence: HIGH / MEDIUM / LOW
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📍 Location: src/routes/users.js, Line 47
🔍 Vulnerable Code:
const query = `SELECT * FROM users WHERE id = ${req.params.id}`;
db.execute(query);
⚠️ Risk:
An attacker can manipulate the `id` parameter to execute arbitrary
SQL commands, potentially dumping the entire database, bypassing
authentication, or deleting data.
Example attack: GET /users/1 OR 1=1--
✅ Recommended Fix:
Use parameterized queries:
const query = 'SELECT * FROM users WHERE id = ?';
db.execute(query, [req.params.id]);
📚 Reference: OWASP A03:2021 Injection
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
```
---
### Dependency Audit Section
```
📦 DEPENDENCY AUDIT
══════════════════
🟠 HIGH — lodash@4.17.20 (package.json)
CVE-2021-23337: Prototype pollution via zipObjectDeep()
Fix: npm install lodash@4.17.21
🟡 MEDIUM — axios@0.27.2 (package.json)
CVE-2023-45857: CSRF via withCredentials
Fix: npm install axios@1.6.0
⚪ INFO — express@4.18.2
No known CVEs. Current version is 4.19.2 — consider updating.
```
---
### Secrets Scan Section
```
🔑 SECRETS & EXPOSURE SCAN
═══════════════════════════
🔴 CRITICAL — Hardcoded API Key
File: src/config/database.js, Line 12
Found: STRIPE_SECRET_KEY = "sk_live_FAKE_KEY_..."
Action Required:
1. Rotate this key IMMEDIATELY at https://dashboard.stripe.com
2. Remove from source code
3. Add to .env file and load via process.env.STRIPE_SECRET_KEY
4. Add .env to .gitignore
5. Audit git history — key may be in previous commits:
git log --all -p | grep "sk_live_"
Use git-filter-repo or BFG to purge from history if found.
```
---
### Patch Proposals Section
Only include for CRITICAL and HIGH findings:
````
🛠️ PATCH PROPOSALS
══════════════════
⚠️ REVIEW EACH PATCH BEFORE APPLYING — Nothing has been changed yet.
─────────────────────────────────────────────
Patch 1/3: SQL Injection in src/routes/users.js
─────────────────────────────────────────────
BEFORE (vulnerable):
```js
// Line 47
const query = `SELECT * FROM users WHERE id = ${req.params.id}`;
db.execute(query);
```
AFTER (fixed):
```js
// Line 47 — Fixed: Use parameterized query to prevent SQL injection
const query = 'SELECT * FROM users WHERE id = ?';
db.execute(query, [req.params.id]);
```
Apply this patch? (Review first — AI-generated patches may need adjustment)
─────────────────────────────────────────────
````
---
### Footer
```
══════════════════════════════════════════════════════════
📋 SCAN COVERAGE
Files scanned: <n>
Lines analyzed: <n>
Scan duration: <time>
⚡ NEXT STEPS
1. Address all CRITICAL findings immediately
2. Schedule HIGH findings for current sprint
3. Add MEDIUM/LOW to your security backlog
4. Set up automated re-scanning in CI/CD pipelines
💡 NOTE: This is a static analysis scan. It does not execute your
application and cannot detect all runtime vulnerabilities. Pair
with dynamic testing (DAST) for comprehensive coverage.
══════════════════════════════════════════════════════════
```
---
## Confidence Ratings Guide
Apply to every finding:
| Confidence | When to Use |
|------------|-------------|
| **HIGH** | Vulnerability is unambiguous. Sanitization is clearly absent. Exploitable as-is. |
| **MEDIUM** | Vulnerability likely exists but depends on runtime context, config, or call path the agent couldn't fully trace. |
| **LOW** | Suspicious pattern detected but could be a false positive. Flag for human review. |
Never omit confidence — it helps developers prioritize their review effort.

View File

@@ -0,0 +1,178 @@
# Secret & Credential Detection Patterns
Load this file during Step 3 (Secrets & Exposure Scan).
---
## High-Confidence Secret Patterns
These patterns almost always indicate a real secret:
### API Keys & Tokens
```regex
# OpenAI
sk-[a-zA-Z0-9]{48}
# Anthropic
sk-ant-[a-zA-Z0-9\-_]{90,}
# AWS Access Key
AKIA[0-9A-Z]{16}
# AWS Secret Key (look for near AWS_ACCESS_KEY_ID assignment)
[0-9a-zA-Z/+]{40}
# GitHub Token
gh[pousr]_[a-zA-Z0-9]{36,}
github_pat_[a-zA-Z0-9]{82}
# Stripe
sk_live_[a-zA-Z0-9]{24,}
rk_live_[a-zA-Z0-9]{24,}
# Twilio Account SID
AC[a-z0-9]{32}
# Twilio API Key
SK[a-z0-9]{32}
# SendGrid
SG\.[a-zA-Z0-9\-_.]{66}
# Slack
xoxb-[0-9]+-[0-9]+-[a-zA-Z0-9]+
xoxp-[0-9]+-[0-9]+-[0-9]+-[a-zA-Z0-9]+
xapp-[0-9]+-[A-Z0-9]+-[0-9]+-[a-zA-Z0-9]+
# Google API Key
AIza[0-9A-Za-z\-_]{35}
# Google OAuth
[0-9]+-[0-9A-Za-z_]{32}\.apps\.googleusercontent\.com
# Cloudflare (near CF_API_TOKEN)
[a-zA-Z0-9_\-]{37}
# Mailgun
key-[a-zA-Z0-9]{32}
# Heroku
[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}
```
### Private Keys
```regex
-----BEGIN (RSA |EC |OPENSSH |DSA |PGP )?PRIVATE KEY( BLOCK)?-----
-----BEGIN CERTIFICATE-----
```
### Database Connection Strings
```regex
# MongoDB
mongodb(\+srv)?:\/\/[^:]+:[^@]+@
# PostgreSQL / MySQL
(postgres|postgresql|mysql):\/\/[^:]+:[^@]+@
# Redis with password
redis:\/\/:[^@]+@
# Generic connection string with password
(connection[_-]?string|connstr|db[_-]?url).*password=
```
### Hardcoded Passwords (variable name signals)
```regex
# Variable names that suggest secrets
(password|passwd|pwd|secret|api_key|apikey|auth_token|access_token|private_key)
\s*[=:]\s*["'][^"']{8,}["']
```
---
## Entropy-Based Detection
Apply to string literals > 20 characters in assignment context.
High entropy (Shannon entropy > 4.5 bits/char) + length > 20 = likely secret.
```
Calculate entropy: -sum(p * log2(p)) for each character frequency p
Threshold: > 4.5 bits/char AND > 20 chars AND assigned to a variable
```
Common false positives to exclude:
- Lorem ipsum text
- HTML/CSS content
- Base64-encoded non-sensitive config (but flag and note)
- UUID/GUID (entropy is high but format is recognizable)
---
## Files That Should Never Be Committed
Flag if these files exist in the repo root or are tracked by git:
```
.env
.env.local
.env.production
.env.staging
*.pem
*.key
*.p12
*.pfx
id_rsa
id_ed25519
credentials.json
service-account.json
gcp-key.json
secrets.yaml
secrets.json
config/secrets.yml
```
Also check `.gitignore` — if a secret file pattern is NOT in .gitignore, flag it.
---
## CI/CD & IaC Secret Risks
### GitHub Actions — flag these patterns:
```yaml
# Hardcoded values in env: blocks (should use ${{ secrets.NAME }})
env:
API_KEY: "actual-value-here" # VULNERABLE
# Printing secrets
- run: echo ${{ secrets.MY_SECRET }} # leaks to logs
```
### Docker — flag these:
```dockerfile
# Secrets in ENV (persisted in image layers)
ENV AWS_SECRET_KEY=actual-value
# Secrets passed as build args (visible in image history)
ARG API_KEY=actual-value
```
### Terraform — flag these:
```hcl
# Hardcoded sensitive values (should use var or data source)
password = "hardcoded-password"
access_key = "AKIAIOSFODNN7EXAMPLE"
```
---
## Safe Patterns (Do NOT flag)
These are intentional placeholders — recognize and skip:
```
"your-api-key-here"
"<YOUR_API_KEY>"
"${API_KEY}"
"${process.env.API_KEY}"
"os.environ.get('API_KEY')"
"REPLACE_WITH_YOUR_KEY"
"xxx...xxx"
"sk-..." (in documentation/comments)
```

View File

@@ -0,0 +1,281 @@
# Vulnerability Categories — Deep Reference
This file contains detailed detection guidance for every vulnerability category.
Load this during Step 4 of the scan workflow.
---
## 1. Injection Flaws
### SQL Injection
**What to look for:**
- String concatenation or interpolation inside SQL queries
- Raw `.query()`, `.execute()`, `.raw()` calls with variables
- ORM `whereRaw()`, `selectRaw()`, `orderByRaw()` with user input
- Second-order SQLi: data stored safely, then used unsafely later
- Stored procedures called with unsanitized input
**Detection signals (all languages):**
```
"SELECT ... " + variable
`SELECT ... ${variable}`
f"SELECT ... {variable}"
"SELECT ... %s" % variable # Only safe with proper driver parameterization
cursor.execute("... " + input)
db.raw(`... ${req.params.id}`)
```
**Safe patterns (parameterized):**
```js
db.query('SELECT * FROM users WHERE id = ?', [userId])
User.findOne({ where: { id: userId } }) // ORM safe
```
**Escalation checkers:**
- Is the query result ever used in another query? (second-order)
- Is the table/column name user-controlled? (cannot be parameterized — must allowlist)
---
### Cross-Site Scripting (XSS)
**What to look for:**
- `innerHTML`, `outerHTML`, `document.write()` with user data
- `dangerouslySetInnerHTML` in React
- Template engines rendering unescaped: `{{{ var }}}` (Handlebars), `!= var` (Pug)
- jQuery `.html()`, `.append()` with user data
- `eval()`, `setTimeout(string)`, `setInterval(string)` with user data
- DOM-based: `location.hash`, `document.referrer`, `window.name` written to DOM
- Stored XSS: user input saved to DB, rendered without escaping later
**Detection by framework:**
- **React**: Safe by default EXCEPT `dangerouslySetInnerHTML`
- **Angular**: Safe by default EXCEPT `bypassSecurityTrustHtml`
- **Vue**: Safe by default EXCEPT `v-html`
- **Vanilla JS**: Every DOM write is suspect
---
### Command Injection
**What to look for (Node.js):**
```js
exec(userInput)
execSync(`ping ${host}`)
spawn('sh', ['-c', userInput])
child_process.exec('ls ' + dir)
```
**What to look for (Python):**
```python
os.system(user_input)
subprocess.call(user_input, shell=True)
eval(user_input)
```
**What to look for (PHP):**
```php
exec($input)
system($_GET['cmd'])
passthru($input)
`$input` # backtick operator
```
**Safe alternatives:** Use array form of spawn/subprocess without shell=True; use allowlists for commands.
---
### Server-Side Request Forgery (SSRF)
**What to look for:**
- HTTP requests where the URL is user-controlled
- Webhooks, URL preview, image fetch features
- PDF generators that fetch external URLs
- Redirects to user-supplied URLs
**High-risk targets:**
- AWS metadata service: `169.254.169.254`
- Internal services: `localhost`, `127.0.0.1`, `10.x.x.x`, `192.168.x.x`
- Cloud metadata endpoints
**Detection:**
```js
fetch(req.body.url)
axios.get(userSuppliedUrl)
http.get(params.webhook)
```
---
## 2. Authentication & Access Control
### Broken Object Level Authorization (BOLA / IDOR)
**What to look for:**
- Resource IDs taken directly from URL/params without ownership check
- `findById(req.params.id)` without verifying `userId === currentUser.id`
- Numeric sequential IDs (easily guessable)
**Example vulnerable pattern:**
```js
// VULNERABLE: no ownership check
app.get('/api/documents/:id', async (req, res) => {
const doc = await Document.findById(req.params.id);
res.json(doc);
});
// SAFE: verify ownership
app.get('/api/documents/:id', async (req, res) => {
const doc = await Document.findOne({ _id: req.params.id, owner: req.user.id });
if (!doc) return res.status(403).json({ error: 'Forbidden' });
res.json(doc);
});
```
---
### JWT Vulnerabilities
**What to look for:**
- `alg: "none"` accepted
- Weak or hardcoded secrets: `secret`, `password`, `1234`
- No expiry (`exp` claim) validation
- Algorithm confusion (RS256 → HS256 downgrade)
- JWT stored in `localStorage` (XSS risk; prefer httpOnly cookie)
**Detection:**
```js
jwt.verify(token, secret, { algorithms: ['HS256'] }) // Check algorithms array
jwt.decode(token) // WARNING: decode does NOT verify signature
```
---
### Missing Authentication / Authorization
**What to look for:**
- Admin or sensitive endpoints missing auth middleware
- Routes defined after `app.use(authMiddleware)` vs before it
- Feature flags or debug endpoints left exposed in production
- GraphQL resolvers missing auth checks at field level
---
### CSRF
**What to look for:**
- State-changing operations (POST/PUT/DELETE) without CSRF token
- APIs relying only on cookies for auth without SameSite attribute
- Missing `SameSite=Strict` or `SameSite=Lax` on session cookies
---
## 3. Secrets & Sensitive Data Exposure
### In-Code Secrets
Look for patterns like:
```
API_KEY = "sk-..."
password = "hunter2"
SECRET = "abc123"
private_key = "-----BEGIN RSA PRIVATE KEY-----"
aws_secret_access_key = "wJalrXUtn..."
```
Entropy heuristic: strings > 20 chars with high character variety in assignment context
are likely secrets even if the variable name doesn't say so.
### In Logs / Error Messages
```js
console.log('User password:', password)
logger.info({ user, token }) // token shouldn't be logged
res.status(500).json({ error: err.stack }) // stack traces expose internals
```
### Sensitive Data in API Responses
- Returning full user object including `password_hash`, `ssn`, `credit_card`
- Including internal IDs or system paths in error responses
---
## 4. Cryptography
### Weak Algorithms
| Algorithm | Issue | Replace With |
|-----------|-------|--------------|
| MD5 | Broken for security | SHA-256 or bcrypt (passwords) |
| SHA-1 | Collision attacks | SHA-256 |
| DES / 3DES | Weak key size | AES-256-GCM |
| RC4 | Broken | AES-GCM |
| ECB mode | No IV, patterns visible | GCM or CBC with random IV |
### Weak Randomness
```js
// VULNERABLE
Math.random() // not cryptographically secure
Date.now() // predictable
Math.random().toString(36) // weak token generation
// SAFE
crypto.randomBytes(32) // Node.js
secrets.token_urlsafe(32) // Python
```
### Password Hashing
```python
# VULNERABLE
hashlib.md5(password.encode()).hexdigest()
hashlib.sha256(password.encode()).hexdigest()
# SAFE
bcrypt.hashpw(password, bcrypt.gensalt(rounds=12))
argon2.hash(password)
```
---
## 5. Insecure Dependencies
### What to flag:
- Packages with known CVEs in installed version range
- Packages abandoned > 2 years with no security updates
- Packages with extremely broad permissions for their stated purpose
- Transitive dependencies pulling in known-bad packages
- Pinned versions that are significantly behind current (possible unpatched vulns)
### High-risk package watchlist: see `references/vulnerable-packages.md`
---
## 6. Business Logic
### Race Conditions (TOCTOU)
```js
// VULNERABLE: check then act without atomic lock
const balance = await getBalance(userId);
if (balance >= amount) {
await deductBalance(userId, amount); // race condition between check and deduct
}
// SAFE: use atomic DB transaction or optimistic locking
await db.transaction(async (trx) => {
const user = await User.query(trx).forUpdate().findById(userId);
if (user.balance < amount) throw new Error('Insufficient funds');
await user.$query(trx).patch({ balance: user.balance - amount });
});
```
### Missing Rate Limiting
Flag endpoints that:
- Accept authentication credentials (login, 2FA)
- Send emails or SMS
- Perform expensive operations
- Expose user enumeration (password reset, registration)
---
## 7. Path Traversal
```python
# VULNERABLE
filename = request.args.get('file')
with open(f'/var/uploads/{filename}') as f: # ../../../../etc/passwd
# SAFE
filename = os.path.basename(request.args.get('file'))
safe_path = os.path.join('/var/uploads', filename)
if not safe_path.startswith('/var/uploads/'):
abort(400)
```

View File

@@ -0,0 +1,111 @@
# Vulnerable & High-Risk Package Watchlist
Load this during Step 2 (Dependency Audit). Check versions in the project's lock files.
---
## npm / Node.js
| Package | Vulnerable Versions | Issue | Safe Version |
|---------|-------------------|-------|--------------|
| lodash | < 4.17.21 | Prototype pollution (CVE-2021-23337) | >= 4.17.21 |
| axios | < 1.6.0 | SSRF, open redirect | >= 1.6.0 |
| jsonwebtoken | < 9.0.0 | Algorithm confusion bypass | >= 9.0.0 |
| node-jose | < 2.2.0 | Key confusion | >= 2.2.0 |
| shelljs | < 0.8.5 | ReDoS | >= 0.8.5 |
| tar | < 6.1.9 | Path traversal | >= 6.1.9 |
| minimist | < 1.2.6 | Prototype pollution | >= 1.2.6 |
| qs | < 6.7.3 | Prototype pollution | >= 6.7.3 |
| express | < 4.19.2 | Open redirect | >= 4.19.2 |
| multer | < 1.4.4 | DoS | >= 1.4.4-lts.1 |
| xml2js | < 0.5.0 | Prototype pollution | >= 0.5.0 |
| fast-xml-parser | < 4.2.4 | ReDoS | >= 4.2.4 |
| semver | < 7.5.2 | ReDoS | >= 7.5.2 |
| tough-cookie | < 4.1.3 | Prototype pollution | >= 4.1.3 |
| word-wrap | < 1.2.4 | ReDoS | >= 1.2.4 |
| vm2 | ANY | Sandbox escape (deprecated) | Use isolated-vm instead |
| serialize-javascript | < 3.1.0 | XSS | >= 3.1.0 |
| node-fetch | < 2.6.7 | Open redirect | >= 2.6.7 or 3.x |
### Patterns to flag (regardless of version):
- `eval` or `vm.runInContext` in dependencies
- Any package pulling in `node-gyp` native addons from unknown publishers
- Packages with < 1000 weekly downloads but required in production code (supply chain risk)
---
## Python / pip
| Package | Vulnerable Versions | Issue | Safe Version |
|---------|-------------------|-------|--------------|
| Pillow | < 10.0.1 | Multiple CVEs, buffer overflow | >= 10.0.1 |
| cryptography | < 41.0.0 | OpenSSL vulnerabilities | >= 41.0.0 |
| PyYAML | < 6.0 | Arbitrary code via yaml.load() | >= 6.0 |
| paramiko | < 3.4.0 | Authentication bypass | >= 3.4.0 |
| requests | < 2.31.0 | Proxy auth info leak | >= 2.31.0 |
| urllib3 | < 2.0.7 | Header injection | >= 2.0.7 |
| Django | < 4.2.16 | Various | >= 4.2.16 |
| Flask | < 3.0.3 | Various | >= 3.0.3 |
| Jinja2 | < 3.1.4 | HTML attribute injection | >= 3.1.4 |
| sqlalchemy | < 2.0.28 | Various | >= 2.0.28 |
| aiohttp | < 3.9.4 | SSRF, path traversal | >= 3.9.4 |
| werkzeug | < 3.0.3 | Various | >= 3.0.3 |
---
## Java / Maven
| Package | Vulnerable Versions | Issue |
|---------|-------------------|-------|
| log4j-core | 2.0-2.14.1 | Log4Shell RCE (CVE-2021-44228) — CRITICAL |
| log4j-core | 2.15.0 | Incomplete fix — still vulnerable |
| Spring Framework | < 5.3.28, < 6.0.13 | Various CVEs |
| Spring Boot | < 3.1.4 | Various |
| Jackson-databind | < 2.14.0 | Deserialization |
| Apache Commons Text | < 1.10.0 | Text4Shell RCE (CVE-2022-42889) |
| Apache Struts | < 6.3.0 | Various RCE |
| Netty | < 4.1.94 | HTTP request smuggling |
---
## Ruby / Gems
| Gem | Vulnerable Versions | Issue |
|-----|-------------------|-------|
| rails | < 7.1.3 | Various |
| nokogiri | < 1.16.2 | XXE, various |
| rexml | < 3.2.7 | ReDoS |
| rack | < 3.0.9 | Various |
| devise | < 4.9.3 | Various |
---
## Rust / Cargo
| Crate | Issue |
|-------|-------|
| openssl | Check advisory db for current version |
| hyper | Check advisory db for current version |
Reference: https://rustsec.org/advisories/
---
## Go
Reference: https://pkg.go.dev/vuln/ and https://vuln.go.dev
Common risky patterns:
- `golang.org/x/crypto` — check if version is within 6 months of current
- Any dependency using `syscall` package directly — review carefully
---
## General Red Flags (Any Ecosystem)
Flag any dependency that:
1. Has not been updated in > 2 years AND has > 10 open security issues
2. Has been deprecated by its maintainer with a security advisory
3. Is a fork of a known package from an unknown publisher (typosquatting)
4. Has a name that's one character off from a popular package (e.g., `lodash` vs `1odash`)
5. Was recently transferred to a new owner (check git history / npm transfer notices)