File size: 2,920 Bytes
90e5963
 
 
 
 
 
 
 
 
 
 
dbd4e8b
90e5963
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# Security Analysis β€” Multilingual ABSA

## Current State

| Area | Status | Notes |
|------|--------|-------|
| JWT Authentication | ❌ Not implemented | No auth layer |
| OAuth | ❌ Not implemented | No SSO |
| HTTPS | ❌ Not enforced | Expects reverse proxy to terminate TLS |
| Input Validation | βœ… Partial | Pydantic validation present; no server-side max_length |
| SQL Injection | βœ… Protected | SQLAlchemy ORM parameterized queries |
| XSS | βœ… Protected | Streamlit dashboard; no raw HTML rendering, user input via native widgets |
| CSRF | ❌ Not implemented | No CSRF middleware; CORS `"*"` mitigates partially |
| Secrets Management | ⚠️ Manual | `.env` gitignored; Docker Compose has hardcoded dev creds |
| Rate Limiting | ❌ Not implemented | No throttling on any endpoint |
| File Upload Security | ⚠️ Partial | Extension validation; no size limit; temp files not cleaned on success |
| Authorization | ❌ None | No role-based or API-key access control |
| CORS | ⚠️ Permissive | `allow_origins=["*"]` |

## Risks & Recommendations

### Critical

1. **Missing authentication** β€” All endpoints are publicly accessible
   - **Fix**: Add FastAPI middleware for API key validation
   - **Fix**: Integrate OAuth2/OIDC for multi-user scenarios

2. **No rate limiting** β€” `/batch` endpoint can be abused (10K rows per request)
   - **Fix**: Add `slowapi` or custom rate-limiting middleware
   - **Fix**: Implement per-IP request quotas

### High

3. **Temp file leak** β€” Batch CSV saved via `NamedTemporaryFile(delete=False)` but `os.unlink()` only called on validation error, not on success
   - **Fix**: Add `try/finally` block to ensure cleanup

4. **CORS all origins** β€” `"*"` allows any website to call the API
   - **Fix**: Restrict to known dashboard domains

5. **No server-side text length limit** β€” `ReviewInput.text` accepts arbitrary length
   - **Fix**: Add `StringConstraints(max_length=512)` to Pydantic model

### Medium

6. **No file size limit on batch uploads** β€” Only row count limit (10K)
   - **Fix**: Add file-size check (e.g., 50MB max)

7. **Hardcoded credentials** in `docker-compose.yml` β€” `absa_user/absa_pass`
   - **Fix**: Use environment variables or Docker secrets

8. **CSRF** β€” No protection; token-based auth (when implemented) would mitigate

### Low

9. **Weak health check** β€” Returns `"db": "connected"` without actually pinging DB
   - **Fix**: Add actual DB ping to `/health` endpoint

10. **No request logging** β€” No structured logging or audit trail

## Configuration Checklist

- [ ] Set `ENABLE_METRICS` to `false` if Prometheus not needed
- [ ] Set `LOG_LEVEL` to `WARNING` in production
- [ ] Use strong, random passwords for PostgreSQL
- [ ] Run API behind TLS-terminating reverse proxy (Railway does this automatically)
- [ ] Keep `.env` out of version control (already in `.gitignore`)
- [ ] Rotate secrets regularly