From 8579339cdeb923cab54199c40c7e52053fa558fe Mon Sep 17 00:00:00 2001 From: Abe Jellinek Date: Mon, 12 May 2025 12:52:37 -0400 Subject: [PATCH] Server: Improve browser detection (cherry picked from commit 2e19017d0ea8de0e7c8a7550c3846abcf4e3b941) --- chrome/content/zotero/xpcom/server/server.js | 26 ++++++-------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/chrome/content/zotero/xpcom/server/server.js b/chrome/content/zotero/xpcom/server/server.js index ccc79b916a..ace195eb14 100755 --- a/chrome/content/zotero/xpcom/server/server.js +++ b/chrome/content/zotero/xpcom/server/server.js @@ -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; }