Presigned URL Security: Expiry, Scope, and Upload Controls

Issue narrowly scoped presigned upload and download URLs while controlling expiry, object keys, content types, and post-upload validation.

In this article

Presigned URL Security: Expiry, Scope, and Upload Controls

A presigned URL delegates one storage operation to anyone who possesses the URL until it expires. It is a bearer credential, not a public object setting. Safe designs minimize duration and scope, keep URLs out of logs, and treat client-declared file metadata as untrusted even when it was included in the signature.

The practical model

Treat presigned url security: expiry, scope, and upload controls as a system with four review points: bind the intended operation, constrain uploads deliberately, design completion as a protocol, protect delivery paths. Give each point an owner, a measurable acceptance condition, and a rollback trigger. Thresholds should come from observed workloads, contracts, or risk tolerance rather than an unexplained default.

Bind the intended operation

Generate a URL for one method, bucket, and object key. Use an unpredictable server-assigned key rather than a raw filename. Separate upload and download prefixes and keep the signing identity unable to list or mutate unrelated objects. A short URL lifetime reduces exposure but does not revoke a leaked URL instantly.

Constrain uploads deliberately

Where supported, sign expected content type, checksum, and size conditions. Do not trust Content-Type as proof of format; inspect magic bytes after upload. Write new objects to a quarantine prefix, scan them, validate dimensions or archive structure, then promote them to a serving prefix with new metadata.

Design completion as a protocol

Have the client notify your API after upload, but verify the object with a trusted metadata call. Check key ownership, size, checksum, creation time, and quarantine state. Make completion idempotent. For large multipart uploads, expire abandoned sessions and validate the completed aggregate object.

Protect delivery paths

For private downloads, authorize the application request before issuing the URL. Use response-content controls carefully, sanitize download names, and set Content-Disposition to avoid inline execution where inappropriate. Redact query strings from access logs, analytics, referrers, and error reports.

Common pitfalls

  • Long expiries used as permanent sharing links.
  • Allowing the client to choose another tenant’s key prefix.
  • Serving uploads before scanning and validation.
  • Assuming deleting an application record revokes an already issued URL.

A focused test plan

  1. Bind the intended operation: verify that generate a URL for one method, bucket, and object key. Then introduce the failure case “long expiries used as permanent sharing links” and confirm that the system fails visibly, stays within its safety boundary, and has a documented recovery action.
  1. Constrain uploads deliberately: verify that where supported, sign expected content type, checksum, and size conditions. Then introduce the failure case “allowing the client to choose another tenant’s key prefix” and confirm that the system fails visibly, stays within its safety boundary, and has a documented recovery action.
  1. Design completion as a protocol: verify that have the client notify your API after upload, but verify the object with a trusted metadata call. Then introduce the failure case “serving uploads before scanning and validation” and confirm that the system fails visibly, stays within its safety boundary, and has a documented recovery action.
  1. Protect delivery paths: verify that for private downloads, authorize the application request before issuing the URL. Then introduce the failure case “assuming deleting an application record revokes an already issued url” and confirm that the system fails visibly, stays within its safety boundary, and has a documented recovery action.

Conclusion

Presigned URLs are safe delegation primitives when each URL expresses one short-lived action. Narrow the signer, quarantine uploads, verify completion server-side, and prevent bearer URLs from leaking into telemetry.

Advertisement