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:
Gmer4Lfe
2026-08-02 10:28:53 -04:00
parent 987313e7dc
commit c34224effa
16 changed files with 198 additions and 67 deletions
+15 -4
View File
@@ -82,13 +82,17 @@
// The SCP target is the local conf path, composed here — no part of the request names a
// destination file.
//
// Accepted: this endpoint writes credentials and runs setup scripts as root.
// It is the setup wizard; that is its function. It is guarded by the Unraid WebGUI
// session; see the CSRF note in README-unraid.md.
// Every action that changes anything is POST only, which is what places them behind
// Unraid's CSRF guard.
// The platform prepend validates the token on every POST and inspects no GET at all.
// Only `detect` remains GET-reachable, and it is a pure read. This endpoint writes
// credentials and runs setup scripts as root — that is its function, and it is why the
// method boundary is the one that matters here.
//
// REQUEST
// GET ?action=detect hostname, Unraid version, boot transport, suggested mode
// GET|POST action=ssh_generate generate the local keypair, return the public key
// POST action=ssh_generate generate the local keypair, return the public key
// (POST, so Unraid's CSRF guard applies)
// POST action=populate run conf_populate.sh --no-push
// POST action=pull partner: SCP master.conf from HOST1, create host conf
// [my_slot] [my_hostname] [host1_hostname]
@@ -149,6 +153,13 @@ if ($action === 'detect') {
// ── GET/POST: generate local SSH keypair ──────────────────────────────────────────────────────
if ($action === 'ssh_generate') {
// POST only. This generates a keypair, and Unraid's CSRF prepend validates POSTs while
// ignoring GETs entirely — over GET it would run with no token check at all.
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
echo json_encode(['ok' => false, 'error' => 'POST only']);
exit;
}
$script = SCRIPTS_DIR . '/Partnership/ssh_setup.sh';
if (!file_exists($script)) {
echo json_encode(['ok' => false, 'error' => 'ssh_setup.sh not found']);