PUT /api/v1/relay/test accepts and echoes a raw Nostr private key #6

Open
opened 2026-10-09 16:47:17 +00:00 by padreug · 0 comments
Owner

views_api.py:86-102 (api_test_endpoint): TestMessage.sender_private_key (models.py:36) is a raw secret key hex taken from the request body (:90), used to sign a NIP-04 DM (:93-96), and the response (TestMessageResponse.private_key, models.py:42) returns the secret hex back to the caller (:99). When no key is supplied a fresh one is minted server-side and still returned.

Impact: an nsec transits the LNbits process and lands in request/response bodies, browser memory, any TLS-terminating proxy, and body-capturing access logs. It runs against the direction we have set for the stack (signing moves to the NIP-46 bunker, identity is being stripped out of LNbits). Admin-only (check_admin), so the blast radius is bounded, but the primitive is wrong. The endpoint is also NIP-04, which is deprecated in favour of NIP-17/44.

Fix direction: drop private-key ingestion and never return a key. For a connectivity self-test, generate a throwaway key server-side, sign, and return only event_json and the pubkey; or sign through the bunker. Remove sender_private_key and private_key from the models and the UI form in templates/nostrclient/index.html. If nothing uses the endpoint, delete it.

Found during reforge run #1 (sandbox nostrclient#2).

`views_api.py:86-102` (`api_test_endpoint`): `TestMessage.sender_private_key` (`models.py:36`) is a raw secret key hex taken from the request body (`:90`), used to sign a NIP-04 DM (`:93-96`), and the response (`TestMessageResponse.private_key`, `models.py:42`) returns the secret hex back to the caller (`:99`). When no key is supplied a fresh one is minted server-side and still returned. Impact: an nsec transits the LNbits process and lands in request/response bodies, browser memory, any TLS-terminating proxy, and body-capturing access logs. It runs against the direction we have set for the stack (signing moves to the NIP-46 bunker, identity is being stripped out of LNbits). Admin-only (`check_admin`), so the blast radius is bounded, but the primitive is wrong. The endpoint is also NIP-04, which is deprecated in favour of NIP-17/44. Fix direction: drop private-key ingestion and never return a key. For a connectivity self-test, generate a throwaway key server-side, sign, and return only `event_json` and the pubkey; or sign through the bunker. Remove `sender_private_key` and `private_key` from the models and the UI form in `templates/nostrclient/index.html`. If nothing uses the endpoint, delete it. Found during reforge run #1 (sandbox nostrclient#2).
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
aiolabs/nostrclient#6
No description provided.