# The Secure Code Review Challenge — Solution #4: File Converter (A Guessable ID Is an Accessible ID)

**URL:** <https://threatmodelingconnect.discourse.group/t/the-secure-code-review-challenge-solution-4-file-converter-a-guessable-id-is-an-accessible-id/1270>\
**Category:** General\
**Created:** [September 3, 2026, 9:21pm UTC](https://threatmodelingconnect.discourse.group/t/the-secure-code-review-challenge-solution-4-file-converter-a-guessable-id-is-an-accessible-id/1270 "2026-09-03T21:21:20Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![Mohamed\_AboElKheir](https://sea2.discourse-cdn.com/flex002/user_avatar/threatmodelingconnect.discourse.group/mohamed_aboelkheir/32/179_2.png) [@Mohamed\_AboElKheir](https://threatmodelingconnect.discourse.group/u/Mohamed_AboElKheir)\
**Post date:** [September 3, 2026, 9:21pm UTC](https://threatmodelingconnect.discourse.group/t/the-secure-code-review-challenge-solution-4-file-converter-a-guessable-id-is-an-accessible-id/1270/1 "2026-09-03T21:21:20Z")

</div>

📢 The solution to Secure Code Review Challenge #4: File Converter is live!

This one’s a reminder that authentication is not authorization. The app does a lot right: bcrypt password hashing, express-mongo-sanitize against NoSQL injection, execFile (not exec) so command injection is a dead end, --sandbox mode against a real Pandoc SSRF CVE, EJS auto-escaping + CSP against XSS, textContent instead of innerHTML on the client. Every classic injection sink is genuinely closed.

But the per-job routes only check who you are — never whether it’s your job. They fetch by job ID alone, with no comparison to the caller’s user ID. And job IDs aren’t random: they’re just today’s date plus a per-day counter starting at 1.

Any registered account can guess a job ID and download a stranger’s uploaded document. Proved it live with two accounts — one stealing the other’s “confidential” file.

🎥 Watch the full walkthrough: [https://youtu.be/R\_xdc6y9Rho](https://youtu.be/R_xdc6y9Rho)  
📄 Read the write-up: [the-secure-code-review-challenge/solutions/004-file-converter/SOLUTION.md at main · mohamed-osama-aboelkheir/the-secure-code-review-challenge · GitHub](https://github.com/mohamed-osama-aboelkheir/the-secure-code-review-challenge/blob/main/solutions/004-file-converter/SOLUTION.md)  
🧩 Try Challenge #4 yourself first: [the-secure-code-review-challenge/challenges/004-file-converter at main · mohamed-osama-aboelkheir/the-secure-code-review-challenge · GitHub](https://github.com/mohamed-osama-aboelkheir/the-secure-code-review-challenge/tree/main/challenges/004-file-converter)

Two things before you dive in:  
🔹 Challenge #5 is already live in the repo: [link]  
🔹 Watch → Custom → Releases on the repo to get notified the moment new challenges/solutions drop, instead of checking back manually: [Releases · mohamed-osama-aboelkheir/the-secure-code-review-challenge · GitHub](https://github.com/mohamed-osama-aboelkheir/the-secure-code-review-challenge/releases)

If you work through it, I’d love to know: when you hit a route that takes an object ID from the URL, is “checking ownership” a reflex for you, or does seeing requireAuth on the route make it feel already covered?
