Skip to content

Conversation

@erickcestari
Copy link

@erickcestari erickcestari commented Dec 11, 2025

unwrapPacket passes the full 2600-byte hopInfo buffer to DecodeHopPayload, but only the first 1300 bytes contain routing info. The remaining 1300 bytes are zero-padding used for XOR decryption.

A malformed packet with a large payload size field can cause the decoder to read beyond the routing info into the padding area. This creates parsing inconsistencies with other implementations that enforce the 1300-byte boundary.

Found through differential fuzzing (bitcoinfuzz) where Core Lightning and rust-lightning rejected the malformed onion packet.

@gemini-code-assist
Copy link

Summary of Changes

Hello @erickcestari, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a critical fix to how onion packet payloads are processed, specifically preventing DecodeHopPayload from reading beyond the intended routing information boundary. Previously, a malformed packet could exploit this by specifying an oversized payload, causing the decoder to read into the zero-padding area. The change ensures that only the valid routing information portion of the hopInfo buffer is processed, enhancing parsing consistency and robustness against malformed inputs. Additionally, new tests have been added to validate this boundary enforcement, alongside minor test function name corrections.

Highlights

  • Payload Boundary Enforcement: The unwrapPacket function now explicitly limits the hopInfo buffer passed to DecodeHopPayload to routingInfoLen (1300 bytes). This prevents the decoder from reading into the zero-padding area of the buffer, addressing a potential parsing inconsistency with malformed packets.
  • New Test Case for Malformed Packets: A new test, TestUnwrapPacketBeyondRoutingInfoBoundary, has been added to verify that unwrapPacket correctly handles malformed onion packets where the payload size attempts to exceed the routing information boundary, ensuring it fails as expected.
  • Test Function Renames: Several test functions in sphinx_test.go were renamed to correct a typo, changing 'Relpay' to 'Replay' (e.g., TestSphinxNodeRelpay is now TestSphinxNodeReplay).
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request addresses a potential vulnerability in unwrapPacket where a malformed packet could cause the decoder to read beyond the intended routing information boundary. The fix correctly restricts the data passed to DecodeHopPayload by slicing the buffer to the appropriate length. This is a solid and important correction. The addition of a specific test case, TestUnwrapPacketBeyondRoutingInfoBoundary, is excellent as it directly verifies the fix against the described vulnerability. I've also noted the correction of typos in other test function names. My review includes a couple of minor suggestions for the new test code to align with the repository's style guide concerning line length.

unwrapPacket passes the full 2600-byte hopInfo buffer to DecodeHopPayload,
but only the first 1300 bytes contain routing info. The remaining 1300
bytes are zero-padding used for XOR decryption.

A malformed packet with a large payload size field can cause the decoder
to read beyond the routing info into the padding area. This creates
parsing inconsistencies with other implementations that correctly enforce
the 1300-byte boundary.
Rename TestSphinxNodeRelpay* to TestSphinxNodeReplay*.
@erickcestari erickcestari force-pushed the fix-hop-payload-bounds branch from a8eb498 to 3fad506 Compare December 11, 2025 11:53
@morehouse
Copy link

Maybe we should also change DecodeHopPayload to enforce the correct size, rather than UINT16_MAX.

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