Skip to content

fix: razorpay signature verification#351

Open
Akhilesh29 wants to merge 1 commit intoapsinghdev:mainfrom
Akhilesh29:main
Open

fix: razorpay signature verification#351
Akhilesh29 wants to merge 1 commit intoapsinghdev:mainfrom
Akhilesh29:main

Conversation

@Akhilesh29
Copy link

@Akhilesh29 Akhilesh29 commented Mar 19, 2026

Summary by CodeRabbit

  • Bug Fixes
    • Enhanced security of payment signature verification to ensure consistent and reliable validation of all transactions.

@vercel
Copy link

vercel bot commented Mar 19, 2026

@Akhilesh29 is attempting to deploy a commit to the AJEET PRATAP SINGH's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 19, 2026

📝 Walkthrough

Walkthrough

Updated the payment verification method to streamline buffer creation by directly passing Buffer.from() results to crypto.timingSafeEqual instead of using explicit intermediate hex-decoding buffers and length equality checks. Error handling logic remains unchanged.

Changes

Cohort / File(s) Summary
Payment Service Refactoring
apps/api/src/services/payment.service.ts
Simplified verifyPaymentSignature implementation by removing intermediate buffer variables and explicit length validation, passing Buffer.from() results directly to crypto.timingSafeEqual.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰✨ A bunny hops through crypto's dance,
Where buffers now skip their fancy prance,
From hex to safe, a cleaner way,
Signatures verified with less delay!
Thump-thump goes the heart of payment true,
Streamlined and swift—refactored brand new! 🔐

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: razorpay signature verification' directly and specifically describes the main change in the pull request, which is fixing the Razorpay signature verification implementation in the payment service.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
📝 Coding Plan
  • Generate coding plan for human review comments

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

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

You can enable review details to help with troubleshooting, context usage and more.

Enable the reviews.review_details setting to include review details such as the model used, the time taken for each step and more in the review comments.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/api/src/services/payment.service.ts`:
- Around line 127-130: The signature comparison currently passes hex strings
into Buffer.from without the 'hex' encoding and can throw a RangeError when
lengths differ; update the verification logic (where crypto.timingSafeEqual is
used with signature and generatedSignatureHex) to first create buffers by
decoding hex (Buffer.from(signature, 'hex') and
Buffer.from(generatedSignatureHex, 'hex')), check that the two buffers have
equal lengths and return false if they don't, and only then call
crypto.timingSafeEqual to compare the buffers; ensure any invalid-hex input is
handled (e.g., return false) rather than relying on catching the timingSafeEqual
exception.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9cc9f165-16dc-4243-840e-1ae1596828fd

📥 Commits

Reviewing files that changed from the base of the PR and between 1b2f4bd and ee61860.

📒 Files selected for processing (1)
  • apps/api/src/services/payment.service.ts

Comment on lines +127 to +130
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(generatedSignatureHex)
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

according to the current node.js docs, what encoding does Buffer.from(string)use when no encoding is provided, and doescrypto.timingSafeEqualthrow when the twoBuffer inputs have different byte lengths?

💡 Result:

According to the current Node.js documentation (v25.8.1), Buffer.from(string) with no encoding provided uses UTF-8 encoding. This is demonstrated by the example Buffer.from('tést') creating a Buffer with UTF-8-encoded bytes [0x74, 0xc3, 0x a9, 0x73, 0x74]. crypto.timingSafeEqual throws an error (specifically ERR_CRYPTO_TIMING_SAFE_EQUAL_LENGTH, a RangeError) when the two Buffer inputs have different byte lengths. The documentation states that the inputs must have the same byte length, and an error is thrown if they differ.

Citations:


Decode signature inputs as hex before comparison.

The current code passes hex strings to Buffer.from() without the "hex" encoding parameter, which treats them as UTF-8 text instead of decoding the hex bytes. Additionally, when the hex strings differ in length, crypto.timingSafeEqual throws a RangeError (as per Node.js docs), causing the exception to be caught and logged as an error. Pre-decode both inputs as hex and check length equality before calling timingSafeEqual to handle invalid signatures on the normal path without triggering exceptions.

suggested fix
-      return crypto.timingSafeEqual(
-        Buffer.from(signature),
-        Buffer.from(generatedSignatureHex)
-      );
+      const signatureBuffer = Buffer.from(signature, "hex");
+      const generatedSignatureBuffer = Buffer.from(
+        generatedSignatureHex,
+        "hex"
+      );
+
+      if (signatureBuffer.length !== generatedSignatureBuffer.length) {
+        return false;
+      }
+
+      return crypto.timingSafeEqual(
+        signatureBuffer,
+        generatedSignatureBuffer
+      );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/api/src/services/payment.service.ts` around lines 127 - 130, The
signature comparison currently passes hex strings into Buffer.from without the
'hex' encoding and can throw a RangeError when lengths differ; update the
verification logic (where crypto.timingSafeEqual is used with signature and
generatedSignatureHex) to first create buffers by decoding hex
(Buffer.from(signature, 'hex') and Buffer.from(generatedSignatureHex, 'hex')),
check that the two buffers have equal lengths and return false if they don't,
and only then call crypto.timingSafeEqual to compare the buffers; ensure any
invalid-hex input is handled (e.g., return false) rather than relying on
catching the timingSafeEqual exception.

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.

1 participant