Quishing: What Marketers Must Check Before a Code Goes to Print
Quishing defence for the brand whose code is on the poster, not the consumer scanning it: overlay attacks, lookalike domains, and edit-time checks.
Most articles about QR code phishing are written for the person holding the phone: don't scan codes from strangers, check the URL before you tap through. That advice is fine as far as it goes, but it leaves out the party actually exposed here, the brand whose logo is on the poster and whose printed code someone else can tamper with. If your code gets stickered over, or your destination is quietly compromised months after print, the consumer who gets phished isn't the one whose trust takes the hit. You are.
Four attacks, four different defences
| Attack | What it targets | Primary defence | Who usually notices first |
|---|---|---|---|
| Physical overlay | The printed code itself | Tamper-evident placement, a recognisable branded frame, lamination | A staff member on a scheduled walk-past, rarely a customer |
| Homograph domain | A destination URL with substituted characters | Character-by-character review, automated lookalike-domain detection | Whoever reviews the destination before print, if they're looking closely enough |
| Destination compromised after launch | A domain or page that was legitimate and later isn't | Re-screening the destination at every edit, not only at creation | Usually nobody, until a customer reports it |
| Unknown or bad verdict passed through anyway | A visitor sent to an unverified destination | A fail-closed interstitial that blocks by default | The platform itself, at the moment of the scan |
Each of these four sits at a different point in a code's life, from the moment it's printed through to years into circulation, which is exactly why no single check, run once, covers all of them.
The physical overlay attack, and what actually defends against it
The simplest attack on a printed QR code needs no technical skill whatsoever: print a sticker the same size as the original code, encode it with a different destination, and place it directly over the legitimate one. Anyone scanning the poster afterward gets the attacker's destination, with no visual sign anything is wrong, since the surrounding artwork, the brand name, the framing, all still belong to you.
The countermeasures are physical, matching the physical nature of the attack. Placement in a genuinely tamper-evident location, somewhere a sticker applied after the fact would visibly disturb the surrounding material, removes the easiest version of this attack outright. A recognisable branded frame or consistent visual treatment around every code you print gives a returning customer a pattern to notice when it's missing or looks different, which a generic, unbranded code never gives them. Lamination over a code placed somewhere genuinely public, a community noticeboard, a bus shelter, a shared entrance, raises the physical effort needed to convincingly overlay it. None of these measures make an overlay impossible, but each one raises the cost and the visibility of attempting it, which is what a determined but not sophisticated attacker is actually deterred by.
The measure most brands skip entirely is the simplest one: checking on a schedule. A code placed in a high-traffic public location and never physically re-inspected after launch could carry an overlay for weeks before anyone notices, particularly if scan volume doesn't obviously collapse (a convincing overlay still gets scanned, it just sends people somewhere else). A periodic walk-past of any code placed somewhere the public can physically reach it, comparing what's actually there against what was installed, catches an overlay far sooner than waiting for a customer complaint to surface one.
Homograph and lookalike destination domains
A subtler attack doesn't touch the printed code at all; it targets the destination domain itself, hoping nobody looks closely enough to notice. A homograph attack substitutes visually similar characters, a lowercase "l" for a capital "I", a zero for the letter "O", certain Cyrillic characters that render identically to Latin ones, into a domain name that looks correct at a glance but resolves somewhere else entirely. A lookalike domain takes a related but different approach: registering a domain that's plausible-sounding and adjacent to a real brand's name, hoping a rushed reviewer approves it without checking the registration against the brand it resembles.
Both attacks exploit the same weakness: a human reviewing a destination URL quickly, under time pressure, before a print run ships, is exactly the reviewer least likely to catch a single substituted character. Automated detection, checking a destination against known homograph patterns and flagging domains that resemble established ones too closely, catches what a rushed manual review reliably misses. This is worth building into your review process regardless of what any single platform does automatically, since the habit of pausing on a destination URL and reading it character by character, not just recognising its general shape, is a cheap defence against an attack that otherwise relies entirely on nobody looking closely.
Making the physical check a habit, not a one-off
The inspection schedule matters more than any single measure listed above, because every physical defence, the frame, the lamination, the tamper-evident placement, only tells you something the moment someone actually looks. A monthly or quarterly walk-past for any code placed somewhere the public can physically reach it, a shopfront, a community board, a shared entrance, a transit shelter, is a small, recurring cost against a risk that otherwise goes unnoticed for as long as nobody happens to look closely. Building this into an existing routine, the same visit that checks stock levels or refreshes seasonal signage, costs almost nothing extra and catches an overlay far sooner than waiting for scan volume to look unusual or for a customer to say something.
Assign the check to a specific person or role rather than leaving it as everyone's implicit responsibility, since a check nobody is explicitly accountable for is a check that quietly stops happening the first time anyone gets busy. A short, dated log, even a single line noting the code was inspected and matched what was installed, gives you something to point to later if a placement's history is ever in question.
Why creation-time checking isn't enough
A common assumption is that once a destination has been checked and approved, it's settled. It isn't, because a destination is a URL that continues to exist in the world, and the world keeps changing around it. A domain can lapse and be re-registered by someone unrelated to the original owner. A page that was legitimate can later be compromised by an unrelated breach, turning a link that used to lead somewhere safe into one that doesn't, without the QR code itself, or the person who originally approved it, changing anything at all.
This is the practical argument for checking a destination again at the moment of every edit, not only once at creation. Editing a dynamic code's destination is, by definition, the one moment a new destination enters the picture, which makes it exactly the moment a fresh check is most valuable, not the moment to skip because "we already checked this code once." A destination that was clean when a campaign launched carries no guarantee about what it is months later, and the only way to actually know is to check again each time it changes, not to assume the original approval still holds.
The fail-closed default, and why it's worth the scans it costs
When a destination check returns a genuinely unknown or actively bad verdict, there are two ways to design the response: pass the visitor through anyway and flag it for later review, or block the redirect outright and show an interstitial explaining why. The first option preserves every scan's conversion rate, uninterrupted, at the cost of occasionally sending someone somewhere dangerous while the review catches up. The second option, blocking by default on an unknown or bad verdict, sacrifices some conversions, including the ones that would have been perfectly safe, in exchange for never knowingly sending anyone through an unverified redirect.
Fail-closed is the correct default despite the cost, because the asymmetry between the two failure modes isn't close. A blocked-but-safe scan costs you one conversion and mildly inconveniences one visitor. A passed-through-but-dangerous scan can cost a customer real harm and costs your brand the specific kind of trust that's expensive to rebuild once it's gone. Treating an unknown verdict as equivalent to a bad one, rather than benefit-of-the-doubt safe, is the more conservative choice, and it's the right one for exactly the situations this entire post is about.
What to do when a customer reports a suspicious code
A customer who takes the time to report a code that looked wrong has already done the hardest part of catching an attack: noticing it. Thank them specifically rather than with a generic acknowledgement, since a specific thank-you signals the report was actually read and taken seriously. Then treat the placement as compromised until you've personally verified both the physical code and its current destination, rather than waiting for a full investigation to conclude before pausing traffic to it. If your own inspection can't immediately confirm the code is legitimate, escalate through a public abuse-reporting channel rather than sitting on an unconfirmed report, since the cost of a brief, unnecessary pause is far smaller than the cost of leaving a genuinely compromised code live while you deliberate.
What this means for your next campaign
Build a physical re-inspection schedule for any code placed somewhere the public can reach it, not just a launch-day check, and treat a branded frame and tamper-evident placement as standard, not optional, wherever a code is genuinely exposed. Push for destination re-screening on every edit, not only at creation, since who actually controls a code's destination is the question this entire defence rests on. And accept the fail-closed trade-off in advance, before an incident forces the conversation, so nobody's arguing for a more permissive default in the middle of an actual problem.
Straight answers
What is quishing, in terms a marketer needs to act on?
Quishing is phishing delivered through a QR code instead of a link in an email. For a brand, the risk isn't reading a suspicious message; it's that someone else can physically alter a code you've already printed and put your name next to a destination you never approved. The practical response is the same discipline you'd apply to any brand asset in public: check it's still yours, and check where it sends people, on a schedule, not just at launch.
Can someone really just stick a fake QR code over a real one?
Yes, and it requires no technical skill at all, just a sticker sized to cover the original. This is why a physical overlay is the most common quishing method aimed at brands, and why the defence is physical too: tamper-evident placement, a recognisable branded frame around the code, and lamination where the code sits somewhere accessible to the public, checked periodically rather than assumed to be fine because it was fine at launch.
Why would a QR code's destination become dangerous after it was already checked and printed?
Because a destination is not a fixed property of the printed code; it's a URL that continues to exist, and change, in the outside world. A domain that was clean and legitimate when a code launched can later expire, get re-registered by someone else, or have a page on it compromised, all without the printed code itself changing at all. Checking once, at creation, only ever answers the question for that one moment.
What should I tell a customer who reports that a QR code looked suspicious?
Thank them specifically, since a reported code is more useful than an unreported one, then stop directing traffic to that placement until you've personally verified the physical code and its current destination. If you can't immediately confirm it's legitimate, treat the report as credible and escalate through your platform's abuse-reporting channel rather than waiting to investigate fully before acting.