From: Ardis Lu Date: Fri, 22 May 2026 05:33:15 +0000 (-0700) Subject: Verify `Content-Type` header on POST X-Git-Tag: v0.1.2~11 X-Git-Url: https://git.ardis.lu/?a=commitdiff_plain;h=417db81d18a306aeb0d1c4ab91bac92490537268;p=envpass Verify `Content-Type` header on POST Setting this header to `application/json` forces the request to be CORS preflighted (i.e. not a "simple request"). This is further security hardening against cross-origin requests from a web browser. --- diff --git a/src/getPrf.js b/src/getPrf.js index 3e39e36..23aeebf 100644 --- a/src/getPrf.js +++ b/src/getPrf.js @@ -94,6 +94,10 @@ export async function getPrf(options = {}) { response.writeHead(403).end(); return; } + if (request.headers['content-type'] !== 'application/json') { + response.writeHead(400).end(); + return; + } let body = ''; request.on('data', chunk => body += chunk); request.on('end', () => { diff --git a/test/getPrf.test.js b/test/getPrf.test.js index f593595..81ea63d 100644 --- a/test/getPrf.test.js +++ b/test/getPrf.test.js @@ -19,14 +19,16 @@ suite('getPrf.js (server)', () => { const challenge = searchParams.get('challenge'); const prf = 'deadbeef000000000000000000000000000000000000000000000000cafebabe'; - deepStrictEqual((await fetch(origin, { method: 'POST', body: JSON.stringify({ challenge, prf }) })).status, 403); // No origin - deepStrictEqual((await fetch(origin, { method: 'POST', headers: { origin: 'null' }, body: JSON.stringify({ challenge, prf }) })).status, 403); // Null origin - deepStrictEqual((await fetch(origin, { method: 'POST', headers: { origin: 'https://example.com' }, body: JSON.stringify({ challenge, prf }) })).status, 403); // Bad origin - deepStrictEqual((await fetch(origin, { method: 'POST', headers: { origin }, body: JSON.stringify({ prf }) })).status, 401); // No challenge - deepStrictEqual((await fetch(origin, { method: 'POST', headers: { origin }, body: JSON.stringify({ challenge: 'INVALID', prf }) })).status, 401); // Bad challenge - deepStrictEqual((await fetch(origin, { method: 'POST', headers: { origin }, body: JSON.stringify({ challenge }) })).status, 400); // No prf - deepStrictEqual((await fetch(origin, { method: 'POST', headers: { origin }, body: JSON.stringify({ challenge, prf: 'INVALID' }) })).status, 400); // Bad prf - deepStrictEqual((await fetch(origin, { method: 'POST', headers: { origin }, body: JSON.stringify({ challenge, prf }) })).status, 200); // Good + deepStrictEqual((await fetch(origin, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ challenge, prf }) })).status, 403); // No origin + deepStrictEqual((await fetch(origin, { method: 'POST', headers: { origin: 'null', 'Content-Type': 'application/json' }, body: JSON.stringify({ challenge, prf }) })).status, 403); // Null origin + deepStrictEqual((await fetch(origin, { method: 'POST', headers: { origin: 'https://example.com', 'Content-Type': 'application/json' }, body: JSON.stringify({ challenge, prf }) })).status, 403); // Bad origin + deepStrictEqual((await fetch(origin, { method: 'POST', headers: { origin }, body: JSON.stringify({ challenge, prf }) })).status, 400); // No Content-Type + deepStrictEqual((await fetch(origin, { method: 'POST', headers: { origin, 'Content-Type': 'INVALID' }, body: JSON.stringify({ challenge, prf }) })).status, 400); // Bad Content-Type + deepStrictEqual((await fetch(origin, { method: 'POST', headers: { origin, 'Content-Type': 'application/json' }, body: JSON.stringify({ prf }) })).status, 401); // No challenge + deepStrictEqual((await fetch(origin, { method: 'POST', headers: { origin, 'Content-Type': 'application/json' }, body: JSON.stringify({ challenge: 'INVALID', prf }) })).status, 401); // Bad challenge + deepStrictEqual((await fetch(origin, { method: 'POST', headers: { origin, 'Content-Type': 'application/json' }, body: JSON.stringify({ challenge }) })).status, 400); // No prf + deepStrictEqual((await fetch(origin, { method: 'POST', headers: { origin, 'Content-Type': 'application/json' }, body: JSON.stringify({ challenge, prf: 'INVALID' }) })).status, 400); // Bad prf + deepStrictEqual((await fetch(origin, { method: 'POST', headers: { origin, 'Content-Type': 'application/json' }, body: JSON.stringify({ challenge, prf }) })).status, 200); // Good deepStrictEqual(await prfActual, Uint8Array.fromHex(prf)); }); test('window expiration works', async (t) => {