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

/ln-invoice settlement grants the gate to the quote-status POLLER, not the quote owner — owner later reads access_granted=true with no gate

Open
#721 0 comments 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
48/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
go

Research direction

Start in src/main.go at the /ln-invoice handler, monitorLightningQuote, and clientMACFromSocket; trace how quote state records the creator and how settlement sets access_granted. Then read the tests/happy-path README and run the harness with two seeded clients. Done when a poll by the second client grants only the creator's MAC and a regression test verifies that behavior.

Written by the indexing model from the issue text.

Description

Summary

The Lightning-quote settlement path grants the gate to whoever polls the quote's status, not to the client that created (and paid for) the quote. A second client on the same router can poll a settled quote; the module then authorizes THE POLLER's MAC, stops the quote monitor, and subsequent polls by the real owner return access_granted: true — while the owner's gate never opened.

Severity: S2/S3 (funds-safe, access/UI-honesty). No value is lost, but the paying customer's portal can display a granted session that never gates their device — the "misleading success" class this project explicitly hunts.

Verified on

  • Commit: 68ad5144ab09cb4723d8f3f655cbba1ac7ea9de5 (main, 2026-10-07)
  • Surface: /ln-invoice create + status-poll flow, offline happy-path harness with two seeded loopback clients

Evidence (verbatim module log)

Quote created and paid by client A (127.0.0.2, lease MAC 02:00:00:00:00:20). Client B (127.0.0.1, MAC 02:00:00:00:00:21 — a different probe) polls the quote status:

Hit /ln-invoice endpoint            module=main  remote_addr="127.0.0.1:35430"     <- poller is client B
Replacing existing timed gate with indefinite data-based gate.  mac_address="02:00:00:00:00:21"  module=valve
Authorization successful for MAC    mac_address="02:00:00:00:00:21"  output="Auth: 02:00:00:00:00:21 - Granted\n"
monitorLightningQuote: stopping for hp-stub-quote-0001 — access granted

After this, client A's poll returns the quote JSON with "access_granted": true — but the fake-ndsctl log contains AUTH for .21 ONLY, never .20. The happy-path suite's enforcement:gate-opens-on-recognised-payment check fails on exactly this mismatch.

Reproduce

The packaged harness (tests/happy-path) reproduces it directly — it needs two resolvable clients, which on a host means seeded lease entries (the harness does not seed them itself; see the companion issue about the missing lease fixture):

git clone https://github.com/OpenTollGate/tollgate-module-basic-go && cd tollgate-module-basic-go
git checkout 68ad5144ab09cb4723d8f3f655cbba1ac7ea9de5
# seed two loopback clients exactly as the harness's README documents
printf '1700000000 02:00:00:00:00:21 127.0.0.1 hp-probe *\n1700000000 02:00:00:00:00:20 127.0.0.2 hp-client *\n' > /tmp/dhcp.leases
# extract a published or locally built .apk (see tests/happy-path/README.md), then:
HP_PYTHON=<python-with-playwright> bash tests/happy-path/run.sh --artifact <extracted-dir> --strict --keep
grep -E 'gate-opens|granted-session' <output>

Expected: AUTH logged for the quote OWNER's MAC (…:20). Actual: AUTH for the POLLER (…:21), owner later reads access_granted: true.

Manual curl-only variant (any host running the module with /tmp/dhcp.leases seeded as above):

  1. From client A: curl -X POST http://127.0.0.2:2121/ln-invoice -d '{"amount":210,"mint_url":"<mint>"}' → note quote id.
  2. Settle the quote at the mint (FakeWallet auto-settles; or wait).
  3. From client B: curl "http://127.0.0.1:2121/ln-invoice?quote=<id>" (the status GET the monitor/portal uses).
  4. Observe: ndsctl auth fired for B's MAC; A's subsequent poll says access_granted: true.

Troubleshooting guide

  1. Where the decision happens: src/main.go — the /ln-invoice handler and monitorLightningQuote (the log line "monitorLightningQuote: stopping … access granted" names it). The grant path resolves the client from the REQUEST SOCKET (clientMACFromSocket) at poll time.
  2. The intended contract: the module's client-identity doctrine says identity is always the socket — that is right for WHO is asking, but for quote settlement the grant should go to the identity recorded when the QUOTE was created (the payer), because the poller is only an observer. Check whether the quote record (monitor goroutine's state) retains the creator's MAC.
  3. Why the portal usually masks it: in production the paying browser is normally both creator and poller — the bug surfaces when any other LAN client (or a monitoring agent) knows the quote id. Quote ids are likely unguessable in practice — quantify that before deciding severity.
  4. Related test that encodes the intent: tests/happy-path api:client-identity / the C7b contract checks (X-TollGate-Client-MAC, ignored ?mac= claims) — the claim-ignoring is correct; this issue is about which socket the GRANT binds to.

Fix hints

  • Persist the quote creator's resolved MAC with the quote at creation; on settlement (monitor or poll-triggered), authorize THAT MAC. The status-poll response's access_granted should reflect the QUOTE's grant state, and include enough identity (or an error) that a non-owner poll cannot be mistaken for the owner's success.
  • Add a regression test with two seeded clients: creator pays, other client polls, assert ndsctl AUTH fires for the creator only.

References

  • Happy-path harness + README (client-identity contract, lease-seeding precondition): tests/happy-path/
  • Client-identity doctrine: README "client is identified by the MAC address their device uses … always resolved from the request's socket"
Dominant language
Go
Stars
12
Forks
14
Avg merge
1d 6h
Merged PRs (30d)
217

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.