Skip to content

fix: security, parallelization, observability, and DX overhaul#1

Open
aezakmixdxd wants to merge 1 commit into
ulsreall:masterfrom
aezakmixdxd:fix/security-quality-overhaul
Open

fix: security, parallelization, observability, and DX overhaul#1
aezakmixdxd wants to merge 1 commit into
ulsreall:masterfrom
aezakmixdxd:fix/security-quality-overhaul

Conversation

@aezakmixdxd
Copy link
Copy Markdown

Summary

Comprehensive security, performance, observability, and DX overhaul of ChainSentinel backend.

Verified locally: 17/17 tests pass, ruff lint clean, server boots, auth + rate limit confirmed via curl.

P0 — Security 🔴

  • CORS misconfiguration fixed: replaced allow_origins=["*"] + allow_credentials=True (invalid per spec, browsers reject) with env-driven ALLOWED_ORIGINS whitelist
  • API key authentication added via X-API-Key header on every /api/* endpoint (constant-time comparison, dev mode opt-in via AUTH_DISABLED=true)
  • Upload size enforced: streamed read with MAX_CONTRACT_SIZE_KB cap (was unbounded — DoS risk)
  • Input validation: code length, LOC count, UTF-8 decoding errors return proper HTTP codes

P1 — Reliability / Performance 🟠

  • True parallel agents: Phase 1 (vuln/gas/logic) now runs via asyncio.gather() instead of sequential for loop. Per-chunk analysis also parallelized — 3× speedup for long contracts.
  • Token tracker persistence: replays JSONL on startup so /stats survives restart (was in-memory only)
  • Configurable storage path: DATA_DIR env var (was hardcoded ~/projects/chainsentinel/..., broke in Docker)
  • Daily budget enforcement (BUDGET_ENFORCE): returns HTTP 429 instead of silent overspend
  • Rate limiting via slowapi (10/minute analyze, 2/minute batch, 30/minute chat — all configurable)

P2 — Observability / Quality 🟡

  • Structured logging (app.core.logging) replaces print()
  • Unhandled exception handler hides stack traces from clients
  • Tests added (17 cases):
    • test_validator.py — pragma, contract/interface/library, brace balance
    • test_pipeline.py — concurrency assertion via fake MiMo client, chunking edge cases, complexity scoring
    • test_token_tracker.py — persistence, budget enforcement, edge cases
  • ruff configured + GitHub Actions CI (lint + test + docker build)

P3 — Infra / DX 🔵

  • Dockerfile (non-root user, healthcheck, layer caching)
  • docker-compose.yml with frontend nginx
  • pyproject.toml (ruff config), pytest.ini (asyncio_mode=auto)
  • requirements.txt: removed unused tiktoken, added slowapi + dev deps (pytest, ruff)
  • .env.example expanded to document all knobs
  • /api/chat/stream endpoint exposing the existing stream_chat() (was unused)

Stats

Before After
Tests 0 17 ✅
Auth none X-API-Key + 401
Rate limit none slowapi 429
Phase 1 concurrency 1 (sequential) 3+ (parallel)
Lines changed +520 / -232

Verification

cd backend
pip install -r requirements.txt
ruff check app tests       # clean
AUTH_DISABLED=true pytest -q  # 17 passed

Smoke tested:

  • POST /api/analyze without key → 401
  • POST /api/analyze with valid X-API-Key200
  • 15 burst requests → first 9 return 200, remaining 429 (rate limit working)

Notes

  • Frontend (frontend/js/app.js) untouched; will need to send X-API-Key header when consuming the API. Suggest a follow-up PR for that.
  • netlify.toml redirect URL chainsentinel-api.onrender.com left as-is — should become a Netlify env var in a future change.
  • Breaking change for clients: all /api/* now require X-API-Key unless AUTH_DISABLED=true (dev only).

P0 — Security:
- Replace permissive CORS (allow_origins=*+credentials) with env-driven whitelist
- Add X-API-Key authentication via Depends(verify_api_key) on all /api endpoints
- Enforce upload size limit (MAX_CONTRACT_SIZE_KB) with streamed read
- Validate code size + LOC on /analyze and /batch-analyze

P1 — Logic / reliability:
- Phase 1 agents now run in true parallel via asyncio.gather (was sequential)
- Per-chunk analysis also parallelized inside each agent
- Token tracker: configurable DATA_DIR, replays JSONL on startup so stats survive restart
- Daily budget enforcement (BUDGET_ENFORCE) returns HTTP 429 instead of silently overspending
- Per-route slowapi rate limits + 429 handling

P2 — Observability / quality:
- Structured logging module (app.core.logging) replaces print()
- Unhandled exception handler hides stack traces from clients
- Tests: validator, pipeline (incl. concurrency assertion), token tracker (incl. persistence + budget)
- ruff config + GitHub Actions CI (lint + test + docker build)

P3 — Infra / DX:
- Dockerfile (non-root, healthcheck) + docker-compose with frontend nginx
- pyproject.toml with ruff, pytest.ini with asyncio_mode=auto
- Remove unused tiktoken; add slowapi, dev deps (pytest, ruff)
- Expand .env.example to document all knobs

Verified: 17/17 tests pass, ruff clean, server boots, auth + rate limit confirmed via curl.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant