diff options
| author | Tianren Dong <tianrendong.dtr@gmail.com> | 2026-05-31 14:19:04 -0400 |
|---|---|---|
| committer | Tianren Dong <tianrendong.dtr@gmail.com> | 2026-05-31 14:19:04 -0400 |
| commit | d21ebf7b96c90943ab48ffcd6d5b02c6f7438c04 (patch) | |
| tree | 00a005deb29fd4071c0d67be8e533bab5972d850 /test-suite/challenges | |
| parent | 0fc5b8950601a36dfffdc8f7163bb12fb94f353e (diff) | |
0.15.29: CSP bypass via CDP Runtime.evaluate for evaluate/snapshot/waitFor/initScript
- evaluateInTab/executeInTab now run through CDP Runtime.evaluate instead of
new Function() in MAIN world, so chrome_evaluate/chrome_snapshot work on pages
that block unsafe-eval (github.com, many bank/SaaS apps). Preserves value
markers (undefined/function/symbol/bigint/Error), DOMRect expansion, and the
expression/statement fallback; keeps {ok,value} error envelope.
- page.waitFor polls via service-worker-side CDP evaluation.
- chrome_navigate initScript uses Page.addScriptToEvaluateOnNewDocument.
- Add npm test (test-suite/unit/csp-eval.test.mjs) and in-browser regression
challenge 42 strict-csp-evaluate; update challenge 39 notes + docs/primer.
Diffstat (limited to 'test-suite/challenges')
| -rw-r--r-- | test-suite/challenges/42-strict-csp-evaluate.html | 16 | ||||
| -rw-r--r-- | test-suite/challenges/42-strict-csp-evaluate.js | 21 |
2 files changed, 37 insertions, 0 deletions
diff --git a/test-suite/challenges/42-strict-csp-evaluate.html b/test-suite/challenges/42-strict-csp-evaluate.html new file mode 100644 index 0000000..745c90e --- /dev/null +++ b/test-suite/challenges/42-strict-csp-evaluate.html @@ -0,0 +1,16 @@ +<!doctype html> +<meta charset="utf-8"> +<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; object-src 'none'; base-uri 'none'"> +<title>42 strict CSP evaluate/snapshot</title> +<link rel="stylesheet" href="../_style.css"> +<script src="../_lib.js"></script> +<body> +<main> + <p>Goal: this page ships a strict CSP (<code>script-src 'self'</code>, no <code>unsafe-eval</code>), which blocks <code>eval</code>/<code>new Function</code>. <code>chrome_evaluate</code> and <code>chrome_snapshot</code> must still work because they run through CDP, which is not subject to page CSP.</p> + <p id="hint">A secret token is exposed only at <code>window.__cspToken</code> — it is never written into the DOM. Use <code>chrome_evaluate</code> to read it, type it into the field (snapshot/uid to find the field), then click Verify.</p> + <label for="tokenInput">Token:</label> + <input id="tokenInput" type="text" autocomplete="off" aria-label="csp token"> + <button id="verify" aria-label="verify token">Verify</button> +</main> +<script src="42-strict-csp-evaluate.js"></script> +</body> diff --git a/test-suite/challenges/42-strict-csp-evaluate.js b/test-suite/challenges/42-strict-csp-evaluate.js new file mode 100644 index 0000000..57351c0 --- /dev/null +++ b/test-suite/challenges/42-strict-csp-evaluate.js @@ -0,0 +1,21 @@ +Challenge.init({ + id: "strict-csp-evaluate", + instructions: "under strict CSP: read window.__cspToken via chrome_evaluate, type it into the field, click Verify", +}); + +// Secret available only via JS evaluation. It is intentionally NOT rendered into the DOM and +// is defined non-enumerable, so the only way to obtain it is to evaluate window.__cspToken in +// the page (which proves chrome_evaluate works despite script-src 'self' blocking eval). +const token = "csp-" + Math.random().toString(36).slice(2, 10); +Object.defineProperty(window, "__cspToken", { value: token, enumerable: false, configurable: false, writable: false }); + +document.getElementById("verify").addEventListener("click", (e) => { + const bad = []; + if (!e.isTrusted) bad.push("verify click isTrusted=false (use trusted/CDP input)"); + const val = (document.getElementById("tokenInput").value || "").trim(); + if (val !== token) { + bad.push(`token mismatch: got "${val}" expected "${token}" — chrome_evaluate must read window.__cspToken under strict CSP`); + } + if (bad.length) Challenge.fail(...bad); + else Challenge.pass("strict CSP: chrome_evaluate read the hidden token via CDP and trusted input submitted it"); +}); |
