A QR code is just data in a visual form, usually a URL, and a phone camera turns it into something the app acts on. That convenience is exactly why QR codes have become an attack vector: an attacker can print a code, or stick one over a legitimate one, that encodes a phishing link, a deep link, or a payment request, and a user scanning it has no way to read the raw content with their eyes. If your app scans QR codes and acts on them automatically, the attacker is effectively handing your app input of their choosing. The term for QR phishing is quishing. Here is what malicious QR codes are and how to handle scanned codes safely.
Short answer
A malicious QR code is one crafted or substituted by an attacker to encode harmful content, most often a phishing URL but also deep links, payment requests, or other data, which a user cannot read by eye before scanning. Per security guidance on QR phishing, often called quishing, the risk is that an app scanning a QR code treats the decoded content as trusted and acts on it, opening a URL, triggering an action, or starting a payment, when it is untrusted input an attacker controls. The fix is to treat decoded QR content as untrusted: validate it, show the user the decoded destination and require confirmation before acting rather than auto-executing, allowlist destinations for sensitive actions, and verify payment or authentication flows server-side. A scan is not a reason to trust what was scanned.
What you should know
- A QR code is data, usually a URL: the user cannot read it by eye.
- Attackers craft or substitute codes: a sticker over a real one, a phishing link.
- Decoded content is untrusted input: an attacker controls what you scan.
- Do not auto-act on a scan: show the destination and confirm.
- Verify sensitive flows server-side: payments and authentication.
What is a malicious QR code?
It is a QR code whose encoded content is chosen by an attacker to cause harm. Because a QR code is a machine-readable blob, a person scanning it cannot see what it contains until the app decodes it, which is what makes it effective: an attacker can encode a link to a phishing site that imitates a legitimate one, a deep link meant to trigger an action, a request to send a payment, or data designed to be misused, and present it as an ordinary code. A common real-world version is substitution, placing a malicious code sticker over a genuine one on a poster, a parking meter, a restaurant table, so users scan the attacker's code believing it is the legitimate one. This is what quishing, QR phishing, refers to. From your app's perspective, the decoded content is input that an attacker may fully control, no different from a malicious URL or a crafted message, so the danger is not the QR format itself but acting on its content as if scanning vouched for it.
What are the risks when an app scans a QR code?
They follow from acting on attacker-chosen content. The table lists them.
| Risk | What happens |
|---|---|
| Phishing URL | A scanned link leads to a credential-stealing site |
| Auto-opened destination | The app navigates without the user seeing where |
| Malicious deep link | A scanned link triggers an in-app action |
| Payment or transfer request | A code initiates a payment to an attacker |
| Injected content | Decoded data passed unsanitized into a query or command |
The headline risk is phishing: a scanned QR encodes a link to a convincing fake, and if the app or browser opens it without the user clearly seeing the destination, they may enter credentials on the attacker's site. Auto-opening makes this worse, because the user never gets to judge the URL. A malicious deep link in a QR can trigger an in-app action, which is dangerous if your app performs sensitive actions from deep links, and a payment or transfer request encoded in a code can initiate a transaction to an attacker if confirmed too readily. And if your app takes decoded QR data and passes it into a query, command, or other sink without sanitizing, it becomes an injection vector. Every one of these comes back to treating the scanned content as trusted when it is attacker-controlled input.
How do you handle scanned QR codes safely?
Treat the decoded content as untrusted, and put the user and the server in the loop for anything consequential. When your app scans a QR code, validate the decoded content rather than acting on it directly, and show the user what was decoded, especially the full destination of a URL, so they can judge it before anything happens, instead of auto-opening or auto-executing. For sensitive actions, validate the destination against an allowlist of your own domains or expected formats, and reject content that does not match, rather than following an arbitrary URL or deep link from a code. Require explicit user confirmation before consequential actions like opening an external link, performing an in-app action, or initiating a payment, and for payments and authentication, verify the request server-side rather than trusting that a scanned code is legitimate. Sanitize decoded data before using it in any query or command, treating it as the untrusted input it is. The principle is that scanning a code only tells you what it contains, not that the content is safe, so validate it, surface the destination to the user, confirm consequential actions, and enforce sensitive ones on the server.
What to watch out for
The first trap is auto-opening or auto-executing a scanned QR's content, so a substituted phishing code sends the user onward without their seeing where; show the destination and require confirmation. The second is performing a sensitive in-app action or payment straight from a scanned code; validate against an allowlist and verify server-side. The third is passing decoded QR data unsanitized into a query or command. QR handling is code you write, so a pre-submission scan such as PTKD.com (https://ptkd.com), which reads the binary against OWASP MASVS, assesses your app's input handling and how it processes URLs and deep links, the surfaces scanned content flows into, while validating and confirming scanned content is yours to implement.
What to take away
- A malicious QR code encodes attacker-chosen content, often a phishing URL, that a user cannot read by eye, and attackers substitute codes over legitimate ones, which is called quishing.
- The risks come from acting on the decoded content as trusted: phishing, auto-opened destinations, malicious deep links, payment requests, and injection.
- Treat decoded QR content as untrusted input: validate it, show the destination and require confirmation before acting, allowlist for sensitive actions, sanitize before use, and verify payments and authentication server-side.
- Use a pre-submission scan such as PTKD.com to assess your app's input and URL handling, and validate scanned content in your code.



