mirror of
https://github.com/whit3rabbit/anyllm-proxy.git
synced 2026-09-21 16:00:49 +00:00
Rust workspace with two crates: - translator: pure, IO-free mapping between Anthropic Messages API and OpenAI Chat Completions - proxy: axum HTTP server with auth, streaming SSE, retry/backoff, concurrency limits 169 tests passing (unit, golden fixture, integration). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2.9 KiB
2.9 KiB
Security Audit
Authentication
Proxy Auth Boundary
- The proxy validates that requests carry either
x-api-keyorAuthorization: Bearerheader - The proxy does NOT verify the key value itself; it prevents accidental open proxying
- Client credentials are never forwarded to OpenAI
- OpenAI is always called with the server-configured
OPENAI_API_KEY
Recommendation
- For production, add key verification against an allowlist
- Consider mTLS or OAuth/JWT at the proxy edge for multi-tenant deployments
Request Size Limits
- 32 MB body limit enforced via axum's
DefaultBodyLimit - Matches Anthropic's documented Messages endpoint limit
- Prevents memory exhaustion from oversized payloads
SSRF Prevention
- The proxy only makes outbound HTTP requests to
OPENAI_BASE_URL(configured via env) - No user-controlled URLs are fetched:
- Image URLs in content are passed as text, not fetched
- Document blocks are converted to text notes, not processed
- No file download/upload proxying
Recommendation
- Validate
OPENAI_BASE_URLis not a private/internal address at startup - Consider URL allowlist for production
Secret Handling
OPENAI_API_KEYis read from environment (never hardcoded)redact_secret()utility available for logging (shows first/last 4 chars only)- Authorization headers are not logged
- Request bodies may contain sensitive content;
RUST_LOGshould beinfoin production
Concurrency Protection
- Tower
ConcurrencyLimitLayercaps at 100 concurrent requests - Prevents self-DOS during upstream 429 incidents
- Retry logic has exponential backoff to avoid hammering upstream
Header Filtering
- Inbound
x-api-keyandAuthorizationheaders are consumed, not forwarded anthropic-versionheader is accepted but not forwarded- Outbound requests only include
Authorization: Bearerwith server key x-request-idis generated/echoed for correlation
Streaming Security
- Bounded channel (capacity 32) prevents unbounded memory growth
- Client disconnect detected and upstream connection dropped
- No content buffering; deltas translated directly
Dependencies
- All dependencies are from crates.io (auditable)
- No
unsafecode in project source cargo auditshould be run in CI
OWASP Top 10 Relevance
| Risk | Status | Notes |
|---|---|---|
| Injection | Mitigated | No SQL/shell; JSON parsed via serde |
| Broken Auth | Partial | Auth presence checked; value not verified |
| Sensitive Data Exposure | Mitigated | Secrets redacted in logs; env-based config |
| XML External Entities | N/A | JSON only |
| Broken Access Control | N/A | Single-purpose proxy |
| Security Misconfiguration | Mitigated | Sensible defaults; env-based config |
| XSS | N/A | API-only, no HTML |
| Insecure Deserialization | Mitigated | Typed serde with strict schemas |
| Using Components with Known Vulns | Recommendation | Run cargo audit in CI |
| Insufficient Logging | Mitigated | Structured tracing with request IDs |