Four violation modes configurable via onViolation in WebShield.init():
| Mode | What happens | Config value |
|---|---|---|
degrade |
Features silently break — app partially works but core functionality fails | 'degrade' |
shutdown |
document.body.innerHTML = '', all timers and intervals killed |
'shutdown' |
redirect |
location.href = config.redirectUrl |
'redirect' |
honeypot |
App appears to work normally, all actions logged to reportUrl |
'honeypot' |
| Custom | Callback function called with violation details | fn(detail) |
Default: 'degrade'
Threshold: config.violationThreshold (default: 2) — number of module reports before the mode triggers. Prevents false positives from a single noisy detector.
shutdown is the instinct — nuke the page, done. But it immediately signals to the attacker that protection exists and triggered. They know exactly what happened and can focus their bypass attempts.
degrade is psychologically stronger. The attacker copies the app, it appears to load, but core features silently fail. No error message. No indication something is wrong. They spend hours debugging their copy, assuming they broke something in the extraction process. The confusion is the protection.
Real-world outcome: a determined attacker eventually figures it out regardless. But degrade wastes their time and creates doubt about whether their copy will ever work. Most walk away.
For cases where you want intelligence rather than deterrence. The app “works” on the wrong domain, but every action — lesson completed, answer submitted, content viewed — is logged to your endpoint. You learn who copied you, how they’re using it, and whether it’s worth a DMCA notice.
Only useful if you have a reportUrl endpoint to receive the logs and someone to review them.
Setting violationThreshold: 1 means a single false positive triggers the mode. DevTools detectors in particular have false positive rates worth accounting for — a user with a slow machine might trip the timing-based anti-debug check legitimately.
violationThreshold: 2 (default) requires two independent module reports before action. Reduces false positives significantly without meaningfully weakening protection — a real attacker will trigger multiple modules.
For maximum aggression: set to 1 and use shutdown. For minimum friction to legitimate users: set to 3 or 4 and use degrade.
The violation handler in core/violation.js:
// Pseudocode
let count = 0
function report(moduleName, severity, detail) {
count++
logToReporter({ moduleName, severity, detail, count })
if (count >= config.violationThreshold) {
trigger(config.onViolation)
}
}
function trigger(mode) {
if (mode === 'shutdown') { document.body.innerHTML = ''; killTimers() }
if (mode === 'degrade') { enableDegradeMode() } // flags read by app
if (mode === 'redirect') { location.href = config.redirectUrl }
if (mode === 'honeypot') { enableHoneypotMode() }
if (typeof mode === 'function') { mode({ count, reports }) }
}
degrade mode sets a global flag that app-level checks can read. The library does not know which features to break — the app integrates by checking WebShield.isDegraded() at feature boundaries.