diff --git a/app/common/gristUrls.ts b/app/common/gristUrls.ts index cdd2b5c3..1f7039f0 100644 --- a/app/common/gristUrls.ts +++ b/app/common/gristUrls.ts @@ -185,7 +185,7 @@ export interface OrgUrlInfo { orgInPath?: string; // If /o/{orgInPath} should be used to access the requested org. } -export function hostMatchesUrl(host?: string, url?: string) { +function hostMatchesUrl(host?: string, url?: string) { return host !== undefined && url !== undefined && new URL(url).host === host; } diff --git a/app/gen-server/lib/DocApiForwarder.ts b/app/gen-server/lib/DocApiForwarder.ts index 4be608af..e79e2cd7 100644 --- a/app/gen-server/lib/DocApiForwarder.ts +++ b/app/gen-server/lib/DocApiForwarder.ts @@ -104,7 +104,7 @@ export class DocApiForwarder { url.pathname = removeTrailingSlash(docWorkerUrl.pathname) + url.pathname; const headers: {[key: string]: string} = { - ...getTransitiveHeaders(req), + ...getTransitiveHeaders(req, { includeOrigin: true }), 'Content-Type': req.get('Content-Type') || 'application/json', }; for (const key of ['X-Sort', 'X-Limit']) { diff --git a/app/server/lib/AppEndpoint.ts b/app/server/lib/AppEndpoint.ts index a676f5e7..c38f6e0e 100644 --- a/app/server/lib/AppEndpoint.ts +++ b/app/server/lib/AppEndpoint.ts @@ -149,7 +149,7 @@ export function attachAppEndpoint(options: AttachOptions): void { // TODO docWorkerMain needs to serve app.html, perhaps with correct base-href already set. const headers = { Accept: 'application/json', - ...getTransitiveHeaders(req), + ...getTransitiveHeaders(req, { includeOrigin: true }), }; const workerInfo = await getWorker(docWorkerMap, docId, `/${docId}/app.html`, {headers}); docStatus = workerInfo.docStatus; diff --git a/app/server/lib/Authorizer.ts b/app/server/lib/Authorizer.ts index 2ad7d134..b8c85981 100644 --- a/app/server/lib/Authorizer.ts +++ b/app/server/lib/Authorizer.ts @@ -677,7 +677,10 @@ export function assertAccess( * Pull out headers to pass along to a proxied service. Focused primarily on * authentication. */ -export function getTransitiveHeaders(req: Request): {[key: string]: string} { +export function getTransitiveHeaders( + req: Request, + { includeOrigin }: { includeOrigin: boolean } +): {[key: string]: string} { const Authorization = req.get('Authorization'); const Cookie = req.get('Cookie'); const PermitHeader = req.get('Permit'); @@ -685,8 +688,6 @@ export function getTransitiveHeaders(req: Request): {[key: string]: string} { const XRequestedWith = req.get('X-Requested-With'); const Origin = req.get('Origin'); // Pass along the original Origin since it may // play a role in granular access control. - const Host = req.get('Host'); // Also pass along the original Host, as we need it since - // the destination compares that with the Origin header. const result: Record = { ...(Authorization ? { Authorization } : undefined), @@ -694,8 +695,7 @@ export function getTransitiveHeaders(req: Request): {[key: string]: string} { ...(Organization ? { Organization } : undefined), ...(PermitHeader ? { Permit: PermitHeader } : undefined), ...(XRequestedWith ? { 'X-Requested-With': XRequestedWith } : undefined), - ...(Origin ? { Origin } : undefined), - ...(Host ? { Host } : undefined), + ...((includeOrigin && Origin) ? { Origin } : undefined), }; const extraHeader = process.env.GRIST_FORWARD_AUTH_HEADER; const extraHeaderValue = extraHeader && req.get(extraHeader); diff --git a/app/server/lib/DocApi.ts b/app/server/lib/DocApi.ts index 8d33aada..e1dbe3fd 100644 --- a/app/server/lib/DocApi.ts +++ b/app/server/lib/DocApi.ts @@ -1102,7 +1102,7 @@ export class DocWorkerApi { const result = await fetch(homeUrl, { method: 'GET', headers: { - ...getTransitiveHeaders(req), + ...getTransitiveHeaders(req, { includeOrigin: false }), 'Content-Type': 'application/json', } }); @@ -1115,7 +1115,7 @@ export class DocWorkerApi { await fetch(this._grist.getHomeInternalUrl(`/api/docs/${options.sourceDocId}/flush`), { method: 'POST', headers: { - ...getTransitiveHeaders(req), + ...getTransitiveHeaders(req, { includeOrigin: false }), 'Content-Type': 'application/json', } }); @@ -1173,7 +1173,7 @@ export class DocWorkerApi { const {states} = await this._getStates(docSession, activeDoc); const ref = await fetch(this._grist.getHomeInternalUrl(`/api/docs/${req.params.docId2}/states`), { headers: { - ...getTransitiveHeaders(req), + ...getTransitiveHeaders(req, { includeOrigin: false }), 'Content-Type': 'application/json', } }); @@ -1202,7 +1202,7 @@ export class DocWorkerApi { const url = `/api/docs/${req.params.docId2}/compare?left=${parent.h}`; const rightChangesReq = await fetch(this._grist.getHomeInternalUrl(url), { headers: { - ...getTransitiveHeaders(req), + ...getTransitiveHeaders(req, { includeOrigin: false }), 'Content-Type': 'application/json', } }); diff --git a/app/server/lib/FlexServer.ts b/app/server/lib/FlexServer.ts index 6a7af17b..59d8a3e5 100644 --- a/app/server/lib/FlexServer.ts +++ b/app/server/lib/FlexServer.ts @@ -2436,7 +2436,7 @@ export class FlexServer implements GristServer { const copyDocUrl = this.getHomeInternalUrl('/api/docs'); const response = await fetch(copyDocUrl, { headers: { - ...getTransitiveHeaders(req), + ...getTransitiveHeaders(req, { includeOrigin: false }), 'Content-Type': 'application/json', }, method: 'POST', diff --git a/app/server/lib/uploads.ts b/app/server/lib/uploads.ts index c2a2eaa1..4c78df30 100644 --- a/app/server/lib/uploads.ts +++ b/app/server/lib/uploads.ts @@ -420,7 +420,7 @@ export async function fetchDoc( template: boolean ): Promise { // Prepare headers that preserve credentials of current user. - const headers = getTransitiveHeaders(req); + const headers = getTransitiveHeaders(req, { includeOrigin: false }); // Passing the Origin header would serve no purpose here, as we are // constructing an internal request to fetch from our own doc worker