Fix: Unauthenticated access to customer order confirmation PDFs via /ftp - #365
Closed
WesternConcrete wants to merge 4 commits into
Closed
WesternConcrete wants to merge 4 commits into
WesternConcrete wants to merge 4 commits into
Conversation
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-Authored-By: Wes Convery <2wconvery@gmail.com>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-Authored-By: Wes Convery <2wconvery@gmail.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-Authored-By: Wes Convery <2wconvery@gmail.com>
Signed-off-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-Authored-By: Wes Convery <2wconvery@gmail.com>
| const orderOwnerEmail = (req: Request): string | undefined => { | ||
| for (const token of [cookieToken(req), utils.jwtFrom(req)]) { | ||
| try { | ||
| if (token && security.verify(token)) { |
|
CI note: the red CodeQL check is "4 new alerts in code changed by this PR", all in the new authorization block of
I don't have permission to dismiss code-scanning alerts on this repo; a maintainer can dismiss them as "used in tests / won't fix". The other failing checks ( |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Finding: Unauthenticated access to customer order confirmation PDFs via /ftp
Repo: COG-GTM/juice-shop
Fix:
servePublicFiles()inroutes/fileServer.tsnow requires a signature-verified JWT (tried from thetokencookie — parsed from the rawCookieheader, sincecookieParseris mounted after the/ftproutes — then from the Bearer header) and only servesorder_<orderId>.pdfwhen the order stored inordersCollectionfor thatorderIdbelongs to the JWT's email; anonymous requests get 401, other customers / unknown orders get 403.placeOrder()writesftp/order_<md5(email)[0:4]>-<random>.pdf(customer email, delivery address, line items) and/ftp/:fileallowlisted every*.pdfwith no auth, so any leaked/shared order link was readable by anyone.Ownership = stored order's vowel-masked email matches the JWT email and the
orderIdcarries themd5(email)[0:4]-prefixplaceOrderderives from the real email (the masked email alone is not unique; the prefix alone is 16 bits). The check runs on the null-byte-stripped filename so the existing%00bypass cannot skip it. A stale/malformed cookie does not mask a valid Bearer token and never throws.cleanupFtpFolderremovesorder_*.pdfon startup, so PDFs and the in-memory order records share a lifetime. Existing/ftpchallenge behaviour for non-order files is unchanged.Tests:
test/server/fileServerSpec.ts(anonymous → 401, other customer → 403, unknown order → 403, masked-email match with wrong prefix → 403, owner → served, invalid cookie + valid Bearer → served, malformed cookie → 401) andtest/api/ftp-folder.test.tsthrough the real Express stack (anonymous → 401, valid cookie + unknown order → 403). mocha, API tests, eslint,tsc --noEmitandnpm run rsnpass.Supersedes #364 (closed by the contribution bot for targeting
masterinstead ofdevelop).Resolved or fixed issue: none
AI Tool Disclosure
DevinDevin (Cognition)Daily security sweep: substantiate and fix new vulnerabilities in COG-GTM/juice-shopAffirmation
Link to Devin session: https://app.devin.ai/sessions/a749d64c0c0e49149bdaff3d2605b5c2
Open in Devin Desktop: https://app.devin.ai/desktop/session/a749d64c0c0e49149bdaff3d2605b5c2?variant=devin
Requested by: @WesternConcrete