Files
safetynet/tests/loopback-http.test.mjs
2026-10-13 10:34:48 +02:00

20 lines
1.8 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import {createServer} from 'node:http';
import {createRequire} from 'node:module';
const {postLoopback}=createRequire(import.meta.url)('../apps/browser/loopback-http.cjs');
async function server(t,handler){const s=createServer(handler).listen(0,'127.0.0.1');await new Promise(r=>s.on('listening',r));t.after(()=>new Promise(r=>s.close(r)));return s.address().port;}
test('private local requests use direct authenticated loopback transport',async t=>{
const port=await server(t,(req,res)=>{assert.equal(req.headers.authorization,'Bearer test-capability');assert.equal(req.url,'/inspect');let body='';req.on('data',data=>body+=data);req.on('end',()=>{assert.deepEqual(JSON.parse(body),{content:'private fixture'});res.end(JSON.stringify({decision:'allow'}));});});
assert.equal((await postLoopback({port,route:'/inspect',token:'test-capability',body:{content:'private fixture'},signal:AbortSignal.timeout(2000)})).body.decision,'allow');
});
test('redirects cannot forward local capabilities or content',async t=>{
let forwarded=0;const target=await server(t,(_req,res)=>{forwarded++;res.end('{}');});
const port=await server(t,(_req,res)=>{res.writeHead(307,{location:`http://127.0.0.1:${target}/capture`});res.end('{}');});
await assert.rejects(postLoopback({port,route:'/inspect',token:'private-capability',body:{content:'private'},signal:AbortSignal.timeout(2000)}),/redirects/);assert.equal(forwarded,0);
});
test('oversized scanner replies fail closed',async t=>{
const port=await server(t,(_req,res)=>res.end(JSON.stringify({data:'x'.repeat(4096)})));
await assert.rejects(postLoopback({port,route:'/inspect',token:'test-capability',body:{},maxResponseBytes:100,signal:AbortSignal.timeout(2000)}),/budget/);
});