Server: Improve browser detection

(cherry picked from commit 2e19017d0e)
This commit is contained in:
Abe Jellinek 2025-05-12 12:52:37 -04:00 • committed by Dan Stillman
parent 094eb92f37
commit 8579339cde

View file

@ -399,33 +399,21 @@ Zotero.Server.RequestHandler.prototype._processEndpoint = async function (method
return;
}
// Reject browser-based requests that don't require a CORS preflight request [1] if they
// don't come from the connector or include Zotero-Allowed-Request
//
// [1] https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Simple_requests
var whitelistedEndpoints = [
'/connector/ping'
];
var simpleRequestContentTypes = [
'application/x-www-form-urlencoded',
'multipart/form-data',
'text/plain'
];
var isBrowser = (this.headers['user-agent'] && this.headers['user-agent'].startsWith('Mozilla/'))
// Origin isn't sent via fetch() for HEAD/GET, but for crazy UA strings, protecting
// POST requests is better than nothing
|| 'origin' in this.headers;
if (isBrowser
// Allow endpoints to explicitly opt into allowing browser requests
// if they really want to
&& !endpoint.allowRequestsFromUnsafeWebContent
&& !this.headers['x-zotero-connector-api-version']
&& !this.headers['zotero-allowed-request']
&& (!endpoint.supportedDataTypes
|| endpoint.supportedDataTypes == '*'
|| endpoint.supportedDataTypes.some(type => simpleRequestContentTypes.includes(type)))
&& !whitelistedEndpoints.includes(this.pathname)
// Ignore test endpoints
// Allow browser requests to test endpoints
&& !this.pathname.startsWith('/test/')
// Ignore content types that trigger preflight requests
&& !(this.contentType && !simpleRequestContentTypes.includes(this.contentType))) {
// Allow browser requests to /connector/ping as long as they come
// from navigation, not XHR/fetch()/resource loading
&& !(this.pathname === '/connector/ping' && this.headers['sec-fetch-mode'] === 'navigate')) {
this._requestFinished(this._generateResponse(403, "text/plain", "Request not allowed\n"));
return;
}