fix: Cloud Hooks and Cloud Jobs bypass readOnlyMasterKey write restriction (GHSA-vc89-5g3r-cmhh)#10088
Conversation
|
🚀 Thanks for opening this pull request! |
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
📝 WalkthroughWalkthroughAdds read-only masterKey access controls to prevent write operations on hooks and cloud jobs. Enforces OPERATION_FORBIDDEN errors for POST/PUT requests while permitting read operations, with comprehensive test coverage validating both forbidden and allowed actions. Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~15 minutes 🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (4)
src/Routers/HooksRouter.js (2)
93-99: Make the forbidden message explicit about delete operations
handlePutblocks both update and delete flows; the log message can be more precise.Proposed wording tweak
- "read-only masterKey isn't allowed to modify a hook.", + "read-only masterKey isn't allowed to update or delete a hook.",🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Routers/HooksRouter.js` around lines 93 - 99, The current read-only check in handlePut uses createSanitizedError with a generic message; update the error message produced when req.auth.isReadOnly is true to explicitly mention that delete operations (in addition to updates) are forbidden by the read-only masterKey—locate the check using req.auth.isReadOnly inside the handlePut flow and change the string passed to createSanitizedError so it clearly states "read-only masterKey isn't allowed to update or delete a hook" (or similar explicit wording).
4-4: PR title suggestion for a clearer changelog entrySuggested title:
fix(security): block read-only masterKey writes for hooks and cloud jobsBased on learnings: For Parse Server PRs, always suggest an Angular-style PR title (
type(scope): description) that yields a meaningful changelog entry.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/Routers/HooksRouter.js` at line 4, Update the pull request title to follow Angular-style changelog convention by setting it to: "fix(security): block read-only masterKey writes for hooks and cloud jobs" so the changelog entry is meaningful and follows project standards.spec/rest.spec.js (2)
1176-1297: Either assert logger output or removeloggerErrorSpy.calls.reset()in new testsRight now resets are done repeatedly without assertions in these new cases, which adds noise.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@spec/rest.spec.js` around lines 1176 - 1297, Several new tests call loggerErrorSpy.calls.reset() without asserting logger behavior; for each test (e.g. the it blocks "should throw when trying to create a hook function", "should throw when trying to create a hook trigger", "should throw when trying to update a hook function", "should throw when trying to delete a hook function", and "should throw when trying to run a job with readOnlyMasterKey") either remove the unnecessary loggerErrorSpy.calls.reset() call or replace it with an assertion that checks expected logger calls (e.g. expect(loggerErrorSpy.calls.count()).toBe(...) or expect(loggerErrorSpy).toHaveBeenCalledWith(...)) so the spy reset is not left unused; update the corresponding test bodies around loggerErrorSpy.calls.reset() accordingly to keep tests meaningful.
1216-1276: Use unique hook names (or cleanup) to avoid cross-test state leakageThe fixed function names can collide on retries/reruns in a non-pristine environment.
Example stabilization tweak
- await request({ + const functionName = `readOnlyUpdateTest_${Date.now()}`; + await request({ url: `${Parse.serverURL}/hooks/functions`, method: 'POST', headers: { 'X-Parse-Application-Id': Parse.applicationId, 'X-Parse-Master-Key': Parse.masterKey, 'Content-Type': 'application/json', }, - body: { functionName: 'readOnlyUpdateTest', url: 'https://example.com/hook' }, + body: { functionName, url: 'https://example.com/hook' }, }); @@ - url: `${Parse.serverURL}/hooks/functions/readOnlyUpdateTest`, + url: `${Parse.serverURL}/hooks/functions/${functionName}`,🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@spec/rest.spec.js` around lines 1216 - 1276, The tests create hook functions with fixed names (readOnlyUpdateTest, readOnlyDeleteTest) which can collide between runs; modify the test to use unique hook names (e.g., append a timestamp or random suffix) when calling request for creation and when targeting the PUT/DELETE, or alternatively perform a cleanup step after the test to remove the created hook using the true master key; update both occurrences of 'readOnlyUpdateTest' and 'readOnlyDeleteTest' in the spec to reference the generated uniqueName (or call the cleanup request) so each test is isolated and does not leak state across runs.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@spec/rest.spec.js`:
- Around line 1176-1297: Several new tests call loggerErrorSpy.calls.reset()
without asserting logger behavior; for each test (e.g. the it blocks "should
throw when trying to create a hook function", "should throw when trying to
create a hook trigger", "should throw when trying to update a hook function",
"should throw when trying to delete a hook function", and "should throw when
trying to run a job with readOnlyMasterKey") either remove the unnecessary
loggerErrorSpy.calls.reset() call or replace it with an assertion that checks
expected logger calls (e.g. expect(loggerErrorSpy.calls.count()).toBe(...) or
expect(loggerErrorSpy).toHaveBeenCalledWith(...)) so the spy reset is not left
unused; update the corresponding test bodies around loggerErrorSpy.calls.reset()
accordingly to keep tests meaningful.
- Around line 1216-1276: The tests create hook functions with fixed names
(readOnlyUpdateTest, readOnlyDeleteTest) which can collide between runs; modify
the test to use unique hook names (e.g., append a timestamp or random suffix)
when calling request for creation and when targeting the PUT/DELETE, or
alternatively perform a cleanup step after the test to remove the created hook
using the true master key; update both occurrences of 'readOnlyUpdateTest' and
'readOnlyDeleteTest' in the spec to reference the generated uniqueName (or call
the cleanup request) so each test is isolated and does not leak state across
runs.
In `@src/Routers/HooksRouter.js`:
- Around line 93-99: The current read-only check in handlePut uses
createSanitizedError with a generic message; update the error message produced
when req.auth.isReadOnly is true to explicitly mention that delete operations
(in addition to updates) are forbidden by the read-only masterKey—locate the
check using req.auth.isReadOnly inside the handlePut flow and change the string
passed to createSanitizedError so it clearly states "read-only masterKey isn't
allowed to update or delete a hook" (or similar explicit wording).
- Line 4: Update the pull request title to follow Angular-style changelog
convention by setting it to: "fix(security): block read-only masterKey writes
for hooks and cloud jobs" so the changelog entry is meaningful and follows
project standards.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## alpha #10088 +/- ##
=======================================
Coverage 92.61% 92.61%
=======================================
Files 191 191
Lines 15776 15784 +8
Branches 180 180
=======================================
+ Hits 14611 14619 +8
Misses 1153 1153
Partials 12 12 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
readOnlyMasterKey write restriction (GHSA-vc89-5g3r-cmhh)
|
fix: Cloud Hooks and Cloud Jobs bypass |
## [9.4.1-alpha.3](9.4.1-alpha.2...9.4.1-alpha.3) (2026-03-04) ### Bug Fixes * Cloud Hooks and Cloud Jobs bypass `readOnlyMasterKey` write restriction ([GHSA-vc89-5g3r-cmhh](https://github.com/parse-community/parse-server/security/advisories/GHSA-vc89-5g3r-cmhh)) ([#10088](#10088)) ([9a3dd4d](9a3dd4d))
|
🎉 This change has been released in version 9.4.1-alpha.3 |
## [9.4.1](9.4.0...9.4.1) (2026-03-04) ### Bug Fixes * Cloud Hooks and Cloud Jobs bypass `readOnlyMasterKey` write restriction ([GHSA-vc89-5g3r-cmhh](https://github.com/parse-community/parse-server/security/advisories/GHSA-vc89-5g3r-cmhh)) ([#10088](#10088)) ([9a3dd4d](9a3dd4d)) * MongoDB default batch size changed from 1000 to 100 without announcement ([#10085](#10085)) ([8f17397](8f17397)) ### Performance Improvements * Upgrade to mongodb 7.1.0 ([#10087](#10087)) ([bebf2fd](bebf2fd))
|
🎉 This change has been released in version 9.4.1 |
Pull Request
Issue
Cloud Hooks and Cloud Jobs bypass
readOnlyMasterKeywrite restriction (GHSA-vc89-5g3r-cmhh).Tasks
Summary by CodeRabbit
Bug Fixes
Tests