# ActiveStorage direct upload fails to sign content-length header for S3 service

Rails ActiveStorage presigned S3 upload URLs silently drop the content-length header, letting attackers upload files of arbitrary size despite developer size validations.

- Payout: hidden
- Severity: medium
- Program: Ruby on Rails
- Found by: travispew
- Disclosed: 2020-05-18
- CVE: CVE-2020-8162
- Write-up quality: 7/10
- Original: https://hackerone.com/reports/789579
- Library page: https://bugbountylibrary.com/r/h1%3A789579
- Tags: area:web3 domain:cloud impact:dos impact:integrity kind:bounty platform:hackerone sev:medium tech:aws tech:ruby tech:s3 vuln:business-logic vuln:misconfiguration

**Target:** ActiveStorage DirectUploadsController / S3 presigned PUT URL
**Root cause:** aws-sdk-s3's presigner silently blacklists the content-length header, so the content_length passed to presigned_url never appears in the signed URL, defeating the intended size enforcement.
**Steps:**
1. Developer configures DirectUploadsController to reject byte_size over a limit (e.g. 10MB).
2. Attacker submits direct_upload params with a small byte_size but uploads a much larger file.
3. S3 presigned PUT URL lacks a signed content-length, so S3 accepts the oversized body.
**How found:** Reading s3_service.rb's url_for_direct_upload and noticing content_length is passed to presigned_url, then checking aws-sdk-s3's presigner.rb which blacklists content-length, confirming the header never reaches the signed URL.
**Exploitation:** Attacker lies about byte_size in the direct upload request, receives a presigned URL without a signed content-length, then PUTs an arbitrarily large file directly to S3, bypassing the developer's size validation and incurring storage/egress costs.
**Insight:** When a library passes a parameter to a third-party SDK, verify the SDK actually honors it—aws-sdk-s3 silently drops blacklisted headers like content-length, so signed-URL constraints must be checked against the generated URL, not the call site.

