aboutsummaryrefslogtreecommitdiff
path: root/test-suite/challenges
diff options
context:
space:
mode:
Diffstat (limited to 'test-suite/challenges')
-rw-r--r--test-suite/challenges/42-strict-csp-evaluate.html16
-rw-r--r--test-suite/challenges/42-strict-csp-evaluate.js21
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");
+});