Security & threat model
This page is the long-form answer to "what does ViaductCDN actually see, and what should I trust you with?" Most CDNs hand-wave this. We don’t, because the value of a privacy-positioned product depends on customers being able to evaluate it cleanly. Plain English; no marketing varnish.
The core trust model in one sentence. We may not know who runs your site (anonymous-tier signup), and we may not know who the readers are (Tor delivery, circuit-ID hashing), but we do see your content in plaintext while it passes through our edge. The privacy story is anonymity, not confidentiality. If you need both, you add application-layer encryption.
What we see in flight
We are a TLS-terminating CDN. Bytes flowing through our edge during a request-response cycle are visible to us in plaintext, including:
- Full request URL paths and query strings.
- All HTTP headers, including Authorization, Cookie, and any custom headers your app sets.
- Request bodies — form POSTs, JSON payloads, file uploads, the lot.
- Response bodies — HTML, JSON, video segments, anything else you serve.
- The fact that a particular site is being accessed (the site ID and host).
This is the same trust position you give Cloudflare, Fastly, AWS CloudFront, or any other CDN that terminates TLS to cache content. The only way to avoid it would be a CDN that does not terminate TLS — which in practice means giving up caching and most of the value the CDN provides. We made the conscious choice to stay caching-capable and be transparent about the trust cost.
What we log to disk
We see in flight is not the same as we log to disk. Our explicit logging policy:
| Logged | Not logged |
|---|---|
|
|
Edge access logs retain the metadata above for 90 days for billing reconciliation and abuse triage. Administrative actions on accounts (sign-ins, configuration changes) are logged for 7 years per US business-records norms. Cryptocurrency deposit records are retained 10 years per US AML recordkeeping norms. Full breakdown on /privacy.
The non-logging is a policy commitment we operationally enforce, not an architectural constraint. We could log bodies if we changed our mind. We don’t.
What’s structurally hidden from us
The architectural pieces — what we genuinely cannot see, regardless of policy:
- Tor reader identity. When a reader uses Tor Browser to reach your .onion, the Tor circuit hides their IP from us. We see a circuit ID (which we hash before logging), nothing more. Different circuits = different observed identifiers, even from the same reader.
- Origin IP, when origin is a .onion. If your origin is itself a Tor hidden service (available on every tier), we fetch through Tor and the circuit hides your origin’s IP from us as much as it hides the reader’s. This is the only way to keep us from knowing where your origin lives.
- Operator identity, on the anonymous-tier signup. A tenant who signs up via the anonymous path (no email, no card) and pays in Monero is structurally unknown to us. We have a tenant handle, a hashed recovery phrase, and crypto deposit metadata — none of that ties to a person we’ve identified.
- Card numbers. Stripe handles the card payment side; they hold the card details, we hold a Stripe customer ID.
Origin auth secrets we hold
To proxy traffic to your origin, we hold whatever credentials your origin requires. These are stored in Azure Key Vault and mounted to edge pods via the CSI driver. They live in the trust class of secrets we explicitly accept responsibility for — meaning we treat them as load-bearing customer secrets, not just configuration. Per-customer:
- Origin pre-authenticated request URIs (PAR for OCI, SAS for Azure Blob) — if you give us a PAR/SAS-signed origin URL, we hold the URL itself. Anyone with the URL can fetch from your origin during the URL’s validity window. Rotate before our copy expires.
- Bearer tokens or basic-auth credentials — if your origin requires Authorization on the upstream request, we hold the token or credential and inject it as we proxy. We never log it.
- mTLS client certificates — if your origin requires client-cert authentication, we hold the cert + private key and present it on the upstream TLS handshake. We do not back it up outside Key Vault; replace if compromised.
- Custom headers — arbitrary fixed-value headers injected on each upstream request. Treated the same as bearer tokens.
- Per-site signed-URL signing secrets — if you use signed URLs to gate edge content, we hold the signing secret. We use it only to verify URLs you’ve generated; we don’t generate URLs on your behalf.
- Per-site password hashes — if you enable password-gated access on a site, we hold the bcrypt hash of the password (not the plaintext).
- Per-site Tor onion private keys — if you bring your own vanity .onion, we hold the private key in Key Vault. Tor needs the private key to publish the hidden service descriptor. The key is never displayed in the UI after upload; deletable at any time.
- Per-site alert webhook secrets — HMAC keys we use to sign outbound alert deliveries to your webhook receiver. Compromise of the key allows an attacker to forge alerts to your webhook (low blast radius, but worth knowing).
Operational protections on these secrets:
- Stored in Azure Key Vault with RBAC scoped to the edge service-principal only.
- Edge pods mount via the Secrets Store CSI driver; secrets are read-only and not in environment variables.
- Soft-delete + purge protection: a deleted secret is recoverable for the retention window; a malicious admin cannot permanently destroy it before then.
- Audit log: every administrative access to Key Vault is logged via Azure’s built-in audit.
What customers trust us with (the explicit list)
- Not snooping on bodies in flight, beyond what’s necessary to cache or proxy.
- Not exfiltrating the credentials or content we have access to.
- Not capitulating to legal overreach; pushing back on overbroad orders and publishing aggregate transparency annually (see /transparency).
- Not making policy changes silently; material changes go through 14-day notice.
- Acting on the rules we’ve published: we suspend sites for the abuse policy at /abuse and nothing else.
Mitigations available to customers
Customers who need confidentiality from us, not just anonymity, have options:
- End-to-end encryption at the application layer. If your app encrypts response bodies on the origin and decrypts them in the client (e.g., using a key that never traverses the CDN), we see ciphertext only. This breaks caching efficiency for the encrypted content but works for sensitive routes mixed in with cacheable static assets.
- Cache-bypass on sensitive routes. Configure paths that handle authentication or sensitive forms to bypass our cache with Cache-Control: private or by sending a Set-Cookie on the response. We still see them in flight; we just don’t persist anything (we already don’t log bodies, but cache-bypass narrows the surface further).
- Signed URLs. Restrict edge content access to pre-signed URLs your app generates. We still see the request, but the access-control logic stays at your origin.
- JWT-at-edge. Validate JWTs at the edge and gate requests without round-tripping to your origin for auth. We see the JWT (which is signed but not encrypted by default) and the origin response. Use it to reduce origin auth round-trips, not to hide content from us.
- Tor origin + Tor delivery. If both ends of the pipeline are .onion, our role is reduced to forwarding ciphertext at the TLS-terminator. We still see the ciphertext, but we don’t see the origin’s IP and we don’t see the reader’s IP.
Comparison to other CDNs
For TLS termination, we are in the same trust position as Cloudflare, Fastly, AWS CloudFront, Bunny, KeyCDN, and any other CDN that caches TLS-encrypted content. They all terminate TLS at the edge to do their job. The differences:
- We don’t require a card or email at signup for paid plans (cryptocurrency path). Other CDNs require both.
- We deliver over Tor as a first-class path, not a side feature. Reader anonymity is part of the product.
- We don’t log client IPs at all; most CDNs log full IPs by default.
- We tell you exactly what we see and log. The above enumerations are the contract. If you’re evaluating us against a CDN that won’t answer the same question this explicitly, that’s a difference worth noting.
Operational protections (high-level)
- Secrets at rest in Azure Key Vault (RBAC-restricted, audit-logged, soft-delete + purge protection).
- Pod-level least-privilege: edge pods read only the secrets needed for their assigned sites; portal pods have separate role-scoping for billing-class secrets.
- Internal audit log of every administrative action on customer accounts.
- Monitoring covers edge availability, error rates, and unusual patterns (large secret-access bursts, mass site mutations).
Bug bounty & vulnerability disclosure
We don’t run a formal bug-bounty program at launch. Email security@viaductcdn.com with reports. PGP key for sensitive disclosures is published on /transparency alongside the abuse-reports key. We commit to acknowledging within 5 business days and to not pursuing legal action against good-faith researchers who comply with this policy. A formal bounty program is on the roadmap once we have launch traffic to justify it.
Cross-references
- /privacy — data we collect, retention, customer rights
- /terms — service terms and your account responsibilities
- /abuse — abuse policy and reporting flow
- /transparency — annual aggregate stats and lawful-order summary (forthcoming)
Questions
Security questions: security@viaductcdn.com. General questions: support@viaductcdn.com.