Safeguard
Security Guides•

Are Rails Active Storage files public by default?

Active Storage controllers are public by default: anyone with the URL can fetch the file. Learn how signed URLs behave and how to add access control.

Safeguard Security Team
3 min read

Effectively yes. The Rails guide says all Active Storage controllers are publicly accessible by default, so anyone who knows a file's URL can fetch it, even if the rest of your application requires login. If files need access control, build authenticated controllers or proxy them yourself.

What the guide says

In the section on serving files, the Active Storage overview states that files can be served by redirecting or by proxying, and that all its controllers are public by default. The URLs contain a signed id for the blob, which makes them hard to guess, but a hard to guess link is not an access check. Anyone who obtains it, from a log, an email forward or a browser history, can use it.

In redirect mode, the app generates a permanent URL from the blob's signed id. That URL goes to a controller which redirects to the real storage endpoint, and the redirect has an HTTP expiration of 5 minutes. The permanent URL itself does not expire.

Comparing the options

ApproachWho can fetchNotes
Default redirect URLsAnyone with the linkFine for public images
Proxy modeAnyone with the link, through your serversUseful with a CDN
Authenticated controllersOnly users who pass your checkFor private documents
Short lived storage service URLsLink holder, until expiryGenerated per request after auth

The guide points to authenticated controllers for files that require access control. The pattern is simple: build your own route, authorize the user against the record, then send or redirect to the file.

Disposition and XSS

Active Storage forces the Content-Disposition header to attachment for some kinds of files, to prevent XSS. You can set disposition yourself on links with the rails_blob_path helper:

rails_blob_path(user.avatar, disposition: "attachment")

Forcing a download for user uploaded documents is a sound default, since a browser will not render them in your site's origin.

Steps

  1. Sort attachments into public and private.
  2. For private ones, add a controller that finds the record through the current user, so access follows your normal rules.
  3. Generate links only after that check.
  4. Use attachment disposition for anything that is not an image you control.
  5. Keep the storage bucket itself private. Check the service configuration so the bucket does not allow public listing.
  6. Review logs and emails that might contain permanent links.
  7. Re-test after upgrades, since defaults can change between versions.

What to remember about leaks

Because the permanent link does not expire, a leaked URL stays useful. If a sensitive file was exposed through one, deleting and re-uploading the file should produce a new blob and a new signed id, so check that in a test. Rotating secret_key_base also affects Active Storage links, as the security guide notes, but that is a heavy tool with side effects on sessions.

Quick check

Is the signed id a password?

No. It makes the URL hard to guess, but it is not tied to a user. Treat the link as a bearer token.

Does proxy mode add access control?

Not by itself. Proxying changes how bytes are served. You still need your own authorization check.

Safeguard's dependency scanning and SBOMs cover the image processing libraries Active Storage relies on. A free scan is at gold.safeguard.sh/scan.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.