2026-10-13 10:33:31 +02:00
import test from 'node:test' ;
import assert from 'node:assert/strict' ;
import net from 'node:net' ;
import { createServer } from 'node:http' ;
import { mkdtempSync , rmSync } from 'node:fs' ;
import { tmpdir } from 'node:os' ;
import { join } from 'node:path' ;
import { createApp } from '../apps/server/app.mjs' ;
import { openStore , digest } from '../apps/server/store.mjs' ;
test ( 'central ICAP capability probe sends no content; gateway cannot bypass external scanning' , async t =>{
const directory = mkdtempSync ( join ( tmpdir (), 'safetynet-enterprise-gateway-' )), store = openStore ( directory ), adminToken = 'public-fixture-administrator-0123456789' ;
const marker = 'PUBLIC_AV_TEST_MARKER' ; let scans = 0 , upstreamRequests = 0 , infectAnswer = false ; const sockets = new Set ();
const icap = net . createServer ( socket =>{ sockets . add ( socket ); socket . once ( 'close' ,()=> sockets . delete ( socket )); socket . on ( 'error' ,()=>{}); let input = Buffer . alloc ( 0 ), done = false ; socket . on ( 'data' , chunk =>{ input = Buffer . concat ([ input , chunk ]); if ( done || input . indexOf ( '\r\n\r\n' ) < 0 ) return ; const options = input . subarray ( 0 , 7 ). toString () === 'OPTIONS' ; if ( ! options &&! input . subarray ( - 5 ). equals ( Buffer . from ( '0\r\n\r\n' ))) return ; done = true ; if ( options ) return socket . end ( 'ICAP/1.0 200 OK\r\nMethods: RESPMOD\r\nAllow: 204\r\nISTag: "fixture"\r\nEncapsulated: null-body=0\r\n\r\n' ); scans ++ ; socket . end ( input . includes ( Buffer . from ( marker )) ? 'ICAP/1.0 200 OK\r\nEncapsulated: res-hdr=0, res-body=99\r\n\r\nHTTP/1.1 403 Forbidden' : 'ICAP/1.0 204 No Content\r\nISTag: "fixture"\r\n\r\n' );});}). listen ( 0 , '127.0.0.1' ); await new Promise ( r => icap . once ( 'listening' , r ));
const upstream = createServer (( req , res )=>{ upstreamRequests ++ ; req . resume (); res . setHeader ( 'content-type' , 'application/json' ); res . end ( JSON . stringify ({ choices : [{ message : { content : infectAnswer ? marker : 'Public safe answer' }}]}));}). listen ( 0 , '127.0.0.1' ); await new Promise ( r => upstream . once ( 'listening' , r ));
const policy = store . get ( 'policy' ); policy . ai = {... policy . ai , enabled : true , trustMode : 'local' , model : 'public-fixture-model' }; policy . enterprise . icap = {... policy . enterprise . icap , enabled : true , url : `icap://127.0.0.1: ${ icap . address (). port } /av` , timeoutMs : 1000 }; store . put ( 'policy' , policy );
const config = { publicUrl : 'http://127.0.0.1' , secure : false , adminToken , requirePQManagement : true , aiBaseUrl : `http://127.0.0.1: ${ upstream . address (). port } ` , aiModel : policy . ai . model , aiEndpointId : 'default' };
const server = createApp ( store , config ). listen ( 0 , '127.0.0.1' ); await new Promise ( r => server . once ( 'listening' , r )); const base = `http://127.0.0.1: ${ server . address (). port } ` ;
t . after ( async ()=>{ for ( const socket of sockets ) socket . destroy (); for ( const service of [ server , upstream ]) service . closeAllConnections (); await Promise . all ([ server , upstream , icap ]. map ( service => new Promise ( r => service . close ( r )))); store . db . close (); assert . ok ( directory . startsWith ( join ( tmpdir (), 'safetynet-enterprise-gateway-' ))); rmSync ( directory ,{ recursive : true , force : true });});
async function api ( route , body , token = adminToken ){ const response = await fetch ( base + route ,{ method : 'POST' , headers : { authorization : `Bearer ${ token } ` , 'content-type' : 'application/json' }, body : JSON . stringify ( body )}); return { status : response . status , body : await response . json ()};}
const code = 'public-fixture-one-use-enrollment-code' ; store . db . prepare ( 'INSERT INTO enrollments VALUES(?,?,?)' ). run ( digest ( code ), Date . now () + 60000 , 'public-user' ); const device = ( await api ( '/api/device/enroll' ,{ name : 'public-device' , platform : 'win32' , code }, '' )). body ;
assert . equal (( await api ( '/api/admin/integrations/icap/probe' , policy . enterprise . icap , device . token )). status , 401 );
const probe = await api ( '/api/admin/integrations/icap/probe' , policy . enterprise . icap ); assert . equal ( probe . status , 200 ); assert . equal ( probe . body . ready , true ); assert . equal ( probe . body . contentSent , false ); assert . equal ( scans , 0 );
const blocked = await api ( '/api/device/ai' ,{ prompt : marker }, device . token ); assert . equal ( blocked . status , 403 ); assert . equal ( upstreamRequests , 0 );
2026-10-13 23:19:22 +02:00
const encoded = await api ( '/api/device/ai' ,{ prompt : Buffer . from ( marker ). toString ( 'base64' )}, device . token ); assert . equal ( encoded . status , 403 ); assert . equal ( upstreamRequests , 0 , 'Decoded blocked content must never reach the provider' );
2026-10-13 10:33:31 +02:00
const allowed = await api ( '/api/device/ai' ,{ prompt : 'Public benign prompt' }, device . token ); assert . equal ( allowed . status , 200 ); assert . equal ( allowed . body . answer , 'Public safe answer' ); assert . equal ( upstreamRequests , 1 );
infectAnswer = true ; const response = await api ( '/api/device/ai' ,{ prompt : 'Public second prompt' }, device . token ); assert . equal ( response . status , 403 ); assert . equal ( Object . hasOwn ( response . body , 'answer' ), false );
const events = store . db . prepare ( 'SELECT metadata FROM events' ). all (); assert . equal ( JSON . stringify ( events ). includes ( marker ), false ); assert . equal ( JSON . stringify ( events ). includes ( 'Public benign prompt' ), false ); assert . ok ( scans >= 5 );
});