security(sections): fix IDOR — private templates leaked/writable by slug#75
Open
Chzhqv wants to merge 1 commit into
Open
security(sections): fix IDOR — private templates leaked/writable by slug#75Chzhqv wants to merge 1 commit into
Chzhqv wants to merge 1 commit into
Conversation
Every custom/AI-generated SectionTemplate defaulted to isShared:true (schema default), and neither buildTemplateDoc (profile-generated sections) nor the manual templates POST overrode it — so every personal section a user creates (including ones whose name/description describe their actual life) was silently public. On top of that, several per-slug endpoints applied no ownership or usageCount gate at all, unlike the list endpoint (which requires isShared + usageCount >= 3): - GET /api/sections/templates/[slug] — had isShared:true with no usageCount check, letting a template become public the instant a single other user's search happened to hit it - GET/POST /api/sections/[slug]/entries — no gate whatsoever - GET /api/sections/[slug]/entries/[id] (PATCH) — no gate whatsoever - GET /api/export/[section] (custom: section export) — no gate, leaked field labels via exported column headers - POST /api/sections/templates/[slug]/edit-layout — no gate, and worse: the save:true path let ANY user overwrite another user's template's layoutHtml by slug (write IDOR, not just a read leak) Fixes: - Schema default isShared: false (private unless explicitly shared) - buildTemplateDoc and the manual template POST now set isShared: false explicitly - All five endpoints above now apply the same ownership/shared gate used by the list endpoint: createdBy === user, or createdBy null (built-in), or isShared + usageCount >= 3 (proven shared template) - edit-layout's save path additionally requires strict ownership (createdBy === userId) even for templates matched via the shared/ built-in branches of that gate, since read-for-AI-context and write-back are different trust levels Updated a pre-existing unit test that had encoded the old insecure default (isShared: true) as expected schema behavior. Verified live with two real registered users: created a private section as User A, then as User B attempted (1) reading A's template definition, (2) reading/(3) posting A's entries, (4) exporting A's section, (5) PATCHing A's entry via the slug route, (6) overwriting A's layoutHtml via edit-layout save:true — all six blocked with 404 (layoutHtml confirmed unchanged in the DB for TemaDeveloper#6). Confirmed no regression: A's own access to all of the above still works, and a genuinely proven shared template (isShared:true, usageCount>=3, different owner) is still correctly readable by other users, while an unproven one (usageCount<3) is correctly still blocked. Fixes TemaDeveloper#44
|
Someone is attempting to deploy a commit to the Artemii's projects Team on Vercel. A member of the Team first needs to authorize it. |
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.
Summary
Every custom/AI-generated
SectionTemplatedefaulted toisShared: true(schema default), and neitherbuildTemplateDoc(profile-generated sections) nor the manual templatesPOSToverrode it — so every personal section a user creates, including ones whose name/description describe their actual life, was silently public.On top of that, several per-slug endpoints applied no ownership or
usageCountgate at all, unlike the list endpoint (which requiresisShared+usageCount >= 3):GET /api/sections/templates/[slug]— hadisShared:truewith nousageCountcheckGET/POST /api/sections/[slug]/entries— no gate whatsoeverPATCH /api/sections/[slug]/entries/[id]— no gate whatsoeverGET /api/export/[section](custom section export) — no gate, leaked field labels via exported column headersPOST /api/sections/templates/[slug]/edit-layout— no gate, and worse: thesave:truepath let any user overwrite another user's template'slayoutHtmlby slug (write IDOR, not just a read leak)Fixes
isShared: false(private unless explicitly shared)buildTemplateDocand the manual templatePOSTnow setisShared: falseexplicitlycreatedBy === user, orcreatedBy null(built-in), orisShared + usageCount >= 3(proven shared template)edit-layout's save path additionally requires strict ownership (createdBy === userId) even for templates matched via the shared/built-in branches of that gate, since read-for-AI-context and write-back are different trust levelsisShared: true) as expected schema behaviorTest plan
Verified live with two real registered users — created a private section as User A, then as User B attempted:
layoutHtmlviaedit-layoutsave:true— blocked (404), confirmedlayoutHtmlunchanged in the DBConfirmed no regression:
.xlsx, entries list correctly, etc.)isShared:true,usageCount>=3, different owner) is still correctly readable by another userusageCount<3) is correctly still blocked for a non-ownerpnpm lint,tsc --noEmit, fullvitest run(556/556) all passFixes #44