- Project
- BookStack
- Affected
- v26.09.1 and earlier
- Fixed in
- v26.09.2
- Severity
- Low (Xora rating)
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:N/I:N/A:L - Weakness
- CWE-352
- Reported
- Oct 9, 2026
- Fixed
- Oct 20, 2026
- Maintainer
- Release announcement ↗
Summary
BookStack applies CSRF protection across the application, with one exception: the saml2/* route group. Because of that exemption, POST /saml2/logout accepted a request with no CSRF token. The session cookie is SameSite=Lax, so a page on a host that shares BookStack’s registrable domain could log a signed-in user out.
The impact is a forced logout and nothing more. An ordinary cross-site page cannot trigger it, and it gives an attacker no access to the account or its data.
Root cause
// app/Http/Middleware/VerifyCsrfToken.php (v26.09.1)
protected $except = [
'saml2/*',
];BookStack added application-wide CSRF verification in release 21.11 (CVE-2021-3944). saml2/* was the only route group carved out of it, so the user-initiated logout route accepted a tokenless POST. The session cookie is set with same_site => 'lax' (app/Config/session.php). Lax is scoped to the registrable domain: the browser withholds the cookie on a genuinely cross-site POST but sends it on one from a sibling subdomain.
Preconditions
- An attacker-controlled host on the same registrable domain as the BookStack instance: a subdomain they control, a dangling DNS record, or a user-content host on that domain.
- A signed-in user who opens a page on that host.
The first precondition is what keeps this rated Low, and it is what the AC:H in the CVSS vector records.
Reproduction
With BookStack at docs.example.com, serve this page from other.example.com and open it as a signed-in user:
<form action="https://docs.example.com/saml2/logout" method="POST"></form>
<script>document.forms[0].submit()</script>In a real browser, the request from the same-site host ended the session. The identical request from a cross-site host did not, because the browser withheld the cookie. That contrast is the evidence.
The fix
We suggested narrowing the exemption to the identity-provider callbacks that cannot carry a CSRF token, or checking Origin and Referer on the exempt routes. BookStack went further: in v26.09.2 the exemption list is empty, so no route skips CSRF verification. We confirmed that change in the source at the v26.09.2 tag. We have not retested the fixed release in a browser.
What we do not claim
- No session fixation, account takeover, data disclosure or privilege change.
- Not reachable from an arbitrary cross-site page.
- We did not measure how often real deployments meet the same-site precondition, so we make no claim about how many instances were exposed.
What the engine got wrong
The Xora engine found the missing CSRF check, but its first record said any website could log a user out. That was wrong. The session cookie is SameSite=Lax, so the browser does not send it with a cross-site POST. In a real browser the cross-site attack failed and only the same-site variant worked, so we reported the narrower claim and rated it Low.
The engine was right that the protection was missing and wrong about who could reach it, and reachability is what sets the severity. We recorded this as a check for the engine to learn: when a finding depends on the browser sending a session cookie, read the cookie’s SameSite setting from the source, then ask whether the attacker’s page is cross-site or only on a sibling subdomain.
Timeline
- Oct 7, 2026: Confirmed against v26.09.1.
- Oct 9, 2026: Reported privately to the BookStack maintainer by email.
- Oct 20, 2026: BookStack released v26.09.2 with the fix, crediting Xora.
Found by the Xora engine, confirmed by a person, and reported under our coordinated disclosure policy. Questions or corrections: security@getxora.ai.