Skip to content

fix: Scheduled Transaction Routes Have No Authentication or Ownership Checks - #917

Merged
Topmatrixmor2014 merged 2 commits into
FinChippay:mainfrom
Skinny001:fix/scheduled-tx-auth
Aug 27, 2026
Merged

fix: Scheduled Transaction Routes Have No Authentication or Ownership Checks #917
Topmatrixmor2014 merged 2 commits into
FinChippay:mainfrom
Skinny001:fix/scheduled-tx-auth

Conversation

@Skinny001

Copy link
Copy Markdown
Contributor

This pull request significantly refactors and expands the tests for scheduled transaction routes, and updates the route handlers to enforce strict authentication and authorization. The changes ensure that only the authenticated user can access or modify their own scheduled transactions and pending executions. Additionally, the tests now cover both authorization failures and successful "happy path" operations, as well as error handling for missing resources.

The most important changes are:

Authorization & Authentication Enforcement:

  • Added verifyJWT middleware to all scheduled transaction routes to require authentication, and introduced requireOwnSchedule and requireScheduleOwner middleware to restrict access to only the authenticated user's data. [1] [2] [3]
  • Updated the POST /api/scheduled-transactions route to derive the owner from the JWT and ensure any provided publicKey matches the authenticated user.
  • For pending execution submission, the route now verifies that the pending execution belongs to the authenticated user before proceeding.

Test Suite Overhaul:

  • Refactored the test suite to comprehensively test authentication (401) and authorization (403) errors for all protected routes, as well as happy path scenarios for the owner.
  • Added tests for error handling, including 404 responses when resources are not found.

Route Handler Improvements:

  • All routes now consistently return standardized error responses for forbidden and not-found cases, improving API reliability and clarity. [1] [2]

These changes greatly improve the security and correctness of the scheduled transactions API, ensuring robust access control and comprehensive test coverage.…p checks

  • Add verifyJWT middleware to all scheduled-transaction routes
  • Add requireOwnSchedule middleware for :publicKey routes (GET /:publicKey, GET /:publicKey/pending)
  • Add requireScheduleOwner middleware for :id routes (PUT, DELETE, POST /execute-now, GET /executions)
  • Add ownership check for POST /pending/:id/submit
  • Use req.user.publicKey as owner for createSchedule (ignore/reject body publicKey)
  • Add getScheduleById and getPendingExecutionById service helpers
  • Add 28 tests: 8x 401 unauthenticated, 7x 403 cross-user, 8x 200 owner, 5x 404 not found

Summary

Type of change

  • Bug fix
  • New feature
  • Documentation update
  • Refactor / chore
  • Smart contract change

Related issue

Closes #886

Changes

Testing

  • Tested locally on Testnet
  • Added/updated unit tests
  • Manually tested UI flow

Screenshots (if UI change)

Checklist

  • My code follows the project style
  • I've updated docs if needed
  • No console errors or warnings
  • I've rebased on latest main

@github-actions github-actions Bot added the needs-review PR ready for Greptile AI code review label Aug 26, 2026
@github-actions

Copy link
Copy Markdown

🤖 Greptile AI Code Review

Greptile will automatically review this PR (4 file(s) changed).

Review gates:

  • ✅ CodeQL Security Scan
  • ✅ Custom rules (.greptile/config.json)
  • ✅ Architecture guidelines (.greptile/rules.md)

To manually trigger a re-review, comment @greptileai on this PR.
To skip review, add the skip-review label.

Comment thread backend/src/routes/scheduledTransactions.js Fixed
Comment thread backend/src/routes/scheduledTransactions.js Fixed
Comment thread backend/src/routes/scheduledTransactions.js Fixed
Comment thread backend/src/routes/scheduledTransactions.js Fixed
Comment thread backend/src/routes/scheduledTransactions.js Fixed
Comment thread backend/src/routes/scheduledTransactions.js Fixed
Comment thread backend/src/routes/scheduledTransactions.js Fixed
Comment thread backend/src/routes/scheduledTransactions.js Fixed
@Topmatrixmor2014

Copy link
Copy Markdown
Contributor

please fix these ci issues and resolve all the issues identified from the review comments

@Skinny001

Copy link
Copy Markdown
Contributor Author

please fix these ci issues and resolve all the issues identified from the review comments

@Topmatrixmor2014 fixed

* If publicKey is provided, it must match the authenticated user's publicKey.
*/
router.post("/", validate(scheduleTransactionSchema), async (req, res, next) => {
router.post("/", sensitiveLimiter, userLimiter, verifyJWT, validate(scheduleTransactionSchema), async (req, res, next) => {
* non-empty string). Service treats it as opaque.
*/
router.post("/pending/:id/submit", validate(idParamSchema, "params"), async (req, res, next) => {
router.post("/pending/:id/submit", sensitiveLimiter, userLimiter, verifyJWT, validate(idParamSchema, "params"), async (req, res, next) => {
* Lists pending executions for a given public key with standardized pagination.
*/
router.get("/:publicKey/pending", async (req, res, next) => {
router.get("/:publicKey/pending", sensitiveLimiter, userLimiter, verifyJWT, requireOwnSchedule, async (req, res, next) => {
* Lists all schedules for a given public key with standardized pagination.
*/
router.get("/:publicKey", validate(loosePublicKeyParamSchema, "params"), async (req, res, next) => {
router.get("/:publicKey", sensitiveLimiter, userLimiter, verifyJWT, requireOwnSchedule, validate(loosePublicKeyParamSchema, "params"), async (req, res, next) => {
* non-empty string), so the service can treat it as opaque.
*/
router.put("/:id", validate(idParamSchema, "params"), async (req, res, next) => {
router.put("/:id", sensitiveLimiter, userLimiter, verifyJWT, requireScheduleOwner, validate(idParamSchema, "params"), async (req, res, next) => {
* Deletes or cancels a scheduled transaction by ID.
*/
router.delete("/:id", validate(idParamSchema, "params"), async (req, res, next) => {
router.delete("/:id", sensitiveLimiter, userLimiter, verifyJWT, requireScheduleOwner, validate(idParamSchema, "params"), async (req, res, next) => {
* regardless of its scheduled time.
*/
router.post("/:id/execute-now", validate(idParamSchema, "params"), async (req, res, next) => {
router.post("/:id/execute-now", sensitiveLimiter, userLimiter, verifyJWT, requireScheduleOwner, validate(idParamSchema, "params"), async (req, res, next) => {
* Shows all execution attempts, retries, and failures.
*/
router.get("/:id/executions", validate(idParamSchema, "params"), async (req, res, next) => {
router.get("/:id/executions", sensitiveLimiter, userLimiter, verifyJWT, requireScheduleOwner, validate(idParamSchema, "params"), async (req, res, next) => {
…p checks

- Add verifyJWT middleware to all scheduled-transaction routes
- Add requireOwnSchedule middleware for :publicKey routes (GET /:publicKey, GET /:publicKey/pending)
- Add requireScheduleOwner middleware for :id routes (PUT, DELETE, POST /execute-now, GET /executions)
- Add ownership check for POST /pending/:id/submit
- Use req.user.publicKey as owner for createSchedule (ignore/reject body publicKey)
- Add getScheduleById and getPendingExecutionById service helpers
- Add 28 tests: 8x 401 unauthenticated, 7x 403 cross-user, 8x 200 owner, 5x 404 not found

Closes: backend auth security bug high-priority
- Add sensitiveLimiter and userLimiter to all scheduled-transaction routes
- Mock rate limiters in tests to avoid hitting limits during test runs
- Follows the same pattern as accounts.js routes (sensitiveLimiter + userLimiter + verifyJWT)
@Skinny001
Skinny001 force-pushed the fix/scheduled-tx-auth branch from ef738b7 to e575442 Compare August 26, 2026 07:47
@Skinny001

Copy link
Copy Markdown
Contributor Author

please fix these ci issues and resolve all the issues identified from the review comments

@Topmatrixmor2014 The CodeQL warnings were from analyzing the old main branch code - the PR will pass once updated with this branch.

so, check now

@Topmatrixmor2014
Topmatrixmor2014 merged commit a1e2f72 into FinChippay:main Aug 27, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-review PR ready for Greptile AI code review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

#105 — Scheduled Transaction Routes Have No Authentication or Ownership Checks

3 participants