Repository navigation
fix(security): rate-limit follow-ups v2 — alert rule, fail-fast env gate, dependency removal, dead code (card 5221c63f) - #282
Conversation
Identical change to the one already open in #270: the old `-r src -f json` args made pre-commit append staged .py files as targets, which bandit's argparse rejects — blocking every .py commit. Applying it here too so this branch's hooks run for real; both changes are byte-identical and merge cleanly.
…sts (card 5221c63f) Fires on rate_limit_backend_failures_total > 0 for 1m (severity warning): the security condition for the default-open rate-limiter fail mode in BETA. Safe pre-merge: the counter arrives with the F-1 line and an absent series never fires. Tests validate rule presence, expression, severity/for and alert-name uniqueness.
…nd pre-deploy (card 5221c63f) New scripts/validate_rate_limit_fail_mode.py rejects any value other than open|closed (case/whitespace tolerant, mirroring the middleware's strip().lower()) across tracked compose files — a typo like 'cloed' previously fell silently back to open. Wired as a blocking step in pr-checks.yml and as Check 15 in scripts/pre-deploy-check.sh.
…d 5221c63f) Zero usages on current main (grep Depends(check_rate_limit) = 0). RateLimitMiddleware is the single live mechanism; the dependency (and the untested 503 branch that only ever existed on the superseded PR #106 line, never ported to F-1) only offered an untested second path. Advisory resolved as 'remove' per card option. Also strips pre-existing trailing whitespace so hooks pass.
…21c63f) granular_rate_limiting.py (188 lines) and rate_limiting.py (33 lines): zero importers on current main, re-verified before deletion. Supersedes the same deletions already present in PR #270 (both-delete resolves cleanly). CHANGELOG updated for all four card items.
PR Check Results✅ Code Formatting: Failed |
|
| Severity | Count |
|---|---|
| 🔴 CRITICAL | 0 |
| 🟠 HIGH | 47 |
| Total | 47 |
Scans performed:
- 📁 Filesystem (vulnerabilities, secrets, misconfigurations)
- 🐳 Backend Docker image
- 🐳 Frontend Docker image
- 🏗️ IaC misconfiguration detection
📋 View detailed SARIF reports
Download artifacts from this workflow run for full SARIF reports.
Results are also available in the GitHub Security tab.
Trivy v0.71.0 | aquasecurity/trivy
PR Check Results✅ Code Formatting: Passed |
🔧 Backend Preview DeploymentApp Coolify: qa-framework-backend-pr-282 ( Preview interna (sin FQDN público hasta decisión de proxy — card 52a85645). |
🎨 Frontend Preview DeploymentApp Coolify: qa-framework-frontend-pr-282 ( Preview interna (sin FQDN público hasta decisión de proxy — card 52a85645). |
🧹 Single-latest preview policyTesting completo en verde sobre la preview de PR #282 → previews anteriores eliminadas (apps Coolify + imágenes del registry local). Solo queda viva la más nueva. |
🧹 Preview CleanupPR #282 - Merged ✅ Preview apps eliminadas de Coolify (verificado via API): backend + frontend. Resources freed at 2026-10-13T00:14:12.874Z |
Re-scope 01-oct (review batch): reemplaza a #264
Base nueva:
origin/main@ 8d9f5cb (la base de #264,fix/rate-limit-fail-open@ 33bfeef, quedó obsoleta al cerrarse #106 como superseded — su contenido vive en la línea F-1 de #270). Este PR sustituye a #264 (cerrable como superseded).Relación con #270 (línea F-1→F-7, OPEN): desacoplado a propósito — este PR no toca los mismos hunks salvo los deletes de dead code (both-delete idéntico, merge limpio). La métrica
rate_limit_backend_failures_totalllega a main vía #270; la alerta es safe pre-merge (serie ausente = nunca dispara). El fix del hook bandit en pre-commit es byte-idéntico al de #270.Los 4 items (card 5221c63f)
1. Alerta Prometheus
RateLimitBackendFailures+ testsrate_limit_backend_failures_total > 0, severity warning,for: 1m, endashboard/monitoring/prometheus/alerts/qa-framework-alerts.yml(el fichero cableado enprometheus.yml→rule_files).dashboard/backend/tests/unit/test_alert_rules.py— presencia, expr, severity/for, unicidad de nombres de alerta.2. Fail-fast de
RATE_LIMIT_FAIL_MODEen deploy/CI (L-A security)scripts/validate_rate_limit_fail_mode.py: valida el valor en los compose trackeados (open|closed, tolerante a case/whitespace igual que el middlewarestrip().lower()). Typocloed→ error claro con valor, fichero y valores permitidos, exit 1.pr-checks.yml(job raíz) + Check 15 enscripts/pre-deploy-check.sh.tests/unit/test_validate_rate_limit_fail_mode.py(6 casos, incl. compose unparsable y multi-fichero).3.
check_rate_limit: eliminada con justificación (opción B de la card)grep Depends(check_rate_limit)= 0). El branch 503 sin test que motivó el advisory nunca existió en main ni en la línea F-1 (solo en el PR fix(security): rate-limit fail-open hardening — metric, degraded header, configurable fail-closed (OBS-1) #106/fix(security): rate-limit follow-ups — alert rule, fail-fast env, dependency tests, dead code (card 5221c63f) #264 superseded; el puerto 4c4388f solo llevó métrica+header+short-circuit).RateLimitMiddlewarees el único mecanismo vivo; mantener una dependency sin wiring ofrecía un segundo camino sin tests. Deletion > test de dead code.4. Dead code borrado (0 imports re-verificado sobre ESTA base)
middleware/granular_rate_limiting.py(188L) ymiddleware/rate_limiting.py(34L):grepde importadores sobre el árbol actual = 0 antes de borrar. 🚀 [GO Joker 01-oct] Línea F-1→F-7 → main (F-123 0697a60 + F-6/F-7 47205d6) #270 ya los borra también (both-delete).Commits
chore(ci): pre-commit bandit fix (alineado byte a byte con 🚀 [GO Joker 01-oct] Línea F-1→F-7 → main (F-123 0697a60 + F-6/F-7 47205d6) #270 — el hook antiguo bloqueaba todo commit .py)feat(monitoring): item 1feat(deploy): item 2refactor(rate-limit): item 3chore(cleanup): item 4 + CHANGELOGVerificación local
tests/middleware+tests/unit/test_alert_rules.py→ 47 passed.tests/unit/test_validate_rate_limit_fail_mode.py→ 6 passed.bash -npre-deploy OK.test_browser_use_agent_013_runtime(entorno local; en CI pasan) y 3 wiring 403-vs-401 locales (idem, 🚀 [GO Joker 01-oct] Línea F-1→F-7 → main (F-123 0697a60 + F-6/F-7 47205d6) #270 verde en CI con los mismos).Conflictos conocidos
#270reescriberate_limit.py: mi borrado del tail (check_rate_limit) puede pedir resolución trivial al mergear 🚀 [GO Joker 01-oct] Línea F-1→F-7 → main (F-123 0697a60 + F-6/F-7 47205d6) #270 después. Los deletes de dead code y el fix bandit son idénticos (limpios).NO mergear desde aquí — gate de Alfred (card 5221c63f).