Skip to content

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=secrets ou focus=injection pour deepdive spécifique.
  • Variante B — Dependency check only : Mode deps-only scanne seulement package.json.
  • Variante C — Scheduled audits : /schedule ed209-monthly pour 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ômeCause probableRésolution
Stack non détectéConfig files non-standardAjouter .js/.ts/.go manually via prompt
False positives (non-issue)Strings contenant “SECRET” mais pas secretsVérifier manuellement, réduire brute force
Database password not foundStored in CI/CD secrets, not in codeGood! But verify no backups or env files
Report too longTrop de findingsLimiter avec --max-findings=50

Voir aussi

  • agents/audit/52-ed209.md — agent complet
  • agents/_shared/checklists/security-checklist.md — checklist OWASP
  • agents/audit/45-sargeras.md — omniscient (includes security axis)
  • agents/audit/05-vision.md — audit code (includes security review)