Security of AWS Pre-Signed URLs



Are AWS Pre-Signed URLs Safe?

Yes—if used correctly. A pre-signed URL is a time-limited, object-scoped URL that grants access
to a specific S3 operation (GET/PUT) without exposing AWS credentials. Security ultimately depends on
expiration, distribution, and transport.

What Is a Pre-Signed URL?

It’s an S3 request signed with AWS Signature V4 using the generator’s IAM credentials. Anyone in possession of
the URL can perform the allowed action until the URL expires.

https://mybucket.s3.amazonaws.com/file.pdf?
X-Amz-Algorithm=AWS4-HMAC-SHA256&
X-Amz-Credential=AKIA.../20251112/us-east-1/s3/aws4_request&
X-Amz-Date=20251112T220000Z&
X-Amz-Expires=3600&
X-Amz-Signature=abcd1234...

Why They’re Safe (When Used Properly)

Feature Security Property
Time-limited Automatic expiry (minutes/hours), reducing exposure window.
Object-scoped Grants access only to a specific object and verb (GET/PUT/HEAD).
Cryptographic signature HMAC-SHA256 (SigV4); cannot be forged without the signer’s credentials.
No static creds in clients Callers never see IAM keys or assume roles directly.

Common Risks (Misuse Patterns)

Risk Impact
Overlong expiration Effectively becomes public access for the duration.
Public sharing or logging It’s a bearer token—anyone with the URL can use it until expiry.
HTTP instead of HTTPS Interception exposes the URL to attackers.
Over-privileged generators Can sign access to sensitive objects unintentionally.
No contextual limits Base S3 presigned URLs can’t restrict by IP/geo without a proxy/CDN.

Best-Practice Guidelines

  • Use short expirations: 5–15 minutes for downloads; ≤1 hour for uploads.
  • Enforce HTTPS: Generate and distribute only over TLS; block HTTP at the edge.
  • Restrict generation: Let only specific backend services/Lambdas create URLs.
  • Generate on demand: Don’t embed in static pages/apps; fetch from your backend per request.
  • Audit access: Enable S3 server access logs and CloudTrail data events for the bucket.
  • Rotate credentials: Use short-lived role creds; rotate keys to limit blast radius.
  • Protect sensitive data: Use SSE-KMS and least-privilege KMS key policies.
  • Need IP/time controls? Front S3 with CloudFront and use CloudFront Signed URLs/Cookies for finer policy (IP, geo, shorter TTLs).

Typical Safe Usage Scenarios

Scenario Recommended Pattern
User downloads from a web app Backend authenticates user, generates short-lived GET URL, returns it once.
Mobile/browser uploads Backend issues short-lived PUT URL with content-type/size constraints; client uploads directly to S3.
Partner/temporary share URL with 15–30 min TTL sent via a secure channel; revoke by object rotation if needed.
CI/CD or Lambda artifact exchange Ephemeral URLs for just-in-time transfers; logs enabled for traceability.

Quick CLI Examples

# Generate a GET pre-signed URL (default expiry ~3600s)
aws s3 presign s3://mybucket/report.pdf --expires-in 900

# Generate a PUT pre-signed URL (upload)
aws s3api put-object --bucket mybucket --key upload/photo.jpg --body photo.jpg
# Then generate a presigned PUT URL from your SDK/backend for controlled uploads

Prefer generating URLs in your backend using AWS SDKs (SigV4). Validate user auth & authorization before issuing the URL.


Summary

Pre-signed URLs are safe for temporary, scoped access when you keep TTLs short, use HTTPS,
restrict who can generate them, and log usage. For IP/geo enforcement or more advanced controls, place S3 behind
CloudFront with signed URLs/cookies.