Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

audit: constructProofs binds neither signature amount nor keyset id to the wallet's request — tampered/hostile swap responses mint-label the proofs (PoC reproduced; fix lands in gonuts-tollgate)

Open
#831 1 comment 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
12/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Active
Tech stack
go
Domain
security

Research direction

The bug lives in the forked wallet's constructProofs (around wallet/wallet.go:2076-2121, in gonuts-tollgate, not this repo), which is where the signature amount and keyset id are trusted instead of checked against the blinded message request. Start by reading that function and the in-package PoC reusing pending_swaps_test.go fixtures. Done means each signature's Amount and Id are checked against the request per index, the unblinded C is verified against Y, and a test covers the tampered-amount case.

Written by the indexing model from the issue text.

Description

From the 2026-10-09 Cashu audit (fork @ d7591d2 + main + #771). PoC reproduced in-package. Fix belongs in gonuts-tollgate (fork-first, then pin bump — the fork repo has issues disabled, tracked here per the #705 pattern).

Finding

Fork wallet/wallet.go constructProofs (≈:2076-2121) accepts whatever BlindSignature.Amount/.Id the response carries: the unblind key is selected BY the signature's own amount label — never compared against blindedMessages[i].Amount/.Id (what the wallet actually requested) — the proof is mint-labeled, there is no post-unblind C-vs-Y verification, and a stripped (nil) DLEQ is skipped silently (so DLEQ presence does not close this).

Attack path

MITM on an http:// mint URL (cloud-lab topology uses one; config does not forbid it) or a malicious mint relabels one signature in a /v1/swap response. Receive returns newProofs.Amount() — the mint-labeled sum — straight into calculateAllotment (merchant.go:2069), which sizes the customer's session; the ecash path has no amount ceiling (the ln-invoice path caps at maxLightningInvoiceSats; steps*StepSize is unbounded here). Also applies to the #771/#497 replay path (resumeOneSwap → same constructProofs).

PoC (in-package, reusing pending_swaps_test.go fixtures)

request 8 sat of outputs → stub mint signs honestly → tampered[0].Amount = 64
constructProofs(tampered, outputs, secrets, rs, keyset) → err=nil, proofs.Amount()=71

Impact: inflated labels → oversized sessions (repeatable revenue theft); deflated → silent under-credit; garbage proofs pollute balance accounting. CWE-345/CWE-347. Severity MEDIUM (preconditions: http-mint MITM or hostile mint).

Minimal fix

constructProofs must require sig.Amount == msg.Amount && sig.Id == msg.Id per index and verify the unblinded C against Y under the selected key; consider refusing stripped DLEQ on keysets that announced it.

Cross-refs: #703, #497, #771.

Dominant language
Go
Stars
12
Forks
14
Avg merge
1d 5h
Merged PRs (30d)
239

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from OpenTollGate/tollgate-module-basic-go

All issues in OpenTollGate/tollgate-module-basic-go

Similar issues

More Go issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.