DOC
Audit sécurité exhaustif avec ED-209
Audit applicatif 10 axes (secrets, injection, auth, autorisation, dépendances, config serveur, RGPD, uploads, rate limiting, logging)
Audit sécurité exhaustif avec ED-209
Contexte
Vous avez un codebase et vous voulez un audit sécurité exhaustif avant production. ED-209 analyse 10 axes de sécurité (OWASP Top 10, CWE, hardcoded secrets, injection, etc.), produit un rapport structuré avec criticité, fichier:ligne, et remédiation concrète.
Prérequis
- Codebase accesible (CLI ou mounted)
- Accès Read complet
- Git history disponible (pour analyse dépendances)
docs/reports/sera créé pour rapports
Étapes
1. Invocation audit sécurité
Lancez ED-209 :
/ulk:ed209
ou
Audit sécurité complet
ED-209 démarre Phase 0 (Détection automatique du projet).
2. Phase 0 — Détection du stack
ED-209 exécute :
PROJECT_NAME=$(basename $(pwd))
[ -f "package.json" ] && LANG="javascript"
[ -f "go.mod" ] && LANG="go"
[ -f "Cargo.toml" ] && LANG="rust"
grep -l 'django' requirements.txt && FRAMEWORK="django"
Sortie :
=== Détection Sécurité ===
💻 Language : TypeScript/Node.js
🎯 Framework : Next.js + Express
🗂️ Entry points: pages/, api/routes/
🔐 Auth type : JWT (detected from code)
3. Phase 1 — Secrets hardcodés (OWASP M1)
ED-209 scanne :
grep -r "API_KEY\|PASSWORD\|SECRET\|TOKEN" . --include="*.js" --include="*.ts" --include="*.env*" --include="*.json" | grep -v node_modules
Résultat :
❌ CRITICAL FINDINGS : Hardcoded Secrets
[api/routes/auth.ts:42]
const API_KEY = "sk-proj-1234abcd..." ← Should be process.env.API_KEY
Type: OpenAI API key
Severity: CRITICAL
CWE: CWE-798 (Use of Hard-coded Credentials)
OWASP: M1 (Insecure Storage)
[config/.env.backup:5]
DATABASE_PASSWORD="postgres123"
Type: Database password
Severity: CRITICAL
[src/integrations/stripe.ts:12]
stripe_key = "sk_live_abcdef1234..."
Type: Stripe live key
Severity: CRITICAL
OWASP: M8 (Code Obfuscation)
Remediation:
[ ] Move all secrets to environment variables (process.env)
[ ] Rotate exposed keys immediately (stripe, OpenAI, DB)
[ ] Remove .env.backup from repo
[ ] Add .env, .env.* to .gitignore
[ ] Use AWS Secrets Manager / HashiCorp Vault for production
4. Phase 2 — Injection SQL & XSS (OWASP A3, A1)
⚠️ HIGH FINDINGS : SQL Injection & Command Injection
[api/routes/users.ts:28]
const query = `SELECT * FROM users WHERE id = ${req.query.id}`
↑ Vulnerable to SQL injection
OWASP: A1 (Injection)
CWE: CWE-89 (SQL Injection)
Remediation:
Use parameterized queries:
const query = 'SELECT * FROM users WHERE id = $1'
const result = await db.query(query, [req.query.id])
[pages/profile.tsx:55]
<div dangerouslySetInnerHTML={{__html: userBio}} />
↑ Vulnerable to stored XSS
OWASP: A3 (Injection)
CWE: CWE-79 (Cross-site Scripting)
Remediation:
Use DOMPurify or React sanitize:
import DOMPurify from 'dompurify'
<div>{DOMPurify.sanitize(userBio)}</div>
5. Phase 3 — Authentification & autorisation (OWASP A2, A7)
❌ HIGH FINDINGS : Weak Authentication & Authorization
[api/middleware/auth.ts:10]
const token = jwt.decode(authHeader) ← No signature verification!
OWASP: A2 (Broken Authentication)
CWE: CWE-347 (Improper Verification)
Remediation:
Use jwt.verify with secret:
const token = jwt.verify(authHeader, process.env.JWT_SECRET)
[api/routes/admin.ts:5]
if (user.role === 'admin') { /* grant access */ }
↑ No explicit permission checks
OWASP: A7 (Broken Access Control)
CWE: CWE-639 (Authorization Bypass)
Remediation:
Implement explicit RBAC:
if (!hasPermission(user, 'admin:delete')) throw Unauthorized()
[public/api/v1/users.ts:20]
app.get('/users/:id', (req, res) => {
res.json(User.findById(req.params.id)) ← No auth check!
})
Missing authentication entirely
OWASP: A2 (Broken Authentication)
Remediation:
Add auth middleware:
app.get('/users/:id', requireAuth, (req, res) => { ... })
6. Phase 4 — Dépendances vulnérables (OWASP A6)
⚠️ MEDIUM FINDINGS : Vulnerable Dependencies
package.json vulnerabilities detected:
express 4.17.1 → Update to 4.18.2+ (CVE-2022-24999)
Severity: HIGH
Issue: Denial of Service via regex in query string
Fix: npm audit fix --force
lodash 4.17.15 → Update to 4.17.21+ (CVE-2021-23337)
Severity: MEDIUM
Issue: Prototype pollution
Fix: npm update lodash
mysql2 1.6.0 → Update to 2.3.0+ (CVE-2021-21261)
Severity: HIGH
Issue: SQL injection in named placeholders
Fix: npm update mysql2
Command:
npm audit fix (fix automatically)
npm audit (show all vulnerabilities)
Dependencies with "any" version constraint:
axios: "*" ← Should pin to exact version
Fix: "axios": "^1.4.0"
7. Phase 5 — Configuration serveur & TLS
⚠️ MEDIUM FINDINGS : Server Configuration
[next.config.js:1]
module.exports = {
poweredByHeader: true, ← Reveals server type
OWASP: A1 (Information Disclosure)
}
Remediation:
poweredByHeader: false (hide X-Powered-By header)
[.env.production:1]
DATABASE_URL="postgresql://user:pass@prod-db.internal"
↑ Plain HTTP connection risk (depends on network)
OWASP: M5 (Insecure Communication)
Recommendation: Use TLS for all DB connections
HTTP vs HTTPS:
HTTP endpoints detected:
[api/auth.ts:15] http://payment-gateway.test (dev OK, but insecure)
OWASP: M5 (Insecure Communication)
Recommendation: All production URLs must be HTTPS
SSL/TLS Certificate:
If applicable (e.g., web service):
✅ HTTPS enabled
✅ Certificate valid (expires 2026-12-31)
⚠️ Consider cert pinning for mobile app
8. Phase 6 — RGPD & données personnelles
⚠️ MEDIUM FINDINGS : GDPR Compliance (OWASP M9)
Data processing:
User emails stored:
[models/User.ts:5] email: String
Regulation: GDPR Article 6 (Lawful basis required)
Question: Consent mechanism present? [ ] Yes [ ] No
Remediation: Implement consent banner if not present
User location data:
[api/tracking.ts:12] ip_address, browser_fingerprint stored
Regulation: GDPR Article 32 (Security measures)
Question: Encrypted at rest? [ ] Yes [ ] No
Remediation: Enable database encryption (TDE, AES-256)
Data retention policy:
No deletion schedule found
Regulation: GDPR Article 17 (Right to be forgotten)
Remediation: Implement data deletion after X days (30/90/365)
Subprocessors:
Third-party APIs detected:
- Stripe (payments) ← Needs DPA (Data Processing Agreement)
- SendGrid (email) ← Needs DPA
- Auth0 (identity) ← Needs DPA
Recommendation: Verify all DPAs are signed
Remediation:
[ ] Add privacy policy link in footer
[ ] Implement consent banner (CookieBot, Termly)
[ ] Enable database encryption
[ ] Create data retention/deletion policy
[ ] Sign all DPAs with subprocessors
9. Phase 7 — Upload de fichiers (OWASP A4)
❌ HIGH FINDINGS : Insecure File Upload
[api/routes/upload.ts:20]
app.post('/upload', async (req, res) => {
const file = req.files.upload
fs.writeFileSync(`public/uploads/${file.name}`, file.data)
})
↑ Vulnerable to arbitrary file upload
OWASP: A4 (Insecure File Upload)
CWE: CWE-434 (Unrestricted Upload of File with Dangerous Type)
Issues:
1. No file type validation
2. No extension whitelist
3. No file size limit
4. Stored in web-accessible directory
Remediation:
[ ] Whitelist allowed extensions: ['.pdf', '.jpg', '.png']
[ ] Check MIME type server-side
[ ] Limit file size to 10MB
[ ] Store in non-web-accessible directory
[ ] Rename files to random UUID (prevent path traversal)
[ ] Scan with antivirus (ClamAV) before storage
Example:
const ALLOWED_TYPES = ['image/jpeg', 'image/png', 'application/pdf']
if (!ALLOWED_TYPES.includes(file.mimetype)) throw BadRequest()
if (file.size > 10 * 1024 * 1024) throw BadRequest()
const filename = `${uuid()}.${ext}`
10. Phase 8 — Rate limiting (OWASP A7)
❌ HIGH FINDINGS : Missing Rate Limiting
[api/routes/auth.ts:1]
app.post('/login', async (req, res) => { ... })
↑ No rate limiting on login endpoint
OWASP: A7 (Broken Access Control)
CWE: CWE-770 (Allocation of Resources Without Limits)
Attack: Brute force login attempts (no limit on failed attempts)
Remediation:
Use express-rate-limit:
const rateLimit = require('express-rate-limit')
const loginLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 5, // 5 attempts
message: 'Too many login attempts, try again later'
})
app.post('/login', loginLimiter, (req, res) => { ... })
Other endpoints needing rate limiting:
[ ] /api/register (sign up)
[ ] /api/password-reset (brute force email enumeration)
[ ] /api/verify-otp (OTP brute force)
Recommendation: Add global rate limiting with redis for production
11. Phase 9 — Logging & monitoring
⚠️ MEDIUM FINDINGS : Insufficient Logging
Current logging:
console.log() → Not suitable for production
No log aggregation (ELK, CloudWatch, etc.)
No audit trail for security events
Missing security logs:
[ ] Login attempts (success & failure)
[ ] Permission denials
[ ] API errors
[ ] File access
[ ] Admin actions
Remediation:
[ ] Add winston/bunyan logger (with log levels)
[ ] Send logs to CloudWatch / DataDog / ELK
[ ] Log authentication events (user, timestamp, success/failure)
[ ] Implement audit trail for sensitive actions
[ ] Monitor for suspicious patterns (failed logins, etc.)
Example:
logger.info('User logged in', { userId, timestamp, ip })
logger.error('Failed login attempt', { email, ip, timestamp })
12. Phase 10 — CORS & autres headers
⚠️ MEDIUM FINDINGS : Insufficient HTTP Headers
[next.config.js]
Missing security headers:
[ ] Content-Security-Policy (CSP)
Prevents XSS by restricting script sources
Recommendation: "default-src 'self'"
[ ] X-Frame-Options
Prevents clickjacking
Recommendation: "DENY" or "SAMEORIGIN"
[ ] X-Content-Type-Options
Prevents MIME type sniffing
Recommendation: "nosniff"
[ ] Strict-Transport-Security (HSTS)
Forces HTTPS
Recommendation: "max-age=31536000; includeSubDomains"
CORS configuration:
[api/_cors.ts:3]
app.use(cors({ origin: '*' }))
↑ Too permissive
OWASP: A5 (Broken Access Control)
Remediation:
Change to:
app.use(cors({
origin: ['https://mysite.com', 'https://app.mysite.com'],
credentials: true
}))
Headers to add:
const headers = {
'Content-Security-Policy': "default-src 'self'",
'X-Frame-Options': 'DENY',
'X-Content-Type-Options': 'nosniff',
'Strict-Transport-Security': 'max-age=31536000'
}
13. Rapport final
ED-209 produit résumé :
=== ED-209 SECURITY AUDIT ===
Date: 2026-04-14
Project: my-app (Next.js + Node.js)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
FINDINGS SUMMARY
CRITICAL (3)
1. Hardcoded API keys (OpenAI, Stripe)
2. SQL injection in /users endpoint
3. Missing JWT signature verification
HIGH (5)
4. Stored XSS in profile page
5. Vulnerable dependencies (express, lodash)
6. No file upload validation
7. Missing rate limiting on login
8. CORS too permissive
MEDIUM (8)
[... 8 medium findings ...]
Total findings: 16 (3 CRITICAL, 5 HIGH, 8 MEDIUM)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
REMEDIATION TIMELINE
Immediate (Day 1):
[ ] Rotate all hardcoded API keys
[ ] Fix SQL injection (parameterize queries)
[ ] Enable JWT verification
This week (by Friday):
[ ] Fix XSS in profile page
[ ] Update vulnerable dependencies
[ ] Add file upload validation
[ ] Add rate limiting to auth endpoints
Next sprint:
[ ] Add GDPR compliance (consent, retention)
[ ] Implement logging & monitoring
[ ] Add security headers
Estimated effort: 2-3 weeks (1-2 devs)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
PRODUCTION READINESS
🔴 NOT READY FOR PRODUCTION
Must fix CRITICAL issues before deploying.
Recommend fixing at least HIGH severity as well.
After remediation: PRODUCTION READY
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
FILES CREATED
docs/reports/
├── ed209-security-audit-YYYYMMDD.md (full report)
├── security-findings.json (structured for tooling)
├── remediation-checklist.md (to-do list)
└── cwe-mapping.csv (CWE cross-reference)
Variantes
- Variante A — Focus security axis : Mode
focus=secretsoufocus=injectionpour deepdive spécifique. - Variante B — Dependency check only : Mode
deps-onlyscanne seulementpackage.json. - Variante C — Scheduled audits :
/schedule ed209-monthlypour audit automatique. - Variante D — Post-fix verification : Re-run after remediations pour confirmation.
Agents enchaînés
Flux typique : ed209 (52) security audit → sargeras (45) omniscient → vision (05) code audit.
Troubleshooting
| Symptôme | Cause probable | Résolution |
|---|---|---|
| Stack non détecté | Config files non-standard | Ajouter .js/.ts/.go manually via prompt |
| False positives (non-issue) | Strings contenant “SECRET” mais pas secrets | Vérifier manuellement, réduire brute force |
| Database password not found | Stored in CI/CD secrets, not in code | Good! But verify no backups or env files |
| Report too long | Trop de findings | Limiter avec --max-findings=50 |
Voir aussi
agents/audit/52-ed209.md— agent completagents/_shared/checklists/security-checklist.md— checklist OWASPagents/audit/45-sargeras.md— omniscient (includes security axis)agents/audit/05-vision.md— audit code (includes security review)