This document outlines the security features and considerations for the Cloudflare Workers S3 Proxy.
The proxy supports URL signature validation for secure access control. When URL_SIGNING_SECRET is configured, all requests must include valid signatures to access protected resources.
The signature validation implementation follows AWS S3 Signature Version 4 standards for maximum compatibility and security:
-
RFC3986 Encoding: Parameter names and values are encoded using RFC3986 standard where:
- Spaces are encoded as
%20(not+) - Special characters
!'()*are percent-encoded - All other characters follow standard
encodeURIComponent()rules
- Spaces are encoded as
-
Parameter Sorting: Query parameters are sorted alphabetically by name (case-sensitive)
-
Trailing
?Handling: The canonical request only includes?when query parameters exist:- With parameters:
pathname?param1=value1¶m2=value2 - Without parameters:
pathname(no trailing?)
- With parameters:
Client-Side (using src/generate_signed_url.js):
// 1. Add expiration parameter
url.searchParams.set("exp", expirationTimestamp.toString());
// 2. Create canonical query string (excluding 'sig')
const canonicalQueryString = createCanonicalQueryString(url.searchParams, "sig");
// 3. Construct data to sign
const dataToSign = canonicalQueryString
? `${url.pathname}?${canonicalQueryString}`
: url.pathname;
// 4. Generate HMAC-SHA256 signature
const signature = await crypto.subtle.sign("HMAC", key, encoder.encode(dataToSign));Server-Side Verification:
- Identical canonical query string construction
- Same RFC3986 encoding rules
- Exact match of
dataToSignformat
The implementation returns appropriate HTTP status codes for different security scenarios:
- 403 Forbidden: Invalid or missing signatures, expired URLs, malformed signature format
- 401 Unauthorized: Reserved for other authentication methods (not signature validation)
This follows security best practices where signature validation failures are authorization issues (403), not authentication issues (401).
CRITICAL: Signature parameters (sig, exp) are automatically excluded from cache keys to ensure:
- Separate Caching: Signed and unsigned requests for the same content are cached together
- Cache Efficiency: Different signatures for identical content don't create unnecessary cache misses
- Security: Expired signatures cannot serve cached content inappropriately
- Attack Prevention: Cache poisoning via signature manipulation is prevented
// Security-aware cache key generation
const signatureParams = ["sig", "exp"]; // Excluded from cache keys
const cacheBustingParams = ["_", "bust", "nocache", "v", "version"];
const paramsToExclude = [...signatureParams, ...cacheBustingParams];URL_SIGNING_SECRET: Strong secret key for HMAC signature generation/verificationCACHE_PURGE_SECRET: Authentication token for cache purging operations
CORS_ALLOW_ORIGINS: Restrict cross-origin access to specific domains
- Path Traversal Protection: Comprehensive filename validation prevents directory traversal attacks
- Parameter Validation: All environment variables are validated with appropriate constraints
- Signature Format Validation: Hex signature format is strictly validated
- Information Disclosure Prevention: Error messages don't reveal internal system details
- Consistent Error Responses: All errors return JSON format for consistent handling
- Rate Limiting Ready: Metrics tracking supports future rate limiting implementation
- HMAC-SHA256: Industry-standard algorithm for signature generation
- Timing Attack Resistance: Uses
crypto.subtle.verify()for constant-time comparison - Key Management: Secrets are only accessed from environment variables
- Short Expiration Times: Use reasonable expiration windows (e.g., 1-24 hours)
- Secure Secret Management: Store
URL_SIGNING_SECRETsecurely in Cloudflare Workers secrets - Client-Side Mirroring: Ensure client-side generation exactly matches server validation
- Environment Isolation: Use different secrets for development/staging/production
- Secret Rotation: Regularly rotate
URL_SIGNING_SECRETand update clients - Monitoring: Monitor signature validation failures for potential attacks
- TTL Limits: Configure appropriate
CACHE_MIN_TTL_SECONDSandCACHE_MAX_TTL_SECONDS - Purge Controls: Restrict
CACHE_PURGE_SECRETto authorized personnel only - Debug Mode: Only enable
CACHE_DEBUGin development environments
# Set your secret
export URL_SIGNING_SECRET="your-secret-key"
# Generate signed URL
node src/generate_signed_url.js- Positive Tests: Valid signatures should return requested content
- Negative Tests: Invalid/expired signatures should return 403 errors
- Edge Cases: Test with various query parameters, special characters, and empty paths
- Signature Tampering: Modify signature - should return 403
- Expiration Testing: Use expired timestamp - should return 403
- Parameter Injection: Add extra parameters - signature should remain valid
- Cache Verification: Same content with different signatures should cache together
worker_errors_total: Monitor for unusual signature validation failuresworker_cache_hits_total/worker_cache_misses_total: Verify cache efficiencyworker_not_modified_responses_total: Track conditional request performance
- High rate of 403 errors (potential attack)
- Unusual geographic distribution of signature failures
- Cache purge requests from unauthorized sources
- Environment validation failures at startup