Back to Blog

Vyso Blog

How to Secure Private Images and Stop Hotlinking on Your Website

Updated October 5, 2026
Technical Deep Dives

An internal draft, a customer upload and a public product photo need different access rules. A customer image may belong behind an authorization check. The product photo may need to appear in search results and partner pages, even while you want to reduce unwanted use of your bandwidth.

Private delivery asks who may fetch the image. Hotlink protection asks which website or context may embed its URL. Scraping concerns programmatic downloads. Redistribution concerns what happens after someone receives the file. Treating all four as “image security” makes it easy to apply a control that solves the wrong problem.

Management authentication, private media delivery, hotlink protection and rights enforcement are separate boundaries. A login to a DAM or dashboard does not make its media URLs private.

Understanding the risk of public URLs

A publicly reachable image URL can be requested directly unless the serving layer performs another access check. Someone who receives the URL can open it without passing through the page where you originally displayed the image.

For example, a customer signs in to view an upload. The page loads the image from a public CDN URL. If that URL also works in a separate browser session without credentials, the page login has protected the interface, but the image remains publicly retrievable.

Long filenames, UUIDs and hidden links can make discovery harder. They do not establish whether a requester is authorized. HTTPS protects the connection in transit; it does not decide who is entitled to the content. If confidentiality matters, the resource needs authorization at request time.

Private images need a delivery-time access check

A private serving path must receive an identity or access credential, decide whether it permits the requested resource, and enforce that decision before returning the image.

Several architectures can do this. A CDN can validate a signed URL or signed cookie. An application can authenticate a session, check access to the asset and stream it from private storage. A media endpoint can validate a token scoped to the requested resource. A private origin can sit behind one of these serving layers.

The choice depends on the client, the number of assets being requested, caching needs and how quickly access must be revoked. A management API accepting bearer tokens does not prove that a separate image endpoint validates those tokens.

Apply the check to every protected serving path, including thumbnails, transformations and downloads. It must also work when a response is served from a shared cache. Checking access only when the origin is contacted leaves cached responses outside the intended boundary. OWASP’s authorization guidance calls for permission checks on every request, including access to static resources.

Signed URLs and signed cookies

Signed URLs are one common mechanism for private delivery. The application first decides whether the requester may access an image. It then issues a URL containing authorization information that the serving layer can validate, such as a signature covering a resource and an expiry condition.

For example, CloudFront validates the signature and policy before serving the file, whether it is already cached or must be fetched from the origin. Its signed URL documentation describes those separate steps. Adding an expires parameter to an otherwise public URL provides no protection unless a serving layer actually enforces it.

Treat a signed URL as an access credential. In a design that checks only its signature and expiry, someone who receives a copied link can use it while it remains valid. That check does not independently confirm the recipient’s current subscription or role. Choose the validity period and any additional restrictions according to the requirement.

Signed cookies provide another pattern: the browser sends authorization information with requests without putting it into every individual media URL. They can suit a page or gallery containing many protected assets, provided the cookie reaches the serving host. AWS’s comparison of signed URLs and signed cookies explains when each fits CloudFront delivery.

Expiry affects future requests. It does not erase a downloaded copy. Immediate revocation also needs an explicit design; do not assume changing an application role invalidates a previously issued media credential.

Hotlink protection solves a different problem

Hotlinking occurs when another website embeds a media URL hosted by your infrastructure instead of hosting its own copy. Visitors to that site request the image from your server or CDN, using your delivery capacity and placing the image in a context you did not choose.

A public product image can be intentionally accessible and still be hotlinked. Reducing third-party embedding is therefore a different task from deciding which authenticated users may fetch a confidential image.

A common anti-hotlink rule checks the HTTP Referer header against permitted domains. Cloudflare’s Hotlink Protection documentation describes such a mechanism. Its built-in feature covers specified image extensions and rejects nonblank referers outside the site’s domain. It is not a private-content authentication system, and passing traffic through Cloudflare does not mean the feature is enabled.

Why Referer checks are not authentication

The Referer header describes request context. It does not identify an authenticated user. Browser policy can omit it or reduce it to the referring origin, and a client outside the browser can supply its own value. MDN’s Referrer-Policy reference explains how browser policies change the information sent.

A rule allowing requests without a referer leaves direct requests possible. A rule rejecting them can break legitimate loads. Neither choice turns the header into proof of identity.

For a custom domain allowlist, parse the referring URL and compare the hostname against explicitly permitted hosts. Avoid accepting a request merely because an approved domain name appears somewhere in the header string. Treat the result as an embedding policy signal, never as authorization to confidential content.

Hotlink protection can affect legitimate discovery

Public imagery may need to work in search results, social previews, partner embeds, external documentation or syndicated content. Those requests do not all originate from your own pages.

Cloudflare distinguishes crawling from display: its documentation says Hotlink Protection does not affect crawling, but can prevent images from appearing on external services such as Google Images and Facebook. Other configurations can behave differently. An image being crawled successfully does not establish that every external preview can display it.

Separate assets meant for public distribution from assets requiring confidential delivery. Scope anti-hotlink rules to the relevant paths, define partner exceptions where needed, and test the actual external uses. A blanket domain rule can remove a distribution channel you intended to keep.

CORS is not private image security

Removing Access-Control-Allow-Origin does not generally stop another site from displaying a public image through an ordinary cross-origin <img> request. Browsers distinguish embedding a resource from letting script read its contents. MDN’s same-origin policy guide describes cross-origin image embedding as typically allowed.

CORS matters when browser code needs permitted access to the image data. Drawing an image loaded without CORS approval into a canvas can taint the canvas and block pixel reads or export operations. MDN’s canvas guidance explains that restriction.

A blocked canvas read is not a blocked download. CORS should not be used as private-delivery authorization or reliable anti-hotlink enforcement.

Scraping is different from hotlinking

A hotlinking page embeds your URL. A scraper downloads resources programmatically and may save its own copies without displaying them through your CDN afterward.

If the image is public, a scraper can request it directly. A Referer allowlist does not establish who is making that request. Rate limits and bot controls can reduce some automated traffic, but their effects depend on the policy and the client’s behavior; they do not make public content confidential.

For an image that must be unavailable to unauthorized users, establish private access first. Then consider traffic controls for abuse of the permitted access path. An authorized recipient can still download content, so redistribution remains a separate concern.

Protect the origin too

A protected CDN path can be bypassed if the same image remains available through an unrestricted storage URL or alternate hostname. The access decision must cover every route to the protected resource.

Restrict the origin so only the intended serving layer can retrieve protected files, using the origin’s supported access controls. AWS’s private-content guidance recommends restricting direct origin access to prevent bypassing CloudFront signed-delivery rules.

Check original downloads and generated representations as well as the main image URL. An application proxy that checks a session and then redirects to an unrestricted source URL exposes that alternate path. Private origin access is general architecture guidance here, not a claim about Vyso’s current delivery model.

Access rules need to be enforced at delivery

Internal drafts, customer uploads and subscriber images can require different decisions. An application may need to check user identity, workspace, asset ownership, role, subscription or business state. Logging in supplies an identity; the application must still decide whether that identity may access the particular image.

Where a signed credential carries the decision onward, issue it only after the relevant check and limit its scope. Where the serving endpoint reads a session, enforce the asset rule there. Decide what happens when the subscription ends or access changes, including any period during which an issued credential remains valid.

Before relying on a private image path, check the outcomes that matter:

  • An authorized requester receives the intended image; an anonymous or unrelated account does not receive its protected bytes.
  • Missing, altered or expired credentials are rejected according to the delivery policy.
  • A response cached after an authorized request remains unavailable to an unauthorized request.
  • Direct origin URLs, thumbnails and transformation routes do not bypass the rule.
  • Public images still work in the search, preview and partner contexts you intend to support.

For repeatable public representations, the Vyso CDN caching guide explains URL reuse and update behavior. Caching and authorization need separate decisions; a cacheable representation is not necessarily a private one.

Logging: requests versus authenticated users

Depending on configuration, delivery logs can contain a timestamp, path, status, transferred bytes, client IP, user agent or referer. These describe a request. They do not automatically establish which authenticated person viewed the image. An IP address is not a verified user identity, and the absence of a later request does not prove that a saved copy was never reused.

If user-level audit records are required, the authorization layer must associate a validated identity with the decision and resource. Record enough context to investigate a failure while excluding access tokens, session secrets and complete signed credentials. OWASP’s logging guidance distinguishes known user identity from network details and recommends excluding access tokens from logs.

Request volume, unexpected referers, bandwidth spikes, rising error rates or repeated requests for unusual paths can identify activity worth investigating. None is conclusive on its own. A popular campaign and a scraper can both increase traffic. Origin logs can also miss requests served entirely from an edge cache, so establish what each reporting source actually observes.

Vyso’s current delivery code records usage events such as request counts and transferred bytes for account assets handled by that code. Those events identify the asset’s account and delivery, not an authenticated person viewing a public CDN image. They should not be described as a complete user-level access audit trail or downstream usage history.

Watermarking and fingerprinting

A visible watermark can carry branding or attribution and discourage some reuse. It can also be cropped or edited. A public watermarked image remains downloadable, and a legitimate recipient can still capture what is displayed.

Fingerprinting needs a precise definition. A file hash can help identify matching copies; a perceptual signature can support similarity analysis. Neither stops a download or identifies the person who received the file. Recipient-specific forensic tracing requires a system that actually adds or associates distinguishable markers and supports later detection. A duplicate-detection hash does not provide that capability.

Fetching an image, embedding its URL and legally reusing the file are separate questions. Watermarks and contextual notes do not enforce licensing terms. The digital asset rights guide covers rights records and reuse decisions.

Where Vyso fits today

Vyso uses Clerk for account authentication, and its protected Developer API operations resolve the authenticated user and scope management actions to the relevant account, user or workspace. The authentication documentation describes Clerk bearer tokens for protected management requests. Vyso’s security page describes HTTPS/TLS and the service boundaries.

The current CDN delivery surface is public. It serves image transformations and cacheable delivery representations. A management login or collection assignment does not add a delivery-time permission check to those URLs.

Signed or expiring CDN URLs, signed cookies, per-asset delivery permissions, referer allowlists and watermark enforcement are separate mechanisms. Vyso’s current public delivery contract does not provide them. If private images are a requirement, choose a serving architecture that enforces private access and keeps the source inaccessible through uncontrolled paths. Authenticating a proxy in front of an otherwise public Vyso URL would leave the public URL available.

Match the control to the problem

For confidentiality, enforce authorization before returning protected media. To reduce ordinary third-party embedding, use appropriately scoped hotlink controls. To investigate unexpected traffic, use request monitoring with a clear understanding of its coverage. To manage permitted reuse, maintain a rights process and the evidence behind it.

Once someone legitimately receives an image, access rules cannot retrieve every saved copy. Plan redistribution and traceability measures around that fact. Layer controls only when each layer addresses a requirement you actually have.

Keep going

Make the media library less work.

See how Vyso brings search, enrichment, cleanup, and delivery into one product.

Start free