ActiveStorage Direct Uploads Safe by Default/How to make it safe?

I’m looking to use ActiveStorage Direct Uploads in a project and I’m struggling to understand how the default configuration is safe.

As I read it, any user can create a new direct upload by calling DirectUploadController#create. They then receive a URL and/or authentication information for uploading the contents of the blob to your storage service. Couldn’t someone simply keep making calls to DirectUploadController#create and keep uploading more and more blobs to the storage service and never attaching any of those blobs?

Is that safe? Is there a risk of a user getting a super large bill from say S3 because a script kept sending blobs? Or maybe this is a similar level of risk as someone creating new database records on a rails site as well, I’m not sure.

Any thoughts on this? Am I looking at this problem totally wrong or is there something I’m not seeing?

You’re not wrong. Active Storage’s built-in controllers are either unauthenticated or protected only by weak signature-based authentication:

  • ActiveStorage::BlobsController: Signature-based authentication, permanent signatures
  • ActiveStorage::RepresentationsController: Signature-based authentication, permanent signatures
  • ActiveStorage::DirectUploadsController: Unauthenticated (:warning:)
  • ActiveStorage::DiskController: Signature-based authentication, short-lived signatures

In a production app, you’ll likely need to authenticate, validate, rate-limit, and otherwise protect storage access more stringently. That means you’ll need to bring your own controllers.

We have warnings to this effect non-exhaustively peppered throughout the API documentation:

If you need to enforce access protection beyond the security-through-obscurity factor of the signed blob references, you’ll need to implement your own authenticated redirection controller.

We can more consistently/clearly/loudly document this—and PRs are welcome for that—but I don’t feel great about the current state of things regardless. We’re trading production safety for Fisher-Price simplicity. I don’t have a solution in mind at the moment.

/cc @bitsweat @DHH

1 Like

Thanks for helping me understand it. I don’t think it’s helped by the fact that:

  • You can’t prevent drawing the default routes for ActiveStorage, until 6.1
  • There doesn’t seem to be a well documented way to override some of the default ActiveStorage routes.

For my use-case, I don’t really care that much about the authentication of the other controllers but I don’t like ActiveStorage::DirectUploadsController being unauthenticated.

I say all this without a good answer on how to fix the problem and still make it easy to get started AND not assume a particular authentication system or design.