AI-generated analysisPublished automatically and not human-verified. Validated context appears in community notes below.
← Watch feed
Moderate 62 Bitcoin

zpay32: reject duplicate payment hash fields

Public commit record

What the developer wrote

Authored by Olaoluwa Osuntokun

98/100 · Strong
zpay32: reject duplicate payment hash fields

In this commit, we reject BOLT 11 invoices that contain more than one
payment hash (`p`) field. `zpay32.Decode` previously kept the first
supported payment hash and ignored later fields, so the interpreted
payment hash depended on field order.

The decoder now tracks whether a `p` field has appeared separately from
whether its contents parsed successfully, and any later `p` field returns
`ErrDuplicatePaymentHash`. This covers identical hashes, distinct hashes,
and a malformed first field followed by a valid one. The change is
deliberately stricter than the current BOLT 11 text, which tells a reader
to use the first `p` field; it is motivated by lightning/bolts#1357, and
will be backported to the v0.20.5 and v0.21.4 releases.

We also replace the stale comment above parse32Bytes, which quoted the
old BOLT 11 rule that a reader must skip over 32-byte fields with an
unsupported length. The current reader requirements say the opposite: a
reader must fail the payment if a fixed-length field (p, h, s, n) does
not have the correct length. The new comment states that reporting the
field as absent is a known divergence, and explains why the end result
for the payment hash is the same either way.

In the tests, we cover identical and distinct duplicate hashes, a
malformed first field followed by a valid one, and the signed vectors. A
valid variant of the flipped vector keeps the wrong-length h and n
fields, so the coverage that such fields are skipped survives. The
duplicate vector in the decode table pins ErrDuplicatePaymentHash
through a new wantErr field rather than asserting any decode error.
✓ Descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Explains rationale or failure mode✓ Mentions testing or verification✓ Links an issue, advisory, or supporting reference
The short version

What changed, and why it matters

This change tightens how LND reads Lightning invoices. Previously, if an invoice contained more than one payment hash field, LND would silently keep the first valid one and ignore the rest. Now it rejects such invoices outright. This prevents an attacker from potentially tricking a wallet into interpreting a different payment hash than intended, which could lead to payments being sent to the wrong destination or failing in unexpected ways. The fix is being backported to two release branches.

Recommended action

Apply this patch and its backports. Review any integrations that rely on LND accepting invoices with multiple payment hash fields, as they will now fail to decode. Consider monitoring for invoice parsing errors after deployment.

Security signals we found

01

Behavioral change from silent first-field acceptance to explicit rejection of duplicate payment hash fields

02

Prevents invoice parsing from depending on field ordering when multiple payment hashes are present

03

Covers malformed first field + valid second field, closing a potential bypass

04

Backported to v0.20.5 and v0.21.4 release branches, indicating security/robustness relevance

05

Referenced upstream BOLT standard discussion (lightning/bolts#1357)

Risk score

Why this scored 62/100

Our methodology →
Potential impact 18/30
Exploitability 12/25
Stealth signal 8/15
Affected reach 12/15
Confidence 8/10
Evidence quality 4/5
Human-validated context

Community notes

Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.

No validated notes yet.

The AI analysis stands alone for now. Submit a note if you can add evidence or important context.