Fiverr used Cloudinary as both a PDF processor and an asset server for customer deliverables. The platform chose public, permanent URLs instead of signed, expiring ones. Hundreds of tax returns, contracts, and work products ended up indexed by Google and accessible to anyone who knew the URL pattern.
This is not a code vulnerability. It is an architectural choice that turned a CDN into an open directory.
What Happened
Fiverr routes customer files through Cloudinary for processing and delivery. Cloudinary supports signed URLs with expiration timestamps, but Fiverr configured public URLs instead. These URLs followed predictable patterns and were crawlable by search engines.
A security researcher discovered the exposure by searching:
site:fiverr-res.cloudinary.com form 1040
The query returned hundreds of completed tax returns, many containing Social Security numbers, income details, and preparer signatures. Fiverr also bought Google Ads for keywords like “form 1040 filing,” driving traffic to a platform that could not secure the resulting work product.
The researcher notified Fiverr’s security team 40 days before public disclosure. No response.
The Architecture Problem
Cloudinary is a media management platform. It ingests, transforms, and serves images, videos, and PDFs. Many platforms use it as a drop-in replacement for S3 with built-in processing.
Fiverr’s flow looked like this:
- Seller uploads deliverable (PDF, image, document) via Fiverr’s messaging interface
- Fiverr sends file to Cloudinary for processing (thumbnail generation, format conversion)
- Cloudinary returns a public URL
- Fiverr stores the URL in its database and displays it to the buyer
- The URL remains accessible indefinitely, with no authentication layer
The deterministic URL structure enabled enumeration. Once indexed by Google, files became searchable by content.
Why Platforms Choose Public URLs
Signed URLs add latency and complexity. Every file request requires:
- A database lookup to verify access permissions
- A signing operation (HMAC or RSA)
- A short-lived token embedded in the URL
- Client-side logic to refresh expired tokens
Public URLs skip all of this. The CDN serves the file directly from cache. No database round trip. No token generation. No expiration handling.
For high-traffic platforms, this trade-off looks attractive. Cloudinary charges per transformation and per bandwidth. Signed URLs do not increase transformation costs, but they do increase origin requests if tokens expire frequently.
The cost difference manifests in request latency (10-20ms per token generation and validation) and cache hit rates.
What Signed URLs Actually Cost
| Approach | Latency Overhead | Cache Efficiency | Enumeration Risk | Implementation Complexity |
|---|---|---|---|---|
| Public URLs | 0 ms | High (CDN serves directly) | High (predictable paths) | Low (static links) |
| Signed URLs (1 hour TTL) | 10-20 ms (token generation) | Medium (cache per token) | Low (tokens expire) | Medium (signing service) |
| Signed URLs (5 min TTL) | 10-20 ms | Low (frequent cache misses) | Very low | Medium |
| Pre-signed upload + private bucket | 20-30 ms (two-step flow) | High (CDN serves after auth) | None | High (separate upload/download flows) |
Fiverr chose the first row. The correct choice for sensitive deliverables is the fourth row.
The Correct File Upload Pipeline
Agent systems that generate or process customer files need three boundaries:
- Upload isolation: Clients get pre-signed upload URLs scoped to a specific file ID and user session
- Processing queue: After upload, a background worker validates, scans, and transforms the file
- Access control inheritance: Download URLs require authentication and respect the same permissions as the parent resource
Here is the flow in pseudocode:
# Step 1: Client requests upload permission
POST /api/deliverables/upload-url
{
"order_id": "abc123"
}
# Server verifies user owns this order, generates unique file ID
# Returns pre-signed upload URL (5 min expiry) and upload parameters
{
"upload_url": "https://api.cloudinary.com/v1_1/{cloud}/upload",
"params": {
"public_id": "private/{user_id}/{order_id}/{file_id}",
"timestamp": 1234567890,
"signature": "abc123...",
"upload_preset": "deliverables_private"
},
"file_id": "file_xyz"
}
# Step 2: Client uploads directly to Cloudinary
# The client uploads directly to Cloudinary using the pre-signed URL and form parameters.
# Step 3: CDN webhook triggers processing
POST /webhooks/cloudinary/upload-complete
{
"public_id": "private/{user_id}/{order_id}/{file_id}",
"secure_url": "https://res.cloudinary.com/..."
}
# Server verifies upload was expected, queues virus scan and validation
# Step 4: Client requests download permission
GET /api/deliverables/{file_id}/download
# Server verifies user can access this file
# Generates signed download URL (15 min expiry)
{
"download_url": "https://res.cloudinary.com/{cloud}/image/authenticated/s--signature--/v1/private/..."
}
This flow ensures:
- Upload URLs are scoped to a specific user and order
- Files land in a private namespace
- Download requires re-authentication
- URLs expire automatically
Multi-Tenant Storage Boundaries
Platforms handling user-generated content need to decide where to enforce isolation. Three common patterns:
Bucket-per-tenant: Each customer gets a dedicated S3 bucket or Cloudinary cloud. Strong isolation, but expensive at scale (AWS charges per bucket, Cloudinary charges per cloud).
Path-based isolation: All files in one bucket, but paths include tenant ID (/tenant-{id}/files/{uuid}). Requires careful IAM policies and prefix-based access control.
Randomized paths with access control: Files stored at random UUIDs, access controlled by application logic. Fastest, but requires a robust permission layer.
Fiverr used randomized paths without access control. The UUIDs prevented trivial enumeration, but Google’s crawler found the files anyway because Fiverr served public HTML that linked to them.
The Enumeration Attack Surface
Even with UUIDs, public URLs are vulnerable if:
- The platform embeds them in public pages (portfolio galleries, public profiles)
- Search engines index them
- Referrer headers leak them to third-party analytics
- Users share links on social media
Signed URLs with short expiration windows mitigate all of these. A leaked URL becomes useless after 15 minutes.
Correct Implementation Steps
- Use Cloudinary’s authenticated delivery: Files require a signature that includes the user’s session token
- Set aggressive expiration: 15-minute TTL for download URLs, 5-minute TTL for uploads
- Implement access control inheritance: Download permission checks the same rules as viewing the order
- Add robots.txt exclusions: Prevent search engines from indexing asset domains
- Monitor for leaked URLs: Alert when files are accessed without a valid referrer or session
The cost would have been 10-20ms per file request and a more complex client implementation. The benefit would have been avoiding a disclosure that exposed hundreds of tax returns.
GLBA Compliance Failure and FTC Safeguards Rule Violations
The HN thread notes that Fiverr actively advertises tax preparation services while failing to secure the resulting work product. Tax preparers are subject to the Gramm-Leach-Bliley Act (GLBA) and the FTC Safeguards Rule, which require administrative, technical, and physical safeguards for customer information.
Public, permanent URLs for tax returns fail this standard. Platform liability under GLBA does not depend on whether users consented to upload. The platform is responsible for safeguarding PII regardless of user intent.
Fiverr’s public response claimed that “content was shared by users in the normal course of marketplace activity to showcase work samples, under agreements and approvals between buyers and sellers.” This defense is legally insufficient. The FTC can impose civil penalties under 15 USC 6823 for violations of the Safeguards Rule. Each exposed tax return represents a separate compliance failure.
Technical Verdict
Use signed URLs when:
- Files contain PII, financial data, or customer work product
- The platform is multi-tenant
- Files are uploaded by users, not generated by your system
- Regulatory compliance requires access controls
Avoid signed URLs when:
- Files are truly public (marketing assets, open-source documentation)
- Latency is critical and files are non-sensitive
- You control all file generation and can guarantee no leaks
For agent systems that process customer deliverables, the correct pattern is pre-signed uploads, private storage, and signed downloads with short expiration. The latency cost is negligible compared to the risk of exposure.
Fiverr’s mistake was not a missing feature but a deliberate choice to optimize for convenience over security. The platform may face regulatory exposure under GLBA and a significant breach of customer trust in a market where reputation is the primary competitive advantage.
Source Links
- Hacker News Discussion (831 points, 232 comments)
- Cloudinary Authentication Signatures Documentation
- FTC Safeguards Rule (15 USC 6823)