...` sink; the // htmlspecialchars(json_encode(...), ENT_QUOTES) pattern used for data-* // attributes is already safe and does not need this. function json_script($value): string { return json_encode( $value, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_UNESCAPED_UNICODE ); } // require_csrf rotates the token after every successful check (Finding // H1). A leaked token (via DOM dump / error log / browser cache) is now // usable for at most one mutation. Forms re-render with csrf_token() so // they pick up the new value automatically; AJAX callers should read // the X-CSRF-Token response header and update their in-memory copy. function require_csrf(): void { $sent = $_POST['csrf'] ?? $_SERVER['HTTP_X_CSRF_TOKEN'] ?? ''; if (!\is_string($sent) || !hash_equals($_SESSION['csrf'], $sent)) { http_response_code(403); exit('CSRF check failed'); } $_SESSION['csrf'] = bin2hex(random_bytes(32)); header('X-CSRF-Token: ' . $_SESSION['csrf']); } Sign in — Yggdrasil

Yggdrasil Admin

Sign in to manage customers, sources, and the AI pipeline.