What Is Dead Code Injection?
Dead code injection is the practice of adding blocks of code to a program that can never execute — but that the parser and human reader must still process. The injected code is unreachable by design: an if that always evaluates false, a typeof check on a variable that does not exist, a loop whose condition is never true.
Unlike most obfuscation techniques, dead code injection is trivially safe. The runtime never enters the injected blocks, so it cannot break behavior. The cost is purely cosmetic: file size grows, and a reader has to spend time reading code that does nothing.
Why Inject Dead Code?
- Waste the reader's time. Every minute they spend reading a fake block is a minute they are not understanding your real code.
- Hide real logic. Real code becomes harder to spot when surrounded by dozens of fake blocks.
- Bloat reverse-engineering tools. Some automated deobfuscators choke on large amounts of unreachable code.
- Bypass naive filters. Some simple static analyzers flag code by pattern. Dead code introduces noise into those patterns.
- Increase the "cost" of reading. Combined with renaming and string encoding, dead code makes the total effort to understand the code much higher.
The Six Patterns This Tool Uses
1. If-False
if (false) {
var _ghost1 = "nothing";
console.log(_ghost1);
}
The simplest pattern. The condition is literally false, so the block never runs. It still appears in the source, still parses, still gets displayed.
2. Typeof-Check
if (typeof _undefined_variable_x9k === "object") {
var _ghost2 = Math.random() * 1000;
console.log("never runs", _ghost2);
}
typeof on an undeclared variable returns "undefined", which is not "object", so the condition is false. This pattern is harder to spot at a glance because it looks like a real feature-detection check.
3. Try-Throw-Catch
try {
throw new Error("never reaches here");
var _ghost3 = 42;
} catch (_e) {
// swallowed silently
}
The throw is executed, but it happens inside a try block whose catch immediately swallows the error. The code after throw is unreachable. The catch block does nothing observable.
4. Never-Loop
for (var _i = 0; _i < 0; _i++) {
console.log("never loops", _i);
}
The loop condition _i < 0 is false on the first check, so the body never runs. This is very common in real code, which makes it harder to spot.
5. Zero-Return
if (Math.random() < -1) {
var _ghost4 = "impossible";
return _ghost4;
}
Math.random() returns a number between 0 and 1 (inclusive of 0, exclusive of 1). It can never be less than -1. The block never executes. This pattern relies on a mathematical property, so it survives most "deobfuscation by simplification" attempts.
6. Random-Mix
Picks one of the above patterns at random for each block. This produces output where consecutive dead blocks look different, making the injection pattern harder to detect and remove.
How Much Dead Code to Inject?
More is not always better. Each block adds bytes to the file, and too many blocks can:
- Slow down parsing (slightly)
- Trigger warnings from linters and minifiers
- Make the code look obviously machine-generated
A reasonable default is 3-10 blocks. For production code that must stay small, use 2-3. For "maximum confusion" experiments, 15-20.
What Dead Code Injection Cannot Do
- It cannot hide real logic. A determined reader can still find the real code by skipping blocks that clearly do nothing.
- It cannot protect secrets. Strings and values in dead code are still visible.
- It cannot prevent copying. Dead code is just more text to copy.
- It cannot replace other obfuscation. Dead code alone is weak. Combine with renaming, string encoding, and minification for real protection.
Best Practices
- Test after injection. Dead code should never change behavior — but always run the code in a browser to confirm.
- Combine with minification. Run dead code injection, then minify. The minifier will not remove the dead code (it cannot prove unreachability in general), so the output stays bloated.
- Use "Random-Mix". If you inject 5 blocks, having them all look the same is a giveaway. Randomize.
- Do not overdo it. 20 identical dead blocks look suspicious. 5 varied blocks look natural.