Wallet: warn users to set an NWC spending budget before connecting

An NWC connection string is a spend credential stored client-side. If a
connection is granted an unlimited budget, a compromise could drain the
wallet up to that limit. Add a prominent security notice in the "Connect
NWC Wallet" dialog instructing users to set a small daily budget and scope
the connection to pay_invoice only, and reminding them it can be revoked in
their wallet. This caps the blast radius of the credential the app must hold.

(The CSP referenced in the report was already added in the prior commit via
public/_headers; storage of nsec/NWC strings in localStorage is inherent to
client-side Nostr signing/payments and is mitigated by the XSS + CSP work.)

Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
This commit is contained in:
shakespeare.diy 2026-08-16 22:16:05 +07:00
parent b4b2375921
commit acfbff6a07

View file

@ -1,5 +1,5 @@
import { useState, forwardRef } from 'react'; import { useState, forwardRef } from 'react';
import { Wallet, Plus, Trash2, Zap, Globe, WalletMinimal, CheckCircle, X } from 'lucide-react'; import { Wallet, Plus, Trash2, Zap, Globe, WalletMinimal, CheckCircle, X, ShieldAlert } from 'lucide-react';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { import {
Dialog, Dialog,
@ -63,6 +63,21 @@ const AddWalletContent = forwardRef<HTMLDivElement, {
rows={3} rows={3}
/> />
</div> </div>
{/* Security guidance: an NWC string is a spend credential. Encourage users
to cap it in their wallet so a compromised connection can't be drained. */}
<div className="flex gap-2.5 rounded-lg border border-amber-500/30 bg-amber-500/10 p-3">
<ShieldAlert className="h-4 w-4 flex-shrink-0 text-amber-500 mt-0.5" />
<div className="space-y-1 text-xs text-amber-200/90">
<p className="font-semibold text-amber-300">Set a spending limit first</p>
<p>
This string lets SkateSpots pay Lightning invoices from your wallet. In
your wallet app, give this connection a small <strong>daily budget</strong>{' '}
(e.g. a few thousand sats) and enable only <strong>pay_invoice</strong>.
Never paste a connection with an unlimited budget. You can revoke it in
your wallet any time.
</p>
</div>
</div>
</div> </div>
)); ));
AddWalletContent.displayName = 'AddWalletContent'; AddWalletContent.displayName = 'AddWalletContent';