Date: 2026-05-29
| Attacker | Skill | Goal |
|---|---|---|
| Casual | None | View source → copy |
| Developer | Medium | DevTools → extract + reuse |
| Determined | High | Deobfuscate → full clone |
| Automated | Medium | Headless scrape + clone |
Target: Tier 1-2 impossible, Tier 3 multi-week project, Tier 4 structurally broken.
<script src="webshield.min.js"></script>
<script>
WebShield.init({
domains: ['techiediaries.com', 'localhost'],
protections: {
domainLock: true,
devtools: true,
antiDebug: true,
antiHeadless: true,
antiIframe: true,
envAnomaly: true,
timingAnalysis: true,
contentEncryption: true,
nonExtractableKeys: true,
blobServing: true,
shadowEncapsulation: true,
opfsBinding: true,
proxyShield: true,
swGatekeeper: true,
domTamper: true,
decoyTraps: true,
trustedTypes: true,
reporting: true,
},
onViolation: 'degrade',
reportUrl: 'https://your-worker.dev/violations',
redirectUrl: 'https://techiediaries.com',
violationThreshold: 2,
debug: false,
})
</script>
import {
useDomainLock,
useDevtools,
useAntiDebug,
useAntiHeadless,
useContentEncryption,
useDecoyTraps,
useProxyShield,
} from 'webshield'
// Vanilla JS — each returns a cleanup fn
const stopDomainLock = useDomainLock({ domains: ['techiediaries.com'] })
const stopDevtools = useDevtools({ threshold: 2, onDetect: 'degrade' })
const stopAntiDebug = useAntiDebug()
// React
function App() {
useDomainLock({ domains: ['techiediaries.com'] })
useDevtools()
useAntiDebug()
return <div>...</div>
}
// Vue composable
export function useShield() {
onMounted(() => {
const stops = [
useDomainLock({ domains: ['techiediaries.com'] }),
useDevtools(),
]
onUnmounted(() => stops.forEach(s => s()))
})
}
Each use* function:
() => void cleanup/stop function| API | How |
|---|---|
SubtleCrypto (HKDF + AES-GCM) |
Domain binding, content encryption, integrity hashing |
IndexedDB + non-extractable CryptoKey |
Key exists in browser, JS cannot read it back |
Origin Private File System (OPFS) |
Per-origin private install token, can’t be copied cross-origin |
SharedArrayBuffer + Atomics |
High-res timing for debugger detection (bypasses throttled performance.now) |
Web Workers |
Isolated check threads, hard to tamper from main thread |
Closed ShadowDOM |
querySelector-proof content rendering |
Proxy + Reflect |
Wrap app objects — unexpected access = violation |
FinalizationRegistry |
Detect if shield objects are being GC’d (tamper signal) |
Trusted Types |
Block injected scripts via CSP policy |
MutationObserver |
Watch <head>/ |
ResizeObserver |
DevTools dock changes window dimensions |
Reporting API |
Silent violation telemetry |
CSS Houdini Paint Worklet |
Critical render logic in worklet — opaque to JS DevTools panel |
WebGL fingerprint |
Environment anomaly scoring |
Canvas fingerprint |
Hardware-bound fingerprint component |
AudioContext fingerprint |
Third fingerprint vector |
Blob URLs (revokable) |
Decrypted content served as temp blob, revoked after render |
navigator.getInstalledRelatedApps() |
Detect PWA vs raw copy |
Atomics.waitAsync |
Precision timing without blocking |
domain-lock HKDF domain binding — key derivation fails on wrong domain
devtools-detect resize delta + console timing + toString trap + element getter
anti-debug SharedArrayBuffer timing + debugger loop + stack trace origin check
anti-headless webdriver flag + plugin count + rAF cadence + connection type
anti-iframe top !== self + Permissions-Policy + frame-busting
env-anomaly hardwareConcurrency + deviceMemory + screen.isExtended + VM heuristics
timing-analysis detect automation via requestIdleCallback starvation pattern
content-encryption AES-GCM encrypted JSON, key from domain + install token
non-extractable-keys SubtleCrypto non-extractable key in IDB — usable, never readable
blob-serving decrypt → blob URL → render → revoke
shadow-encapsulation render content in closed ShadowDOM
opfs-binding install timestamp in OPFS as key derivation component
proxy-shield Proxy wraps all app objects, unexpected access = violation
dom-tamper MutationObserver on <head>/<script> + FinalizationRegistry on shield objects
decoy-traps fake window.__lessons, window.__config via Proxy get traps
trusted-types Trusted Types policy blocks injected scripts
sw-gatekeeper Service Worker validates integrity headers on every asset request
worker-isolation core logic in Web Worker, main thread is render-only shell
houdini-core critical render logic in CSS Paint Worklet (experimental, Chrome)
reporting Reporting API + custom endpoint, silent violation telemetry
self-destruct shutdown | degrade | redirect | honeypot | custom fn
| Mode | Effect | Best for |
|---|---|---|
shutdown |
Body cleared, all timers killed | Maximum aggression |
degrade |
Features silently break, looks like bugs | Most psychologically effective |
redirect |
Push to official site | User-friendly |
honeypot |
App “works” but logs everything | Intel gathering |
fn |
Your callback | Full control |
degrade is the strongest — the copier debugs their broken clone for days.
webshield/
src/
core/
index.js # init(), use* factory, config validator, module runner
registry.js # module registration + dependency graph
reporter.js # Reporting API + custom endpoint
violation.js # threshold counter + response modes
modules/
detection/
domain-lock.js
devtools-detect.js
anti-debug.js
anti-headless.js
anti-iframe.js
env-anomaly.js
timing-analysis.js
content/
content-encryption.js
non-extractable-keys.js
blob-serving.js
shadow-encapsulation.js
opfs-binding.js
active/
proxy-shield.js
dom-tamper.js
decoy-traps.js
trusted-types.js
sw-gatekeeper.js
worker-isolation.js
houdini-core.js
workers/
shield-worker.js # Web Worker for isolated checks
sw-template.js # Service Worker template
cli/
encrypt.js # encrypt content files at build time
hash.js # generate integrity hashes
bundle.js # generate configured single-file output
tests/
unit/
core/
modules/ # one file per module
integration/
combinations/ # protection combo tests
attacker-sims/ # simulate attack scenarios
e2e/
playwright/ # headless, devtools, wrong domain, injection
decisions/
feasibility-webshield.md
use-api-design.md # to be written in Phase 1
responses/ # this file + future session responses
docs/
tutorial/ # series source files
dist/
webshield.min.js
webshield.esm.js
webshield.cjs.js
TODO.md
KNOWLEDGE.md
memory.md
package.json
Every module exports:
export default {
name: 'domain-lock', // unique slug
deps: [], // other module names required before this
supported: () => Boolean, // feature detection — returns false if API unavailable
start: (config, report) => fn, // activates protection, returns stop()
// start() returns cleanup function: () => void
}
Core calls supported() first — if false, skips gracefully. Never crashes.
| Phase | Modules | Exit criteria |
|---|---|---|
| 1 | Core engine, registry, violation handler, reporter, use* factory | 24 unit, 8 integration |
| 2 | domain-lock, anti-iframe, env-anomaly | +36 unit, +12 integration, 2 e2e |
| 3 | devtools-detect, anti-debug, timing-analysis | +42 unit, +15 integration, 3 e2e |
| 4 | anti-headless, dom-tamper, decoy-traps | +36 unit, +12 integration, 3 e2e |
| 5 | content-encryption, non-extractable-keys, opfs-binding, CLI | +48 unit, +16 integration, 2 e2e |
| 6 | proxy-shield, trusted-types, blob-serving, shadow-encapsulation | +40 unit, +14 integration, 3 e2e |
| 7 | sw-gatekeeper, worker-isolation | +30 unit, +10 integration, 2 e2e |
| 8 | houdini-core, reporting, bundle, TypeScript types, publish | full suite green |
Part 1: The Lie of Client-Side Security (and What's Actually True)
Part 2: Cryptographic Domain Binding with SubtleCrypto
Part 3: Detecting DevTools, Debuggers, and Headless Browsers
Part 4: Using Proxy and FinalizationRegistry as Tamper Sensors
Part 5: The Origin Private File System as a Security Primitive
Part 6: Closed ShadowDOM and Blob URLs for Content Protection
Part 7: Service Workers as Security Gatekeepers
Part 8: Building a Modular Flag-Based Protection Library
Part 9: Automated Attacker Simulation with Playwright
Each part: 1500-2500 words, working code samples, linked to webshield repo. Primary SEO target: “client side protection 2026”, “javascript domain lock”.