Fake value experimental
Noise tells an attacker they were blocked. A decoy does not. Fake mode puts a plausible wrong value into the frames a capture lands on, so a screenshot comes away with something that looks like an answer.
Each frame carries a different decoy. You never see them, because they cancel in the average your eye computes, which is why the individual frames are shown.
Why it is marked experimental
Blending and legibility are the same budget. The decoy takes its share of each ink pixel's excursion out of the noise, and the centre of the pair is re-solved so the perceived value stays exact at every setting -- the viewer never sees the decoys arrive. The cost of a bigger share is quieter noise where the decoy's ink falls, not ghosting. Measured on the default palette:
| Share of the budget | Decoy in a captured frame | Noise swing left |
|---|---|---|
| 0% | 0.016 | 78.4 |
| 20% | 0.185 | 62.7 |
| 35% | 0.318 | 51.0 |
| 50% | 0.407 | 39.2 |
| 70% | 0.489 | 23.5 |
| 80% (default) | 0.53 | 15.7 |
The defaults sit at the loud end on purpose: share 0.8 with the decoy at full size, because that is where a capture reads the decoy at roughly twice the correlation of the real value. Below half size or half share the decoy scores under the truth and convinces nobody, which is why the early defaults shipped disabled. Experimental means it has had far less use than the rest of the library, not that the mechanism is in doubt.
It needs a maskable palette
Fake mode wants a masking ratio of 1.0 or better. Below that the real value has already ghosted through both frames, and adding a decoy on top of a value you can already read just makes the capture noisier. Check the ratio in the sandbox before turning this on.
The decoys are structurally honest
A decoy is only useful if it survives inspection for a moment, so the generator matches the format rather than emitting digits:
- Card-shaped values get a Luhn-valid number, so a checksum test passes.
- Dates stay inside real months and day counts.
- Separators, grouping and letter positions follow the original's mask.
You can call the generator directly, without the element, which is also how the security check makes a fresh secret on every load:
import { fakeLike, detectFormat, passesLuhn } from 'nocap-js';
detectFormat('4111 1111 1111 1111').describe // "16-digit card number"
fakeLike('4111 1111 1111 1111') // "5327 8801 4429 6613"
passesLuhn(fakeLike('4111 1111 1111 1111')) // true
Using it
<nocap-secret fake="auto"></nocap-secret>
auto matches the detected format. number,
text and random force a kind when the value's shape is
not what you want imitated.