Carry the CSRF token on fetch requests and put mutations behind POST
Unraid already enforces CSRF on every POST via auto_prepend, but its injector is jQuery-only — the plugin's native fetch() calls carried no token and were being terminated before the endpoint ran, silently, because csrf_terminate exits with an empty body that r.json() swallows.
This commit is contained in:
@@ -46,14 +46,14 @@
|
||||
// Cache-Control: no-store, no-cache. A cached provisioning response would report an old
|
||||
// key preview after a genuine renewal — the one moment the preview matters.
|
||||
//
|
||||
// Known gap: this is a state-changing action served over GET.
|
||||
// Both callers (pages/setup.php, pages/partnership.php) fetch it, and POST bodies are
|
||||
// unreliable on this nginx/PHP setup. It is guarded by the Unraid WebGUI session rather
|
||||
// than by method or token. Documented rather than silently accepted — see the CSRF note
|
||||
// in README-unraid.md.
|
||||
// POST only, which is what places it behind Unraid's CSRF guard.
|
||||
// The platform prepend validates the token on every POST and inspects no GET at all, so
|
||||
// a state-changing action reachable by GET is a state-changing action with no CSRF
|
||||
// protection. This was previously a GET; the callers now POST and the token travels as
|
||||
// an X-CSRF-Token header set by the shim in Varaverk.page. See README-unraid.md.
|
||||
//
|
||||
// REQUEST
|
||||
// GET, no parameters (the target host is the local host, by construction)
|
||||
// POST, no parameters (the target host is the local host, by construction)
|
||||
//
|
||||
// RESPONSE
|
||||
// {"ok":true,"key_preview":"abcd1234...wxyz"} or "registered" when the key is not readable
|
||||
@@ -67,6 +67,14 @@ header('Content-Type: application/json');
|
||||
header('Cache-Control: no-store, no-cache');
|
||||
require_once dirname(__DIR__) . '/include/config.php';
|
||||
|
||||
// POST is what puts this behind Unraid's CSRF guard — the platform prepend validates every
|
||||
// POST and ignores every GET, so a state-changing action must not be reachable by GET.
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
http_response_code(405);
|
||||
echo json_encode(['ok' => false, 'error' => 'POST only']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$host = vv_detect_host();
|
||||
if (!preg_match('/^host\d+$/', $host)) {
|
||||
echo json_encode(['ok' => false, 'error' => 'Cannot detect local host']);
|
||||
|
||||
Reference in New Issue
Block a user