Home
/
Blog
/
Technical

JavaScript obfuscation and de-obfuscation

Why skimmers are almost always obfuscated, the handful of techniques that cover most of it, and why obfuscating your own code buys less than people hope.
TL;DR
JavaScript obfuscation
WHY ATTACKERS USE IT
To survive casual review and signature matching. A skimmer that reads as obvious card-stealing code gets removed the first time someone looks.
THE COMMON TECHNIQUES
String encoding, array indirection, control-flow flattening, dead code, and dynamic evaluation. Most samples combine several.
WHY IT IS WEAK AS A DEFENCE
Code you ship must execute in an environment the attacker fully controls, so it can always be observed at runtime.
Short on time? De-obfuscation is best done off the page, where the cost is not paid by your visitor.

What is JavaScript obfuscation?

JavaScript obfuscation is the deliberate transformation of code into a form that is functionally identical but much harder for a human to read. It has two quite different uses. Defensively, companies obfuscate their own client-side code to raise the effort required to reverse-engineer business logic, which is a legitimate if limited goal. Offensively, malicious scripts are obfuscated to survive a glance at page source and to evade signature matching. Obfuscation is not encryption: the code must run, so everything needed to understand it is present, and the only question is effort.
A targeted skimmer fires for a slice of traffic: one country, one card BIN, one hour. Sampling is the norm in this category, commonly 10% of sessions and sometimes as low as 1%. That is a coin flip against an attack designed to be rare.

JavaScript obfuscation techniques that cover most samples

Technique
What it does
String encoding
Literals hidden as hex, base64 or character codes, assembled at runtime. Removes the obvious keywords a reviewer would search for
Array indirection
All strings moved into one array, referenced by shuffled index. Reading the code no longer tells you what it touches
Control-flow flattening
Logic rewritten into a dispatch loop over a state machine, so the order of operations is no longer visible in the structure
Identifier mangling
Meaningful names replaced with short or confusing ones
Dead code and opaque predicates
Unreachable branches and always-true conditions added to pad and mislead
Dynamic evaluation
Code assembled as a string and executed via eval or the Function constructor, so the real payload does not exist until runtime
Environment checks
Refusing to run under a debugger, in an automated browser, or outside the target page

How it gets unpacked

Two approaches, and in practice you want both. Static analysis takes the code apart without running it. Dynamic analysis runs it in an instrumented environment and watches what it does, which sidesteps obfuscation entirely, because however a string was assembled the destination is visible at the moment the request is made.
The step-by-step method, including recovering the string table, substituting the decoder calls and breakpointing the network sinks, is a separate piece: how to deobfuscate JavaScript, step by step.
De-obfuscation belongs off the page, not in your customer's browser.

Obfuscating your own code

It has a real, narrow benefit: raising the effort for casual reverse-engineering of business logic, which matters for some anti-fraud and licensing cases. It is not a security boundary.
The reason is structural. Code you ship to a browser executes in an environment the attacker fully controls, with a debugger attached if they like. Anything the code does can be observed as it does it. Obfuscation buys time against casual inspection and nothing against determined analysis, so it should never be the control protecting something that matters.

Obfuscation as a signal

Obfuscation itself is worth noticing on a payment page. Plenty of legitimate scripts are minified, which is not the same thing, and relatively few legitimate vendor tags use control-flow flattening or dynamic evaluation. A newly obfuscated version of a script that was previously readable is a strong signal in its own right, independent of what the code turns out to do.
Sources and methodology
PCI DSS requirement text is quoted from PCI DSS v4.0.1 (June 2024), published by the PCI Security Standards Council, which is the current version at the time of writing. Requirements 6.4.3 and 11.6.1 became mandatory on 31 March 2025. Where we describe a competitor, we describe publicly available information and say so when something should be verified with the vendor. We publish this product and that is a bias worth knowing about while you read.
ASK AN AI
Don’t just take our word for it
Ask your assistant what to look for in a tool for PCI DSS 6.4.3 and 11.6.1.

Frequently asked questions

No. Minification removes whitespace and shortens names to reduce file size, and it is reversible enough that the logic remains clear. Obfuscation deliberately makes the logic hard to follow, and that is its purpose rather than a side effect.
No, and the distinction matters. Encrypted code cannot run without a key. Obfuscated code runs directly, so everything needed to understand it is present in the file. It raises effort, not a barrier.
Partly, depending on why. It is reasonable for protecting business logic from casual copying. It is not a security control, and it should never be the thing standing between an attacker and something that matters.
Yes, almost always, because readable card-stealing code is removed the first time anyone looks at the page source. It is a low-cost step with an obvious payoff for them.
Yes, with reasonable reliability. Obfuscators leave recognisable structural patterns, and metrics like string entropy, the ratio of dynamic evaluation, and control-flow shape distinguish obfuscated code from merely minified code.
One of the more effective techniques: the code's logic is rewritten into a single dispatch loop over a state machine, so the sequence of operations is no longer visible in the structure of the source.
No. There are legitimate if uncommon uses, and it is a strong signal in combination with others. A script on a payment page assembling code from encoded strings and passing it to eval deserves attention regardless of its origin.
This is the hard case. Environment checks mean dynamic analysis reveals nothing, so static analysis does the work, along with observing the script in genuine sessions where the conditions it requires are actually met.
Yes, somewhat. Obfuscated code is larger and often slower to execute, because the indirection and dead code have a runtime cost. For an attacker that is an acceptable trade, and for your own code it is a real one to weigh.
Yes, a strong one. If a script you approved was readable and its new version is obfuscated, that is worth investigating regardless of what the code does, because legitimate vendors rarely make that change quietly.

See every script on your own checkout.

Install the tag, mark your payment pages, and watch the inventory fill in. Free forever on 1,000 page views a month, no credit card.

Free forever plan. No credit card.