The PondPilot CORS proxy is designed with security and privacy as core principles.
Version 2.0 introduces comprehensive SSRF protection, domain allowlisting, and enhanced security controls.
- Forwards HTTP Requests: Acts as a transparent proxy for GET/HEAD requests
- Adds CORS Headers: Enables browser access to resources without CORS headers
- Validates Origins: Only allows requests from authorized PondPilot instances
- Rate Limiting: Prevents abuse through IP-based rate limiting
- Validates URLs: Ensures only allowed protocols and domains are accessed
- No Logging: Request URLs, content, and user data are NOT logged
- No Data Storage: No caching or storage of proxied data
- No Modification: Response data is passed through unmodified
- No Tracking: No analytics, cookies, or user tracking
- No Authentication: Does not store or transmit credentials
When using the official cors-proxy.pondpilot.io:
- β No request logging
- β No data retention
- β No user tracking
- β No analytics
- β Cloudflare's standard edge caching only
- β Source code is public and verifiable
When self-hosting:
- β Complete control over all data
- β Requests never leave your infrastructure
- β You control logging and monitoring
- β Open source - verify the code yourself
SSRF attacks attempt to use the proxy to access internal network resources. Version 2.0 implements comprehensive SSRF protection:
Private IP Blocking:
- β Loopback: 127.0.0.0/8 (localhost)
- β Private networks: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16
- β Link-local: 169.254.0.0/16 (AWS/GCP metadata!)
- β IPv6 private ranges
Blocked Hostnames:
- β localhost, 0.0.0.0
- β metadata.google.internal (GCP metadata)
- β Other cloud metadata endpoints
Example Blocked Requests:
# β Accessing AWS metadata (credential theft)
/proxy?url=http://169.254.169.254/latest/meta-data/
# β Accessing internal services
/proxy?url=http://127.0.0.1:3000/admin
# β Scanning internal network
/proxy?url=http://192.168.1.1/router-configDefault Allowlist (automatically applied):
- AWS S3:
*.s3.amazonaws.com,*.s3.*.amazonaws.com - CloudFront CDN:
*.cloudfront.net - GitHub:
*.github.io,*.githubusercontent.com - Google Cloud Storage:
*.storage.googleapis.com - Azure Blob Storage:
*.blob.core.windows.net - Common CDNs and data repositories
Custom Allowlist (optional):
# Self-hosted (.env)
ALLOWED_DOMAINS=*.s3.amazonaws.com,*.cloudfront.net,data.example.com
# Cloudflare Worker (wrangler.toml)
ALLOWED_DOMAINS = "*.s3.amazonaws.com,my-cdn.net"
# Leave empty to use secure defaults
ALLOWED_DOMAINS=Wildcard Pattern Semantics (
Version 2.0 introduces single-level wildcard matching for improved security:
*matches ONE subdomain level only (not multiple levels)- Pattern matching uses
[^.]*instead of.*to prevent subdomain traversal
Examples:
# Pattern: example.com
β
Matches: example.com
β Does NOT match: sub.example.com, api.example.com
# Pattern: *.example.com
β
Matches: sub.example.com, api.example.com
β Does NOT match: a.b.example.com, deep.sub.example.com
# Pattern: *.*.example.com
β
Matches: a.b.example.com, api.v1.example.com
β Does NOT match: x.y.z.example.com
# Pattern: data.*.gov
β
Matches: data.usa.gov, data.uk.gov
β Does NOT match: data.example.comMigration from v1.x: If you previously used wildcards expecting multi-level matching, you may need to add more specific patterns:
# Before (v1.x): *.example.com matched all depths
# After (v2.0): Need explicit patterns for each level
ALLOWED_DOMAINS=*.example.com,*.*.example.com,*.*.*.example.comSecurity Rationale: Single-level wildcards prevent accidental over-permissive patterns and ReDoS (Regular Expression Denial of Service) attacks.
New in 2.0: Optional credential forwarding for trusted sources.
By default, the proxy does NOT forward credentials (cookies, auth headers). Enable this only for fully trusted origins and data sources:
# Self-hosted (.env)
ALLOW_CREDENTIALS=true
# Cloudflare Worker (wrangler.toml)
ALLOW_CREDENTIALS = "true"- Only enable if both the client application (
ALLOWED_ORIGINS) and data source (ALLOWED_DOMAINS) are fully trusted - If an allowed data source has a vulnerability (e.g., reflects user input), it could be exploited
- Upstream
Set-Cookieheaders are blocked to prevent cookie hijacking - Enabling this increases risk and should only be used when absolutely necessary
Use Cases:
- Accessing authenticated APIs from browser-based applications
- Corporate environments with trusted internal data sources
- Development/testing scenarios with controlled domains
Best Practices:
- Use credential forwarding sparingly
- Restrict
ALLOWED_ORIGINSto specific, trusted origins (no wildcards) - Restrict
ALLOWED_DOMAINSto specific, trusted data sources - Regularly audit which domains are allowed
- Consider using a separate proxy instance for authenticated requests
Attack: Redirect to internal IP after validation
Protection:
- β
Redirect following is disabled (
redirect: 'manual') - β 3xx responses are rejected
- β Prevents DNS rebinding attacks
New in 2.0:
- Default: 30 seconds
- Prevents hanging connections
- Configurable via
REQUEST_TIMEOUT_MS
Production Mode:
- HTTPS-only by default
- Configurable via
HTTPS_ONLYenvironment variable - Prevents man-in-the-middle attacks
Only requests from whitelisted origins are allowed:
// Default allowed origins
const allowedOrigins = [
'https://app.pondpilot.io',
'http://localhost:5173', // Development only
];Prevents: Unauthorized sites from using the proxy
IP-based rate limiting prevents abuse:
- Default: 60 requests per minute per IP
- Configurable per deployment
- Cloudflare Worker: Uses Cloudflare's rate limiting API
- Self-hosted: Uses express-rate-limit
Prevents: DDoS attacks, excessive bandwidth usage
Only HTTPS (and HTTP for development) are allowed:
const allowedProtocols = ['https:', 'http:'];Prevents: Access to non-web protocols (file://, ftp://, etc.)
Maximum file size enforced (default: 500MB):
Prevents: Bandwidth exhaustion, memory issues
Strict allowlist of trusted data hosts with optional extensions:
ALLOWED_DOMAINS=*.example.com,datasets.govPrevents: Proxy abuse by restricting outbound requests to approved domains
The proxy does NOT forward:
- Authorization headers
- Cookies
- API keys
- Session tokens
Prevents: Credential leakage
| Threat | Mitigation |
|---|---|
| SSRF attacks | Private IP blocking, domain allowlist, redirect blocking |
| DNS rebinding | Domain allowlist validation before DNS resolution |
| Unauthorized access | Origin validation |
| DDoS / abuse | Rate limiting |
| Bandwidth exhaustion | File size limits, request timeouts |
| Open proxy abuse | Domain allowlist, origin validation |
| Credential theft | No auth header forwarding |
| Data exfiltration | Read-only operations, domain allowlist |
| Data logging | No logging policy |
| Threat | Why Not | Mitigation |
|---|---|---|
| MITM attacks on target | Not a proxy responsibility | Target should use HTTPS |
| Malicious targets | Users choose what to access | User responsibility |
| Client-side vulnerabilities | Not in proxy scope | PondPilot handles this |
- Accessing public data sources without CORS headers
- Loading public databases for analysis
- Accessing open datasets from S3, GitHub, etc.
- Educational and research purposes
- Accessing private or authenticated resources
- Circumventing access controls or paywalls
- Violating terms of service of target sites
- Illegal content or activities
- Spamming or abusive requests
- URL: Not logged (passed through only)
- Headers: Minimal forwarding, no auth headers
- IP Address: Used for rate limiting only, not logged
- Origin: Validated against whitelist, not stored
- Content: Streamed directly to client, not stored
- Headers: Forwarded with CORS additions
- Caching: Edge caching only (Cloudflare), no permanent storage
- No personal data collected
- No data retention
- No user tracking
- No cookies
- Official Service: Cloudflare global edge network
- Self-Hosted: Your infrastructure, your control
- Use HTTPS: Always access PondPilot over HTTPS
- Verify URLs: Only proxy public, trustworthy sources
- Check Connections: Use browser DevTools to verify proxy usage
- Self-Host: For maximum privacy, self-host the proxy
- Production Mode: Set
NODE_ENV=production - HTTPS Only: Set
HTTPS_ONLY=trueand use reverse proxy with SSL/TLS - Domain Allowlist: Configure
ALLOWED_DOMAINSor use secure defaults - Firewall: Block outbound access to private IP ranges at network level
- Updates: Keep Node.js and dependencies updated
- Monitoring: Monitor for unusual traffic patterns and blocked requests
- Rate Limiting: Adjust
RATE_LIMIT_REQUESTSbased on your needs
- Self-Hosted: Check logs and block offending IPs
- Official Service: Report to [email protected]
Please report security issues to:
- Email: [email protected]
- Subject: "CORS Proxy Security Issue"
We'll respond within 48 hours.
All code is open source and available for inspection:
No Hidden Features
- No telemetry
- No hidden logging
- No backdoors
- What you see is what runs
Before deploying to production, verify:
-
NODE_ENV=productionis set -
HTTPS_ONLY=trueis configured -
ALLOWED_ORIGINSis restricted to your domain(s) -
ALLOWED_DOMAINSis configured (or using secure defaults) - Rate limiting is enabled and configured
- HTTPS is enforced at reverse proxy/CDN level
- Firewall rules block outbound access to private IP ranges
- Monitoring and alerting is configured
- Dependencies are up to date
- Test SSRF protection with blocked IPs
This security policy is reviewed and updated:
- After any security incident
- When new features are added
- At least quarterly
Last updated: October 22, 2024 Version: 2.0.0
For security questions or concerns:
- Email: [email protected]
- GitHub Issues: Report an issue