- Home
- Client-Side Defense
- Attack Script Library
Attack Script Library
The single executable payload source is scripts/lib/csd-scenarios.mjs. Run scenarios through
scripts/csd-traffic.mjs; documentation does not contain a second payload implementation. The
Node.js 22 runner creates an isolated Chrome DevTools Protocol (CDP) context and captures sanitized
Page, Runtime, Network, and Log/console evidence in a versioned JSON receipt.
Prerequisites
Section titled “Prerequisites”- Node.js 22 or newer.
- Chrome or Chromium listening on a loopback remote-debugging endpoint.
- The protected HTTPS page contains the injected
__imp_apg__instrumentation. - The default target is
https://client-side-defense.f5-sales-demo.com.
On macOS, start a dedicated Chrome profile:
open -na "Google Chrome" --args \ --remote-debugging-port=9222 \ --user-data-dir="$TMPDIR/csd-demo-chrome"The runner owns and disposes its isolated context and page. It does not close the external browser.
Canonical CLI
Section titled “Canonical CLI”node scripts/csd-traffic.mjs --listnode scripts/csd-traffic.mjs --scenario <name> [--scenario <name> ...]node scripts/csd-traffic.mjs --allnode scripts/csd-traffic.mjs --target <https-url>node scripts/csd-traffic.mjs --cdp-endpoint <http-or-ws-endpoint>node scripts/csd-traffic.mjs --timeout <duration>node scripts/csd-traffic.mjs --settle <duration>node scripts/csd-traffic.mjs --receipt <path|->node scripts/csd-traffic.mjs --allow-host <exact-hostname>node scripts/csd-traffic.mjs --print-script <scenario>node scripts/csd-traffic.mjs --help--scenario is repeatable. An execution requires exactly one selector form: one or more
--scenario values, or --all. There is no implicit execution selector. --list,
--print-script, and --help are nonexecution modes. Durations accepted by --timeout and
--settle are validated duration values, not platform-detection promises.
List the stable scenarios without connecting to Chrome:
node scripts/csd-traffic.mjs --listRun one scenario and write an atomic receipt:
mkdir -p .artifacts/csdnode scripts/csd-traffic.mjs \ --scenario login-credential-skimmer \ --cdp-endpoint http://127.0.0.1:9222 \ --timeout 30s \ --settle 10s \ --receipt .artifacts/csd/login-credential-skimmer.jsonRun multiple selected scenarios by repeating the selector:
node scripts/csd-traffic.mjs \ --scenario login-credential-skimmer \ --scenario payment-overlay-card-skimmer \ --receipt .artifacts/csd/focused-scenarios.jsonRun the complete manifest with --all:
node scripts/csd-traffic.mjs \ --all \ --receipt .artifacts/csd/all-scenarios.jsonTo stream the receipt, use --receipt -. Stdout then contains only the JSON receipt; all human
logs go to stderr, so piping stdout to jq is safe:
node scripts/csd-traffic.mjs \ --scenario maximum-detection \ --receipt - \ | jq '{schema_version, run_id, requested_scenarios, success, eventual_csd_evidence}'A custom target requires --target and an exact repeatable --allow-host. The target guard rejects
HTTP, IP literals, credentials, wildcards, suffix matches, non-default ports, unauthorized
redirects, and a final document origin outside the exact allowlist.
Manual fallback
Section titled “Manual fallback”Generate the reviewed payload from the canonical module:
node scripts/csd-traffic.mjs \ --print-script maximum-detection \ > .artifacts/csd/maximum-detection.browser.jsReview the generated file, open its documented route in the dedicated profile, and paste it into
DevTools Console. --print-script is the only manual payload source. Manual execution can record
visible Console and Network behavior, but cannot provide the runner’s complete receipt or cleanup
proof.
Scenario evidence matrix
Section titled “Scenario evidence matrix”| Stable scenario | Route | Browser behavior | Immediate receipt evidence | Eventual CSD evidence | Claim boundary |
|---|---|---|---|---|---|
login-credential-skimmer | /#/login | Wait for login inputs, use native setters for synthetic markers, read counts/populated state, discard values, and POST synthetic counters to www.httpbin.org. | Fields found; total/populated counts; native-setter and discard markers; fetch attempt and terminal Network state; completion marker. | Matching field/script observations and/or the run’s reviewed destination. | Browser evidence proves field/network activity, not a fixed-time risk label or field classification. |
registration-harvester | /#/register | Wait for inputs/selects, populate documented synthetic placeholders with native setters, count/read, discard values, and POST counters to jsonplaceholder.typicode.com. | Controls found; counts; native-setter and discard markers; fetch terminal state; completion marker. | Matching form-field/script telemetry and destination if observed. | Do not claim every registration field is classified or visible in bounded time. |
payment-overlay-card-skimmer | /#/login | Count original fields, inject a run-scoped payment overlay containing masked display-only card evidence, POST counters to www.httpbin.org, then remove it. | Original-field count; overlay presence; masked-only fixture assertion; fetch terminal state; overlay cleanup. | Original-field/script observations and destination if observed. | No card data is entered or retained; rendering is not proof of injected-form detection. |
obfuscated-loader | / | Base64 encode and decode the fixed benign jsDelivr Lodash URL, verify equality, then inject one script. | Encoded/decoded equality; element insertion; response, loading-failed, or timed-out terminal outcome; cleanup. | Matching script/domain record if observed. | Obfuscation and the attempted injection are proven; classification is asynchronous. |
multi-cdn-injection | / | Inject the four documented benign CDN candidates. | Exactly four attempts, each retaining its own response, loading-failed, or timed-out outcome; console markers; cleanup. | Only the subset the platform observes. | Never claim all four loaded or were detected; failures remain evidence. |
tag-manager-hijack | / | Inject the fixed Chart.js candidate with run-scoped data-tag-manager metadata, then count/discard form values. | Element and tag metadata; Network terminal state; optional field count; cleanup. | jsDelivr/Chart.js and form observations if present. | The tag metadata simulates semantics; it does not prove platform attribution. |
multi-channel-exfiltration | /#/login | Count/discard login values, then attempt one fetch POST, one image beacon, and one link prefetch with count-only data. | Counts/discard marker; all three channel attempts with terminal or timed-out states; cleanup. | Field/script evidence and destinations actually observed. | Browser attempts are not detection proof; CSD views may emphasize script-source domains. |
high-volume-domain-exfiltration | /#/login | Count/discard fields, inject five documented script candidates, and attempt two benign POSTs. | Exactly seven network attempt records: five script outcomes and two POST outcomes; field counts; cleanup. | Observed subset of scripts, domains, and form fields. | “High volume” means a bounded seven-attempt fixture, not volumetric load or seven guaranteed detections. |
form-overlay | /#/login | Count original fields, cover the existing form with a run-scoped synthetic overlay, verify geometry/presence, then remove it. | Original-field count; overlay DOM and geometry evidence; no overlay input values; cleanup proof. | Original-field/script access if observed. | Dynamic fields are not promised as a standalone CSD signal. |
keylogger-simulation | /#/login | Attach a run-scoped keydown counter, generate synthetic events without retaining keys or target identity, periodically POST aggregate counts, then detach and clear its timer. | Listener attached; aggregate event and periodic flush/POST counts; key-discard marker; request outcomes; listener/timer cleanup. | Form/script access and destination telemetry if observed. | Counts prove event handling only; no keystrokes or fixed-time classification are retained. |
maximum-detection | /#/login | Compose the canonical field-observation, multi-CDN, multi-channel request, and DOM-banner primitives under one run ID. | Child primitives listed; combined console and Network evidence; every candidate outcome; banner cleanup; one run ID. | Observed subset across scripts, domains, fields, and dashboard/user telemetry. | Maximum attempted signal coverage does not guarantee every load, telemetry surface, or classification. |
Reading the receipt
Section titled “Reading the receipt”The receipt records schema/run/start/end/duration, the tool name and Node runtime, requested scenarios,
target origin and routes, the exact allowlist, sanitized CDP endpoint, per-scenario assertions and
markers, sanitized Log/console messages, Network terminal outcomes, protected-document and
instrumentation evidence, cleanup, aggregate success/caveats, and a separate
eventual_csd_evidence field that remains null until a separate correlation operation records it.
When a receipt destination was requested, the runner writes it atomically even after execution or cleanup failure. The primary error remains distinct from cleanup errors. A failed CDN candidate is an observed terminal outcome, not a hidden success and not automatically a harness failure.
Do not commit receipts. Store them beneath .artifacts/ or another ignored private directory.
Explicit post-receipt CSD correlation
Section titled “Explicit post-receipt CSD correlation”The runner performs no platform API calls. Only after the immediate receipt passes, separately use
read-only xcsh_api operations scoped to its start/end window, protected origin, and exact reviewed
hosts recorded by its Network evidence. Record results under the separate eventual-evidence concept
as OBSERVED, NOT_OBSERVED, PENDING, or ERROR. Temporal proximity is correlation, not proof
of causation; no fixed polling interval or complete classification is guaranteed.