Paste Target Guard

Compares a pasted IBAN, UPI ID or wallet address with what was copied or expected, so a clipboard hijacker's swapped address is caught before paying.

StopsHelps catch a clipboard hijacker swapping the payee address

Installation

pnpm dlx shadcn@latest add https://bollard-ui.vercel.app/r/paste-target-guard.json

The files land in your project. They're yours to edit.

Usage

paste-target-guard-usage.tsx
import { PasteTargetGuard } from "@/components/ui/paste-target-guard"

<PasteTargetGuard label="Payee IBAN" expected={INVOICE_IBAN} defaultValue={SWAPPED} placeholder="DE00 0000 0000 0000 0000 00" />

What it catches

  • Pasted address that differs from what was copied on the page
  • Address that differs from the expected one
  • Look-alikes of saved recipients
  • Matching start and end with a different middle (the clipper trick)

Props

PasteTargetGuard props
PropTypeDefault
label

Visible label.

string"Recipient"
value

Controlled value.

string—
defaultValue

Initial value when uncontrolled.

string""
onValueChange

Called with the value on every change.

(value: string) => void—
kind

Force the kind instead of detecting it.

PasteTargetKind—
expected

What the user typed or confirmed earlier (step 1, the invoice on file). Compared when nothing was copied on this page.

string—
watchCopy

Remember IBANs, UPI IDs and wallet addresses copied anywhere on this page, to compare with what gets pasted.

booleantrue
known

Saved recipients. A value that copies one's start and end but not its middle is flagged as a look-alike.

KnownTarget[][]
chunkSize

Characters per group in the comparison.

number4
edgeGroups

Groups shown at each end before the middle collapses.

number2
onMismatch

Called when a mismatch is shown.

(detail: { value: string; reference: string; source: "copied" | "expected" | "known" }) => void—
copiedTitle

Title when the paste differs from what was copied.

string"This isn't what you copied"
expectedTitle

Title when the value differs from the expected one.

string"This doesn't match what you entered earlier"
lookalikeTitle

`{label}` is filled in.

string"Looks like “{label}”, but it isn't"
copiedText

Explains the copied-vs-pasted mismatch.

string"It changed between copy and paste. Malware on this devic…
staleCopiedTitle

Title and text when the page lost focus after the copy, so the user may have copied something else since.

string"This isn't what you copied on this page"
staleCopiedText

Explains a mismatch with an older copy.

string"If you copied it from somewhere else since, check it aga…
expectedText

Explains the expected-vs-entered mismatch.

string"Check it against the original before you send anything."
differText

Screen reader summary of the comparison. `{count}` and `{total}` are filled in.

string"{count} of {total} groups differ."
endsMatchText

Warns that the ends match but the middle differs.

string"The start and end match, so a quick glance would pass. L…
copiedLabel

Row label for what was copied.

string"Copied"
expectedLabel

Row label for the expected value.

string"Earlier"
knownLabel

Row label for the saved recipient.

string"Saved"
pastedLabel

Row label for what was pasted.

string"Pasted"
middleLabel

`{count}` is filled in.

string"+{count}"
showAllLabel

Accessible label to show every group.

string"Show every group"
useLabel

`{label}` is filled in for saved recipients.

string"Use the original"
keepLabel

Button text to keep the pasted value.

string"Keep this one"
matchText

Shown when the paste matches what was copied.

string"Matches what you copied, every character."

* required. Also accepts the native props of <input> (className, aria-*, data-*…), passed through to it.

Accessibility

  • Visible label; input has aria-invalid on mismatch and is described by the check
  • Mismatches use role=alert; a match is announced politely
  • Show-all and keep buttons have aria-labels

Only what the source does. Test with your own screen reader and content before shipping.

Limitations

This is a UX guard rail. Enforce on the server: Confirm the payee with your provider and require step-up confirmation for new or changed recipients on the server.

  • Only sees copies made on this page (watchCopy) or the expected value you pass
  • Malware that also changes what the page shows can't be detected
  • Doesn't verify the payee; use Payee Check or your provider

What it stops

Helps catch a clipboard hijacker swapping the payee address

Also known as

clipboard hijacking · clipper · upi id · iban · wallet address · crypto · payee · send money

Field type

Dependencies

Pairs well with