Skip to content

Comments

Update digest endpoint to use verifySignatureAppRouter#578

Merged
elie222 merged 1 commit intoelie222:mainfrom
edulelis:digest-emails-v4
Jul 18, 2025
Merged

Update digest endpoint to use verifySignatureAppRouter#578
elie222 merged 1 commit intoelie222:mainfrom
edulelis:digest-emails-v4

Conversation

@edulelis
Copy link
Collaborator

@edulelis edulelis commented Jul 17, 2025

Summary by CodeRabbit

  • Security

    • Enhanced the security audit documentation and scripts to ensure all QStash endpoints use signature verification, with updated checklists and clearer audit steps.
    • Updated the security review process to explicitly verify signature checks on QStash endpoints.
  • Bug Fixes

    • Replaced manual cron secret checks with automated signature verification for digest email endpoints, improving security and reliability.
  • Chores

    • Removed unnecessary inclusion of sensitive environment variables in QStash job payloads.

@vercel
Copy link

vercel bot commented Jul 17, 2025

@edulelis is attempting to deploy a commit to the Inbox Zero Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jul 17, 2025

Walkthrough

The updates enhance security practices around QStash endpoints by requiring signature verification using verifySignatureAppRouter. The security audit documentation and scripts are updated to check for this middleware. Code changes remove reliance on a cron secret in favor of signature verification, and sensitive secrets are no longer included in QStash job payloads.

Changes

File(s) Change Summary
.cursor/rules/security-audit.mdc Updated audit script and documentation to require and check for verifySignatureAppRouter on QStash endpoints.
apps/web/app/api/resend/digest/all/route.ts Stopped including CRON_SECRET in QStash job payloads.
apps/web/app/api/resend/digest/route.ts Replaced manual cron secret check with verifySignatureAppRouter middleware for signature verification.

Sequence Diagram(s)

sequenceDiagram
    participant QStash
    participant API_Endpoint as Digest Endpoint
    participant Server

    QStash->>API_Endpoint: POST /api/resend/digest (with signature)
    API_Endpoint->>API_Endpoint: verifySignatureAppRouter(request)
    alt Signature valid
        API_Endpoint->>Server: Process digest email logic
        Server-->>API_Endpoint: Success/Failure
        API_Endpoint-->>QStash: JSON response
    else Signature invalid
        API_Endpoint-->>QStash: 401 Unauthorized
    end
Loading

Poem

A rabbit hops with nimble feet,
Securing endpoints, neat and sweet.
No secrets sent, no spoofing fright,
Signatures checked—security’s tight!
The audit’s sharp, the docs are clear,
Our QStash calls have naught to fear.
🐇✨


📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b8dcc85 and dfd432f.

📒 Files selected for processing (3)
  • .cursor/rules/security-audit.mdc (4 hunks)
  • apps/web/app/api/resend/digest/all/route.ts (1 hunks)
  • apps/web/app/api/resend/digest/route.ts (3 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
apps/web/**/*.{ts,tsx}

Instructions used from:

Sources:
📄 CodeRabbit Inference Engine

  • apps/web/CLAUDE.md
apps/web/app/**/*

Instructions used from:

Sources:
📄 CodeRabbit Inference Engine

  • apps/web/CLAUDE.md
**/*.{ts,tsx}

Instructions used from:

Sources:
📄 CodeRabbit Inference Engine

  • .cursor/rules/form-handling.mdc
.cursor/rules/*.mdc

Instructions used from:

Sources:
📄 CodeRabbit Inference Engine

  • .cursor/rules/cursor-rules.mdc
.cursor/rules/[a-z0-9\-]*.mdc

Instructions used from:

Sources:
📄 CodeRabbit Inference Engine

  • .cursor/rules/cursor-rules.mdc
🧠 Learnings (4)
📓 Common learnings
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security-audit.mdc:0-0
Timestamp: 2025-06-23T12:27:05.686Z
Learning: Regularly run automated security audit scripts and manually review flagged routes to ensure ongoing compliance with security best practices in API route development.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-06-23T12:27:17.978Z
Learning: Cron endpoints must use withError middleware and validate requests with strong secrets (hasCronSecret/hasPostCronSecret); never use weak or predictable secrets.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security-audit.mdc:0-0
Timestamp: 2025-06-23T12:27:05.686Z
Learning: Cron endpoints in API routes must be protected with secret validation middleware such as hasCronSecret or hasPostCronSecret to prevent unauthorized access.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security-audit.mdc:0-0
Timestamp: 2025-06-23T12:27:05.686Z
Learning: Do not hardcode secrets directly in code for cron endpoints; secrets should be managed via environment variables (e.g., CRON_SECRET) and not as plain strings in the source code.
apps/web/app/api/resend/digest/all/route.ts (4)
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security-audit.mdc:0-0
Timestamp: 2025-06-23T12:27:05.686Z
Learning: Do not hardcode secrets directly in code for cron endpoints; secrets should be managed via environment variables (e.g., CRON_SECRET) and not as plain strings in the source code.
Learnt from: edulelis
PR: elie222/inbox-zero#576
File: packages/resend/emails/digest.tsx:78-83
Timestamp: 2025-07-17T04:19:57.099Z
Learning: In packages/resend/emails/digest.tsx, the DigestEmailProps type uses `[key: string]: DigestItem[] | undefined | string | Date | undefined` instead of intersection types like `& Record<string, DigestItem[] | undefined>` due to implementation constraints. This was the initial implementation approach and cannot be changed to more restrictive typing.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-06-23T12:27:17.978Z
Learning: Cron endpoints must use withError middleware and validate requests with strong secrets (hasCronSecret/hasPostCronSecret); never use weak or predictable secrets.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security-audit.mdc:0-0
Timestamp: 2025-06-23T12:27:05.686Z
Learning: Cron endpoints in API routes must be protected with secret validation middleware such as hasCronSecret or hasPostCronSecret to prevent unauthorized access.
apps/web/app/api/resend/digest/route.ts (20)
Learnt from: edulelis
PR: elie222/inbox-zero#576
File: packages/resend/emails/digest.tsx:78-83
Timestamp: 2025-07-17T04:19:57.099Z
Learning: In packages/resend/emails/digest.tsx, the DigestEmailProps type uses `[key: string]: DigestItem[] | undefined | string | Date | undefined` instead of intersection types like `& Record<string, DigestItem[] | undefined>` due to implementation constraints. This was the initial implementation approach and cannot be changed to more restrictive typing.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/get-api-route.mdc:0-0
Timestamp: 2025-06-23T12:26:11.276Z
Learning: In Next.js App Router, GET API route handlers should be wrapped with either `withAuth` or `withEmailAccount` middleware to ensure consistent error handling and authentication.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security-audit.mdc:0-0
Timestamp: 2025-06-23T12:27:05.686Z
Learning: In Next.js API routes under apps/web/app/api/, always use authentication middleware such as withAuth or withEmailAccount, or ensure custom authentication logic is present if using withError.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-06-23T12:27:17.978Z
Learning: In Next.js/TypeScript API routes, always use authentication middleware (withAuth for user-level, withEmailAccount for account-level) to protect endpoints that handle user data.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security-audit.mdc:0-0
Timestamp: 2025-06-23T12:27:05.686Z
Learning: Cron endpoints in API routes must be protected with secret validation middleware such as hasCronSecret or hasPostCronSecret to prevent unauthorized access.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-06-23T12:27:17.978Z
Learning: Cron endpoints must use withError middleware and validate requests with strong secrets (hasCronSecret/hasPostCronSecret); never use weak or predictable secrets.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/get-api-route.mdc:0-0
Timestamp: 2025-06-23T12:26:11.276Z
Learning: Responses from GET API routes in Next.js should be returned using `NextResponse.json()` for consistency and proper response formatting.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/server-actions.mdc:0-0
Timestamp: 2025-06-23T12:27:23.938Z
Learning: In Next.js projects, server actions should be implemented using the next-safe-action library to ensure type safety, input validation, context management, and centralized error handling.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/data-fetching.mdc:0-0
Timestamp: 2025-07-03T12:02:38.024Z
Learning: For mutating data, use Next.js server actions
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/project-structure.mdc:0-0
Timestamp: 2025-06-23T12:26:59.468Z
Learning: For components with onClick handlers in Next.js App Router, ensure they are client components by including the 'use client' directive at the top of the file.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/data-fetching.mdc:0-0
Timestamp: 2025-07-03T12:02:38.024Z
Learning: Applies to **/*.tsx : For API GET requests to server, use the `swr` package
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/ui-components.mdc:0-0
Timestamp: 2025-06-23T12:27:33.499Z
Learning: When fetching data from an API in a Next.js React application, use the `swr` package for GET requests to the server. This provides built-in caching, revalidation, and error handling.
Learnt from: CR
PR: elie222/inbox-zero#0
File: apps/web/CLAUDE.md:0-0
Timestamp: 2025-07-03T12:02:16.137Z
Learning: Applies to apps/web/app/**/* : NextJS app router structure with (app) directory
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/gmail-api.mdc:0-0
Timestamp: 2025-06-23T12:26:14.189Z
Learning: Never call provider APIs (such as Gmail) directly from routes or components; always use abstraction layers provided by utility wrapper functions.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/project-structure.mdc:0-0
Timestamp: 2025-06-23T12:26:59.468Z
Learning: Use kebab-case for route directories in Next.js App Router (e.g., api/hello-world/route) to maintain consistency and readability.
Learnt from: elie222
PR: elie222/inbox-zero#485
File: apps/web/app/(landing)/login/page.tsx:41-43
Timestamp: 2025-06-05T09:49:12.168Z
Learning: In Next.js App Router, components that use the `useSearchParams` hook require a Suspense boundary to handle the asynchronous nature of search parameter access. The Suspense wrapper is necessary and should not be removed when a component uses useSearchParams.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/gmail-api.mdc:0-0
Timestamp: 2025-06-23T12:26:14.189Z
Learning: Always use wrapper functions from the utils folder (e.g., apps/web/utils/gmail/message.ts) to interact with provider APIs, ensuring maintainability and easier future provider support.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/project-structure.mdc:0-0
Timestamp: 2025-06-23T12:26:59.468Z
Learning: In Next.js projects using the App Router, colocate files in the folder where they're used unless they can be used across the app; if a component can be used in many places, place it in the components folder.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/get-api-route.mdc:0-0
Timestamp: 2025-06-23T12:26:11.276Z
Learning: When using `withAuth` or `withEmailAccount` middleware in GET API routes, explicit try/catch blocks are unnecessary because the middleware handles errors.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-06-23T12:27:17.978Z
Learning: Use consistent error response formats across all API routes to aid in security and debugging without leaking internal details.
.cursor/rules/security-audit.mdc (11)
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security-audit.mdc:0-0
Timestamp: 2025-06-23T12:27:05.686Z
Learning: Regularly run automated security audit scripts and manually review flagged routes to ensure ongoing compliance with security best practices in API route development.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-06-23T12:27:17.978Z
Learning: Cron endpoints must use withError middleware and validate requests with strong secrets (hasCronSecret/hasPostCronSecret); never use weak or predictable secrets.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security-audit.mdc:0-0
Timestamp: 2025-06-23T12:27:05.686Z
Learning: Cron endpoints in API routes must be protected with secret validation middleware such as hasCronSecret or hasPostCronSecret to prevent unauthorized access.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-06-23T12:27:17.978Z
Learning: Security testing for API routes should include manual and automated tests for authentication bypass, IDOR, parameter manipulation, and error information leakage.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security-audit.mdc:0-0
Timestamp: 2025-06-23T12:27:05.686Z
Learning: Do not hardcode secrets directly in code for cron endpoints; secrets should be managed via environment variables (e.g., CRON_SECRET) and not as plain strings in the source code.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-06-23T12:27:17.978Z
Learning: For public endpoints or webhooks, always implement custom authentication or validation logic and never expose user data without proper checks.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-06-23T12:27:17.978Z
Learning: In Next.js/TypeScript API routes, always use authentication middleware (withAuth for user-level, withEmailAccount for account-level) to protect endpoints that handle user data.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security-audit.mdc:0-0
Timestamp: 2025-06-23T12:27:05.686Z
Learning: In Next.js API routes under apps/web/app/api/, always use authentication middleware such as withAuth or withEmailAccount, or ensure custom authentication logic is present if using withError.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/get-api-route.mdc:0-0
Timestamp: 2025-06-23T12:26:11.276Z
Learning: In Next.js App Router, GET API route handlers should be wrapped with either `withAuth` or `withEmailAccount` middleware to ensure consistent error handling and authentication.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-06-23T12:27:17.978Z
Learning: All input parameters (route, query, body) must be validated for type, format, and length before use; use libraries like Zod for request body validation.
Learnt from: CR
PR: elie222/inbox-zero#0
File: .cursor/rules/security.mdc:0-0
Timestamp: 2025-06-23T12:27:17.978Z
Learning: Database queries in API routes must always include user/account scoping (e.g., userId, emailAccountId) to prevent unauthorized data access and IDOR vulnerabilities.
🧬 Code Graph Analysis (1)
apps/web/app/api/resend/digest/route.ts (6)
apps/web/app/api/resend/digest/all/route.ts (1)
  • POST (90-101)
apps/web/app/api/ai/digest/route.ts (1)
  • POST (16-59)
apps/web/app/api/resend/summary/route.ts (1)
  • POST (283-315)
apps/web/utils/middleware.ts (1)
  • withError (182-184)
apps/web/app/api/resend/digest/validation.ts (1)
  • sendDigestEmailBody (40-40)
apps/web/utils/error.ts (1)
  • captureException (60-72)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Static Code Analysis Js
  • GitHub Check: Jit Security
🔇 Additional comments (10)
apps/web/app/api/resend/digest/all/route.ts (1)

65-65: LGTM! Security improvement by removing secret from payload.

Removing CRON_SECRET from the QStash job payload is a good security practice. This aligns with the migration to signature-based verification using verifySignatureAppRouter in the target endpoints, eliminating the need to pass secrets in job payloads.

apps/web/app/api/resend/digest/route.ts (3)

1-1: LGTM! Necessary import for NextRequest typing.

The NextRequest type is needed for the signature verification middleware.


25-25: LGTM! Proper import for QStash signature verification.

Adding verifySignatureAppRouter from @upstash/qstash is the correct approach for securing QStash endpoints.


288-316: Excellent security improvement! Migration to signature verification.

The POST handler has been properly updated to use verifySignatureAppRouter for signature verification instead of manual cron secret validation. This approach:

  • Prevents request spoofing by verifying QStash signatures
  • Eliminates manual secret management
  • Follows QStash security best practices
  • Maintains all existing functionality with proper error handling

The implementation correctly wraps the handler with both withError and verifySignatureAppRouter middleware, ensuring both error handling and signature verification.

.cursor/rules/security-audit.mdc (6)

52-64: LGTM! Comprehensive QStash endpoint security check.

The automated script correctly identifies QStash endpoints by searching for publishToQstash or publishToQstashQueue calls, extracts the API paths, and verifies that the corresponding endpoint files use verifySignatureAppRouter. The clear pass/fail output format makes it easy to identify security issues.


114-126: LGTM! Consistent security testing commands.

The security testing commands section now includes the same QStash endpoint verification logic as the main audit script, ensuring comprehensive security coverage in both automated and manual testing workflows.


173-188: LGTM! Clear examples of QStash security best practices.

The code examples effectively demonstrate the security difference between unprotected and properly protected QStash endpoints. The examples show the correct usage pattern with verifySignatureAppRouter wrapped by withError middleware.


190-194: LGTM! Critical endpoints list for focused security review.

The list of critical QStash endpoints provides clear guidance on which endpoints require special attention during security reviews. This helps ensure that high-risk endpoints are properly secured.


208-211: LGTM! QStash security integrated into code review process.

Adding QStash endpoint verification to the code review checklist ensures that signature verification is consistently applied during development. The emphasis on preventing request spoofing highlights the security importance.


218-221: LGTM! QStash security integrated into regular audit process.

Including QStash endpoint verification in regular security audits ensures ongoing compliance with security best practices. The comprehensive coverage includes checking new endpoints added to QStash queues.

✨ Finishing Touches
  • 📝 Generate Docstrings

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@elie222 elie222 merged commit 4d7e92f into elie222:main Jul 18, 2025
8 of 10 checks passed
@edulelis edulelis deleted the digest-emails-v4 branch July 24, 2025 18:15
@coderabbitai coderabbitai bot mentioned this pull request Sep 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants