This document describes security considerations and important behavioral changes for Trove operators.
Trove has migrated from gorilla/csrf to filippo.io/csrf (v0.2.1) for CSRF protection. This migration addresses a security vulnerability in the gorilla/csrf package and implements modern browser security features.
The gorilla/csrf package has known security issues and is no longer actively maintained. The filippo.io/csrf package provides:
- Fetch Metadata-based protection: Uses modern browser headers (
Sec-Fetch-Site,Sec-Fetch-Mode) instead of tokens - Better security model: Fundamentally addresses CSRF as a browser-specific issue
- Reduced complexity: No token management, rotation, or synchronization required
Normal browser interactions work seamlessly:
| Scenario | Result |
|---|---|
| Same-origin form submissions | ✅ Allowed |
| Same-origin AJAX requests | ✅ Allowed |
| Direct navigation (bookmarks, URL bar) | ✅ Allowed |
| Cross-origin requests from malicious sites | ❌ Blocked |
Non-browser clients are handled differently:
| Client Type | Behavior | Notes |
|---|---|---|
| CLI tools (curl, wget) | ✅ Allowed | No Sec-Fetch headers = non-browser |
| API clients (requests, axios) | ✅ Allowed | Session auth still required |
| Mobile apps | ✅ Allowed | Use session cookies or API auth |
| Server-to-server | ✅ Allowed | No browser headers present |
| Webhooks | ✅ Allowed | External callbacks work |
Key Insight: The absence of Sec-Fetch-Site header indicates a non-browser client, which cannot be exploited for CSRF attacks (CSRF requires a browser to carry cookies automatically).
filippo.io/csrf is stricter than gorilla/csrf for same-site requests.
Requests with Sec-Fetch-Site: same-site (e.g., from subdomains) are blocked.
Affected Scenarios:
- Form submissions from
api.example.comtoexample.com - AJAX from
cdn.example.comtoapp.example.com
Workarounds:
- Ensure all requests come from the same origin (not just same site)
- Use API endpoints that are exempt from CSRF (see below)
- Use non-browser clients for cross-subdomain operations
CSRF tokens have been removed from templates. The filippo.io/csrf library:
- Does NOT use token-based validation
- Protection is solely based on Fetch Metadata headers
- Hidden
csrf_tokenform fields are no longer rendered - JavaScript no longer needs to extract or send tokens
If your application relied on extracting/validating CSRF tokens programmatically, those patterns are no longer applicable.
The following endpoints are intentionally exempt from CSRF middleware to support non-browser clients:
| Endpoint | Method | Reason |
|---|---|---|
/upload |
POST | Streaming multipart uploads |
/api/uploads/init |
POST | Chunked upload initialization |
/api/uploads/{id}/chunk |
POST | Chunk upload |
/api/uploads/{id}/complete |
POST | Upload completion |
/api/uploads/{id} |
DELETE | Upload cancellation |
/api/uploads/{id}/status |
GET | Upload status (read-only) |
/api/files/status |
GET | SSE status stream (read-only) |
These endpoints rely on:
- Session-based authentication (
RequireAuthmiddleware) SameSite=Laxcookie policy
CSRF protection can be disabled entirely via environment variable:
CSRF_ENABLED=false # Default: trueWarning: Disabling CSRF is not recommended for production deployments.
The migration includes comprehensive integration tests in internal/middleware/middleware_integration_test.go:
TestCSRFProtection: Basic browser scenariosTestCSRFNonBrowserClients: CLI, API, webhook, mobile app scenariosTestCSRFBrowserBehavior: Cross-site attack preventionTestCSRFTokenBehavior: Token deprecation verification
Run tests:
go test -v ./internal/middleware/... -run "TestCSRF"- Check
Sec-Fetch-Siteheader: If present ascross-siteorsame-site, the request will be blocked - Verify Origin: Mismatched Origin headers (even without Sec-Fetch-Site) are rejected
- Use browser DevTools: Network tab shows all headers being sent
Ensure your client is NOT sending browser-like headers:
- Remove
Sec-Fetch-Siteheader if manually set - Ensure
Originheader matches the target server (or omit it)
Options:
- Configure your application to serve from a single origin
- Use the CSRF-exempt API endpoints
- Implement custom authentication for cross-subdomain flows
- Session Security: All protected endpoints still require valid session authentication
- Cookie Policy: SameSite=Lax cookies prevent cross-site request forgery at the cookie level
- Rate Limiting: Authentication endpoints remain rate-limited (5 attempts/15 minutes)
- HTTPS: Production deployments should always use HTTPS