fix(plugin-security): mask read-protected fields on write responses (FLS leak)#2692
Merged
Conversation
…FLS leak) Field-level security masking ran only on find/findOne results, so a caller with edit-but-not-field-read could PATCH/POST a record and read a read-protected field back out of the mutation response image. Field writes were already denied (detectForbiddenWrites); this closes the read leak on the echoed post-image by extending the mask to insert/update results. Found by dogfooding the permission stack end-to-end (Studio package + permission sets + real users): an employee permission set with hr_note readable:false could still read hr_note via the PATCH response. Added regression tests for both update and insert echoed records. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
📓 Docs Drift CheckThis PR changes 1 package(s): 11 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
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.
What
Field-level security masking ran only on
find/findOneresults. The record echoed back by a write (insert/update) was never masked, so a caller with edit-but-not-field-read couldPATCH/POSTa record and read a read-protected field back out of the mutation response.Field writes to protected fields were already denied (
detectForbiddenWrites), so this is purely a read leak on the response image. The mask now coversinsert/updateresults too — matching read behavior.packages/plugins/plugin-security/src/security-plugin.ts— extend the op allow-list on the post-next()masking block from['find','findOne']to['find','findOne','insert','update'].How it was found
Dogfooding the permission stack end-to-end as an admin, in the browser:
leave_requestobject +请假中心app in a writable package.员工请假权限(CRU,hr_notereadable:false) and人事请假权限(full CRUD + view/modify-all,hr_notereadable).Employee 张三 (hr_note not readable):
GETlist / by-id →hr_notecorrectly stripped ✅PATCH(editing an allowed field) → response includedhr_notewith the sensitive value ❌Verification
plugin-securitysuite: 129 passed.PATCHresponse no longer containshr_note✅PATCHresponse still containshr_note— no regression for authorized readers ✅hr_notestill403— write-protection intact ✅🤖 Generated with Claude Code