short story
It started with a simple application flow.
Create an account. Log in. Fill out the required details. Upload supporting documents — mostly PDFs.
Everything looked standard. Nothing out of place.
But in security testing, the most "normal" features are often where things break.
While going through the upload functionality, one question stood out:
What actually happens to the file after it's uploaded?
The upload worked exactly as expected. PDFs were accepted, stored, and accessible after submission.
Which is exactly why it was worth testing further.

The Payload
Instead of uploading a normal PDF, I crafted one with an embedded JavaScript payload.
After uploading, I accessed the file — and that's when it happened.
A popup appeared in the browser.
Not from the application… but from an AWS-hosted URL:
s3.ap-south-1.amazonaws.com
The payload wasn't just stored — it was executed directly from the cloud.
This confirmed a Stored XSS, triggered every time the file was accessed.

Why This Got Worse in the Cloud
The file wasn't served through the application itself.
Instead, it was hosted on a public cloud storage endpoint — similar to Amazon S3.
This changed the impact completely.
The malicious file was accessible via a direct public URL, without authentication. Anyone with the link could open it — and trigger the payload.
What started as a stored XSS inside an application now became a publicly reachable attack vector.
Because the file was hosted on trusted cloud infrastructure, it could easily be shared as a legitimate document — like a resume or report — making it far more effective in real-world scenarios.
At that point, it wasn't just a vulnerability.
It was a weaponized asset.
Breaking the Access Boundary
The file required login to upload and view.
But when accessed, it redirected to a cloud URL on Amazon S3.
I copied the link, opened it in incognito — it still worked.
No session. No authentication.
Anyone with the link could access it.
The file wasn't protected anymore. It was public.

Lessons Learned
- File uploads are input vectors, not just storage
- Extensions aren't enough — validate content
- Public storage like Amazon S3 can expose data if misconfigured
- If you get a URL, test it outside the application