proxy: add JavaScript cookie challenge for dumb bots#2016
Conversation
Production observations show many unsophisticated bots stressing the dashboard with random requests. Add a lightweight JavaScript and cookie hurdle before serving frontend or API requests from Safari, Android, and Chromium-style user agents. Cross-check the claimed browser platform/vendor, reject WebDriver, require the exact verification cookie value, and safely return browsers to the original URI. Preserve local HTTP support while marking the cookie Secure on browser-facing HTTPS connections. Legitimate programmatic API clients using their normal python-requests, Wget, or curl user agents bypass the browser gate. Clients that claim to be browsers must complete the same challenge before reaching /api. This is intentionally a speed bump for dumb bots rather than an authentication boundary; rate limiting remains the appropriate additional protection for determined direct API abuse. Signed-off-by: Denys Fedoryshchenko <denys.f@collabora.com>
| var marker = "?return="; | ||
| var target = location.search.slice(marker.length); | ||
| if (location.search.slice(0, marker.length) !== marker || | ||
| target.charAt(0) !== "/" || target.charAt(1) === "/" || | ||
| target.charAt(1) === "\\") { | ||
| target = "/"; | ||
| } | ||
| location.replace(target); |
There was a problem hiding this comment.
Gemini suggests to replace string parsing for ?return= in JavaScript with native URL() handling to guarantee absolute path safety.
| var marker = "?return="; | |
| var target = location.search.slice(marker.length); | |
| if (location.search.slice(0, marker.length) !== marker || | |
| target.charAt(0) !== "/" || target.charAt(1) === "/" || | |
| target.charAt(1) === "\\") { | |
| target = "/"; | |
| } | |
| location.replace(target); | |
| var params = new URLSearchParams(location.search); | |
| var target = params.get("return") || "/"; | |
| // Enforce a strict relative path to prevent open redirects (e.g., //evil.com, /\evil.com) | |
| if (!target.startsWith("/") || target.startsWith("//") || target.startsWith("/\\")) { | |
| target = "/"; | |
| } | |
| location.replace(target); |
There was a problem hiding this comment.
In the solution proposed by Gemini, we are possibly dropping extra query parameters other than return.
I think its fine to check via startsWith (cleaner), but using URLSearchParams might bring problematic. Unless we only have return as a single query parameter.
| var claimsSafari = /Safari/i.test(ua) && !claimsChromium; | ||
| var platformLooksValid = false; | ||
|
|
||
| if (claimsAndroid) { |
There was a problem hiding this comment.
Cant we endup loosing some legitimate accesses here?
Mostly, people who use hardened browsers or less conventional ones?
There was a problem hiding this comment.
Only those who dont support cookie at all (which are integral part of browsers, even console based), but i am afraid it will happen with Anubis as well.
|
After discussion in chat, i think Anubis is preferable as it is more tested solution. |
Production observations show many unsophisticated bots stressing the dashboard with random requests. Add a lightweight JavaScript and cookie hurdle before serving frontend or API requests from Safari, Android, and Chromium-style user agents.
Cross-check the claimed browser platform/vendor, reject WebDriver, require the exact verification cookie value, and safely return browsers to the original URI. Preserve local HTTP support while marking the cookie Secure on browser-facing HTTPS connections.
Legitimate programmatic API clients using their normal python-requests, Wget, or curl user agents bypass the browser gate. Clients that claim to be browsers must complete the same challenge before reaching /api.
This is intentionally a speed bump for dumb bots rather than an authentication boundary