3.8 KiB
3.8 KiB
AOC v1.7.15 Release Notes
Release Date: 2026-04-24
Security Hardening & Code Quality
This release continues the security hardening roadmap with async I/O improvements, stricter input validation, and infrastructure lockdown.
Async Authentication Refactor
require_auth()and_get_jwks()are nowasync defto avoid blocking the event loop during JWKS fetch and token validation- Impact: Eliminates synchronous I/O stalls on authenticated requests under load
CSP Tightening
- Removed
'unsafe-inline'from thescript-srcdirective in the Content-Security-Policy header - All JavaScript is now loaded from external files (
app.js) or trusted CDNs with SRI hashes 'unsafe-eval'is retained for Alpine.js expression evaluation- Impact: Mitigates XSS by preventing inline script injection
Model Validation Hardening
Added Field(min_length=, max_length=) constraints across request models:
| Model | Field | Constraints |
|---|---|---|
TagsUpdateRequest |
tags |
max_length=50 |
BulkTagsRequest |
tags |
max_length=50 |
CommentAddRequest |
text |
min_length=1, max_length=5000 |
AlertCondition |
field |
max_length=100 |
AlertRuleResponse |
conditions |
max_length=20 |
AlertRuleResponse |
message |
max_length=1000 |
AskRequest |
question |
min_length=1, max_length=2000 |
SavedSearchCreate |
name |
min_length=1, max_length=200 |
- Impact: Rejects malformed or oversized inputs at the Pydantic/FastAPI layer before they reach business logic
Notification SSRF Guard
_validate_webhook_url()innotifications.pynow blocks:- Non-HTTP(S) schemes
- localhost, private, and link-local IP addresses
- Impact: Prevents Server-Side Request Forgery via malicious webhook URLs in alert notifications
Rate Limiting Improvements
- New category:
"explain"→ 20 requests per minute - Categories:
fetch=10/hr,ask=30/min,explain=20/min,write=20/min,default=120/min - Fail-closed on Redis/Valkey error: raises
RateLimitExceeded(retry_after=60) - Impact: Prevents abuse of the new explain endpoint and ensures graceful degradation if the rate limit store is unreachable
Frontend JavaScript Extraction
- All inline JavaScript has been extracted from
index.htmlintobackend/frontend/app.js - Alpine.js SPA loads
/app.js?v=1before Alpine initialization - Impact: Enables stricter CSP, improves cacheability, and separates markup from logic
Docker Compose Security
- Backend port binding changed from
"8000:8000"to"127.0.0.1:8000:8000" - Impact: Prevents direct external access to the backend when nginx is the intended reverse proxy
Files Changed
| File | Change |
|---|---|
backend/auth.py |
require_auth() and _get_jwks() made async |
backend/main.py |
CSP tightened; startup warnings |
backend/models/api.py |
Added Field validation constraints |
backend/notifications.py |
SSRF guard for webhook URLs |
backend/rate_limiter.py |
Added "explain" rate limit category |
backend/routes/saved_searches.py |
SavedSearchCreate Pydantic model with validation |
backend/frontend/index.html |
Extracted inline JS to app.js |
backend/frontend/app.js |
New — extracted frontend JavaScript |
docker-compose.yml |
Backend port bound to 127.0.0.1 only |
nginx/nginx.conf |
Security headers alignment |
backend/tests/test_auth.py |
Updated for async require_auth() |
backend/tests/test_api.py |
Updated saved searches validation test |
backend/tests/test_ask.py |
Updated empty question test for 422 |
.gitignore |
Added memory/ |
VERSION |
Bumped to 1.7.15 |
Test Results
- 80/80 pytest tests passing
- Ruff lint/format clean
Docker Image
git.cqre.net/cqrenet/aoc-backend:v1.7.15