Harden API and session security: enforce CSRF on cookie-auth /api/v1 writes, exempt bot bearer tokens, and set SameSite=Lax + conditional Secure on auth/CSRF/ip-session cookies

This commit is contained in:
Speng Reb 2026-05-21 16:25:34 +02:00
parent 6eeee342d7
commit 36da4bdff1
3 changed files with 20 additions and 12 deletions

View file

@ -13,10 +13,13 @@ exports.init = function csrfInit (domain) {
var secret = req.signedCookies._csrf; var secret = req.signedCookies._csrf;
if (!secret) { if (!secret) {
secret = tokens.secretSync(); secret = tokens.secretSync();
const secure = req.realProtocol === 'https' || req.secure === true;
res.cookie("_csrf", secret, { res.cookie("_csrf", secret, {
domain: domain, domain: domain,
signed: true, signed: true,
httpOnly: true httpOnly: true,
sameSite: 'lax',
secure
}); });
} }

View file

@ -38,10 +38,13 @@ export function ipSessionCookieMiddleware(req, res, next) {
} }
if (!hasSession) { if (!hasSession) {
const secure = req.realProtocol === 'https' || req.secure === true;
res.cookie('ip-session', createIPSessionCookie(req.realIP, firstSeen), { res.cookie('ip-session', createIPSessionCookie(req.realIP, firstSeen), {
signed: true, signed: true,
httpOnly: true, httpOnly: true,
expires: NO_EXPIRATION expires: NO_EXPIRATION,
sameSite: 'lax',
secure
}); });
} }

View file

@ -241,21 +241,23 @@ module.exports = {
}, },
setAuthCookie: function setAuthCookie(req, res, expiration, auth) { setAuthCookie: function setAuthCookie(req, res, expiration, auth) {
const secure = req.realProtocol === 'https' || req.secure === true;
const baseCookieOptions = {
expires: expiration,
httpOnly: true,
signed: true,
sameSite: 'lax',
secure
};
if (req.hostname.indexOf(Config.get("http.root-domain")) >= 0) { if (req.hostname.indexOf(Config.get("http.root-domain")) >= 0) {
// Prevent non-root cookie from screwing things up // Prevent non-root cookie from screwing things up
res.clearCookie("auth"); res.clearCookie("auth");
res.cookie("auth", auth, { res.cookie("auth", auth, Object.assign({}, baseCookieOptions, {
domain: Config.get("http.root-domain-dotted"), domain: Config.get("http.root-domain-dotted"),
expires: expiration, }));
httpOnly: true,
signed: true
});
} else { } else {
res.cookie("auth", auth, { res.cookie("auth", auth, baseCookieOptions);
expires: expiration,
httpOnly: true,
signed: true
});
} }
} }
}; };