Repository navigation
fix(api): guard dynamic action dispatch against prototype property lookup - #1117
Merged
collinsezedike merged 1 commit intoOct 20, 2026
Merged
Conversation
|
@EngrAlbaniy001 is attempting to deploy a commit to the Collins' projects Team on Vercel. A member of the Team first needs to authorize it. |
|
@EngrAlbaniy001 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
Use Object.prototype.hasOwnProperty.call in isAction so constructor, toString, valueOf, and __proto__ cannot pass validation. Add tests asserting constructor, toString, and unknown actions return 404.
collinsezedike
force-pushed
the
fix/tx-action-validation
branch
from
October 20, 2026 14:39
3262e99 to
2907c09
Compare
Collaborator
|
@EngrAlbaniy001 thank you again for getting this over the line. If you are enjoying working on Meridian, starring the repository helps more contributors find the project and is much appreciated. |
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
api/v1/tx/[action].ts) againstObject.prototypeproperty lookup by replacing theinoperator check withObject.prototype.hasOwnProperty.call(ACTIONS, value).constructor,toString,valueOf, and__proto__from validating as valid transaction actions, ensuring they cleanly return a 404 with{ error: "Unknown action" }.api/__tests__/handlers.test.tsverifying that calls to/api/v1/tx/constructor,/api/v1/tx/toString, and unknown actions return 404.Why
The dynamic route handler in
api/v1/tx/[action].tschecked whether an action was valid usingvalue in ACTIONS. Becauseintraverses the prototype chain of standard JavaScript objects, inherited properties likeconstructor,toString,valueOf,hasOwnProperty, and__proto__passed the validation check.When
action=constructor, invokingACTIONS[action](req.body)executedObject(req.body), returning the caller's parsed JSON payload. The route then executedres.status(result.status).json(result.body), allowing an unauthenticated caller to arbitrarily set the HTTP status code and response payload from a public endpoint. Inherited method names liketoStringreturned non-RouteResultvalues lacking a numeric.status, throwing an unhandled exception and causing a 500 error instead of a clean 404.Implementation
isActioninapi/v1/tx/[action].tsto checkObject.prototype.hasOwnProperty.call(ACTIONS, value)instead ofvalue in ACTIONS. This ensures only declared own properties ofACTIONS(deposit,withdraw,submit,add-trustline) pass validation.describe("POST /api/v1/tx/[action] action validation")test suite inapi/__tests__/handlers.test.ts:action="constructor"returns 404{ error: "Unknown action" }and ignores status/body payload injection.action="toString"returns 404{ error: "Unknown action" }instead of throwing 500.api/v1/vaults/[vaultId].ts,api/v1/positions/[publicKey].ts,api/v1/admin/[resource].ts, andapi/v1/keepers/[action].ts): confirmed they already useSet.haslookup, key validation, or strict string equality and are not vulnerable to prototype property traversal.Testing
pnpm --filter @meridian/api test __tests__/handlers.test.ts(60/60 tests passing, including 3 new test cases)pnpm run typecheck:api(tsc --noEmit -p api/tsconfig.jsonexits with code 0)pnpm run lint(turbo run lintexits with code 0)npx prettier --check api/v1/tx/[action].ts api/__tests__/handlers.test.ts(Prettier code style check passes)Scope / Risk
api/v1/tx/[action].tsand corresponding tests inapi/__tests__/handlers.test.ts.deposit,withdraw,submit,add-trustline) continue to function unchanged, while non-declared prototype keys that previously faulted or returned attacker-controlled bodies now consistently return 404.Issue
Closes #1049