From c0e803a24b6c1dcace670daf001fcd64612614d9 Mon Sep 17 00:00:00 2001 From: SPGoding Date: Sat, 4 Jan 2025 00:16:06 -0600 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Indicate=20weak=20validator=20in?= =?UTF-8?q?=20ETag=20header?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/web-api-server/src/index.ts | 1 - packages/web-api-server/src/utils.ts | 9 +++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/web-api-server/src/index.ts b/packages/web-api-server/src/index.ts index c2fbcc76a..b4dfce80e 100644 --- a/packages/web-api-server/src/index.ts +++ b/packages/web-api-server/src/index.ts @@ -51,7 +51,6 @@ const DELAY_AFTER = 50 const app = express() .set('trust proxy', 1) - .set('etag', 'strong') .use(cors({ exposedHeaders: [ 'ETag', diff --git a/packages/web-api-server/src/utils.ts b/packages/web-api-server/src/utils.ts index 9ffbbbb3b..35476c34e 100644 --- a/packages/web-api-server/src/utils.ts +++ b/packages/web-api-server/src/utils.ts @@ -92,7 +92,11 @@ export async function sendGitFile( path: string, ) { const hash = (await git.log(['--format=%H', '-1', branch, '--', path])).latest!.hash - res.setHeader('ETag', hash) + // Git commit sha is a [weak validator](https://datatracker.ietf.org/doc/html/rfc2616#section-3.11), + // since the same value is used for different representations of the same resource (e.g. gzip + // compressed v.s. no compression). It can only guarantee semantic equivalence, not byte-for-byte + // equivalence. + res.setHeader('ETag', `W/"${hash}"`) if (req.headers['if-none-match'] === hash) { res.status(304).end() await rateLimiter.reward(req.ip!, CHEAP_REQUEST_POINTS) @@ -117,7 +121,8 @@ export async function sendGitTarball( fileName = branch, ) { const hash = (await git.log(['--format=%H', '-1', branch])).latest!.hash - res.setHeader('ETag', hash) + // See comments in sendGitFile() for why this is a weak validator. + res.setHeader('ETag', `W/"${hash}"`) if (req.headers['if-none-match'] === hash) { res.status(304).end() await rateLimiter.reward(req.ip!, EXPENSIVE_REQUEST_POINTS)