Homoglyphs and Unicode confusables in payee names: the cheapest attack on approvals
There is an attack on payment approvals that costs nothing, requires no malware, and defeats a careful reviewer reading attentively. It exploits the fact that two different strings can render as the same picture.
How do lookalike characters defeat a payee approval?
The database stores two distinct strings; the screen renders them identically. A Cyrillic а and a Latin a occupy different code points and look the same, so an approver comparing two payee names visually is comparing pixels, not data. Normalising and comparing at code-point level catches it; looking never will.
- Unicode contains many characters that render identically or near-identically to Latin letters. A payee name using them is a distinct string that displays the same.
- The Unicode Consortium publishes confusables data specifically for this problem, and almost no financial application consumes it.
- Normalisation plus confusable detection at payee creation is a small amount of code and closes the attack at the point of entry.
Part of Payment release authorization
The mechanism, precisely
Unicode assigns distinct code points to characters from many scripts. Several of those characters are visually identical, or near-identical, to Latin letters in common fonts.
Latin small a U+0061 a
Cyrillic small a U+0430 а ← renders identically in most fonts
Greek small omicron U+03BF ο
Latin small o U+006F o ← near-identical
Fullwidth Latin A U+FF21 A
Latin small dotless i U+0131 ı
A payee named with a Cyrillic character in place of a Latin one is, to a database, a different vendor. To an approver reading the screen, it is the same vendor.
Why this is cheaper than every other payment attack
| Attack | Requires | Cost |
|---|---|---|
| Vendor email compromise | Phishing the vendor, persistence, timing | Moderate |
| Voice cloning callback | Audio samples, tooling, live performance | Moderate |
| Session theft | Malware delivery or proxy phishing infrastructure | Moderate |
| Homoglyph payee | A keyboard | Zero |
It also requires no access to your systems beyond the ability to submit a vendor record — through an onboarding portal, a supplier self-service form, or a social-engineered request to AP.
Where it lands in the payment flow
Two variants, with different targets.
- Duplicate vendor. A new payee is created with a name visually identical to an existing supplier and a different bank account. Invoices are submitted against it. Approvers see a familiar name.
- Beneficiary name mismatch. The payee name on the payment differs from the account holder name at the receiving bank in a way that confirmation-of-payee style checks may or may not catch, depending on their normalisation.
What the Unicode Consortium already provides
This is a solved problem in specification terms and an unsolved one in deployment terms.
Unicode Technical Standard 39, on security mechanisms, defines identifier profiles and provides confusables data mapping characters to a skeleton form. Two strings whose skeletons are equal are confusable. Unicode Standard Annex 15 defines normalisation forms — NFC and NFD — that resolve composition differences.
Together they give a deterministic test. It is not heuristic, it is not machine learning, and it is a few lines of code against a published data file.
The control at payee creation
- Normalise. Apply NFC to the submitted payee name. This resolves the case where an accented character is submitted as base plus combining mark.
- Restrict the script set. Decide which scripts are legitimate for your payee population. A business paying only domestic suppliers has no reason to accept mixed-script names.
- Compute the skeleton. Using the published confusables mapping, reduce the name to its skeleton form.
- Compare against existing payees. A skeleton collision with an existing payee is not an error to reject silently — it is a flag for review, because legitimate similar names exist.
- Record the decision. If a reviewer clears a collision, record who cleared it and why.
Step two does most of the work at the lowest cost. Mixed-script payee names are almost never legitimate in a domestic payables population, and rejecting them outright removes the attack.
Why the approval screen cannot fix this alone
Some organisations respond by rendering suspicious characters visibly — highlighting non-Latin characters in payee names at approval time.
That helps and it is a second line rather than a first. The approver is being asked to notice something at the end of a process where the record should never have been created. Detection at creation is cheaper, earlier and does not depend on an approver's attention at the wrong moment.
Signing and canonicalisation
There is a subtler point for anyone signing payment statements. If the payee name is part of the signed content, normalisation must happen before signing and must be deterministic, or two systems will compute different hashes for the same logical name.
Freeze the normalisation form in the specification, apply it before canonicalisation, and reject confusables rather than signing them. A signature over a homoglyph name is a cryptographically perfect record of the wrong payee.
The confusable families worth detecting
| Technique | Example effect |
|---|---|
| Cross-script homoglyphs | Cyrillic а, е, о and Greek ο render as Latin letters |
| Zero-width characters | Two names render identically while differing in bytes |
| Trailing or doubled whitespace | A name that appears to match exactly |
| Directional override characters | Displayed order differs from stored order |
Unicode Technical Standard 39 exists precisely for this and publishes confusable mappings. Running a payee name through skeleton normalisation and comparing against existing payees is a few lines of code and catches every family above.
Objections and honest limits
“Our payee names come from the vendor master, which is controlled.” The attack is at creation or amendment of that record, not at payment. Normalise on write and compare against the existing set, not on approval.
“We would spot a different company name.” The name is not different. That is the entire technique — it renders identically, and the approver has no way to see otherwise.
Detecting confusables in payee data
- Normalise to a Unicode skeleton. UTS 39 confusable mapping, applied at record creation and amendment.
- Compare against every existing payee. A skeleton collision with a different underlying string is the signal.
- Reject or flag mixed-script names. Unless the vendor legitimately trades under one.
- Strip and reject invisible characters. Zero-width, directional overrides and doubled whitespace have no legitimate place in a payee name.
Terms used here
- Homoglyph
- A character from one script that renders identically to one from another.
- Skeleton
- A normalised form under UTS 39 in which confusable characters map to a single representative, so lookalikes collide.
- Mixed-script name
- A string drawing characters from more than one script, which is occasionally legitimate and usually a signal.
Frequently asked questions
Is this a real attack or a theoretical one? Homoglyph techniques are well documented in domain and identifier attacks. The payee-name variant is the same mechanism applied to a field that is compared visually and stored exactly.
Will rejecting mixed-script names break legitimate vendors? For organisations with international suppliers, yes — which is why the script set should match your actual payee population rather than a default.
Does confirmation of payee solve it? It depends entirely on how the scheme normalises names before matching. Ask your bank what normalisation their matching applies.
Where should the check live? At payee creation, in the vendor master workflow. Detection at approval is a useful second line and a poor first one.
Why can't the approver spot it? The strings render identically. There is nothing visible to spot, which is why the check must be mechanical and must happen on write.
Where should the check run? At payee creation and amendment, against the existing payee set. Checking at approval is too late and asks a human to do a machine's job.
Is there a standard for this? Unicode Technical Standard 39 publishes confusable mappings and a skeleton algorithm designed for exactly this comparison.
Where this fits in Manav
Manav renders the full beneficiary details and the delta from what was on file, binds the approver's signature to that exact payload, and has the payment service recompute the digest before it releases funds.