Add packaged DLP broker and protected Windows service foundation

This commit is contained in:
Karl committed 2026-10-14 14:19:22 +02:00
1 parent 95d23f4e0b
commit 7b5057901a
140 files changed
+11215 -60

No files matched your search

+23
View File
@@ -0,0 +1,23 @@
'use strict';
const {app,session}=require('electron');
const {createBrokerCertificatePins}=require('../../apps/browser/broker-certificate-pins.cjs');
app.disableHardwareAcceleration();
let initialized=false;
process.once('disconnect',()=>app.exit(0));
process.on('message',async input=>{
if(input?.type==='stop'){app.exit(0);return;}
if(initialized||input?.type!=='start')return;initialized=true;
try{
app.setPath('userData',input.profile);await app.whenReady();
const partition=session.fromPartition('certificate-pin-native',{cache:false});
const pins=createBrokerCertificatePins({generation:'synthetic-generation',policyVersion:4,current:()=>true,authorizedAuthority:authority=>authority===input.leaf.authority});
pins.accept({...input.leaf,generation:'synthetic-generation',policyVersion:4});
partition.setCertificateVerifyProc((request,callback)=>pins.verify(request,callback));
await partition.setProxy({mode:'direct'});
const allowed=await partition.fetch(input.publicURL,{signal:AbortSignal.timeout(10000)});
const publicBody=await allowed.text();let denied=false;
try{await partition.fetch(input.untrustedURL,{signal:AbortSignal.timeout(10000)});}catch{denied=true;}
await partition.closeAllConnections();pins.revoke();
process.send({type:'proof',publicStatus:allowed.status,publicBody,untrustedRejected:denied,electron:process.versions.electron,chromium:process.versions.chrome});
}catch{process.send({type:'fault',reason:'certificate-native-proof-failed'});}
});
+17
View File
@@ -0,0 +1,17 @@
'use strict';
// Test-only, actual fsync of synthetic metadata. Production uses the protected
// encrypted audit store; this fixture never stores request contents or tokens.
const fs=require('node:fs');
const path=require('node:path');
const {randomUUID}=require('node:crypto');
const {BrokerAuditEventSchema}=require('../../apps/network-broker/audit-gate.cjs');
function createSyntheticAudit(test){
const root=path.resolve(__dirname,'../../artifacts/broker-audit-fixtures');fs.mkdirSync(root,{recursive:true});
const filename=path.join(root,`${randomUUID()}.jsonl`),fd=fs.openSync(filename,'wx');
test.after(()=>fs.closeSync(fd));
return Object.freeze({
persist:event=>{BrokerAuditEventSchema.parse(event);fs.writeFileSync(fd,JSON.stringify(event)+'\n');fs.fsyncSync(fd);return {persisted:true,eventId:event.eventId};},
events:()=>fs.readFileSync(filename,'utf8').trim().split('\n').filter(Boolean).map(line=>JSON.parse(line))
});
}
module.exports={createSyntheticAudit};
+42
View File
@@ -0,0 +1,42 @@
'use strict';
// Test-only stock Electron client. No production browser APIs or policy edits.
const {app,BrowserWindow,session}=require('electron');
const {X509Certificate}=require('node:crypto');
app.disableHardwareAcceleration();
let window,config,loginCount=0,initialized=false;
const send=value=>{if(process.connected)process.send(value);};
process.on('disconnect',()=>app.exit(0));
app.on('login',(event,contents,_details,info,callback)=>{
event.preventDefault();
if(config&&contents===window?.webContents&&info.isProxy&&info.host==='127.0.0.1'&&info.port===config.proxyPort&&info.scheme.toLowerCase()==='basic'&&info.realm==='SafetyNet private broker'){
loginCount++;callback(config.credentials.username,config.credentials.password);
}else callback();
});
process.on('message',async message=>{
try {
if(message?.type==='initialize'&&!initialized){
initialized=true;config=message.config;
app.setPath('userData',config.userData);
await app.whenReady();
const partition=session.fromPartition('broker-interop',{cache:false});
partition.setCertificateVerifyProc((request,callback)=>{
try {
const certificate=new X509Certificate(request.certificate.data);
const now=Date.now();
if(request.hostname==='localhost'&&certificate.checkHost('localhost')==='localhost'&&certificate.fingerprint256===config.fingerprint&&Date.parse(certificate.validFrom)<=now&&now<Date.parse(certificate.validTo))return callback(0);
}catch{}
callback(-3);
});
await partition.setProxy({mode:'fixed_servers',proxyRules:`http=127.0.0.1:${config.proxyPort};https=127.0.0.1:${config.proxyPort}`,proxyBypassRules:'<-loopback>'});
window=new BrowserWindow({show:false,webPreferences:{session:partition,nodeIntegration:false,contextIsolation:true,sandbox:true,webSecurity:true}});
window.webContents.on('render-process-gone',()=>send({type:'error',code:'renderer-gone'}));
await window.loadURL(config.origin+'/');
send({type:'ready',loginCount,electron:process.versions.electron,chromium:process.versions.chrome});return;
}
if(message?.type==='stop'){window?.destroy();app.exit(0);return;}
const bodies={public:'public browser content',secret:'PROJECT SECRET',revoked:'public revoked content'};
if(!window||!Object.hasOwn(bodies,message?.type))throw Error('invalid-message');
const result=await window.webContents.executeJavaScript(`(async()=>{try{const response=await fetch('/submit',{method:'POST',body:${JSON.stringify(bodies[message.type])}});return {status:response.status,body:await response.text()};}catch{return {blocked:true};}})()`);
send({type:'result',operation:message.type,result,loginCount});
} catch {send({type:'error',code:'interop-failed'});}
});
+19
View File
@@ -0,0 +1,19 @@
'use strict';
// Diagnostic fixture only: compare explicitly allowlisted environment profiles
// against a real packaged contained inspector. No private content or values.
const path=require('node:path');
const {startInspector}=require('../../apps/browser/inspection.cjs');
const {execFileSync}=require('node:child_process');
function children(){const text=execFileSync('C:/Windows/System32/WindowsPowerShell/v1.0/powershell.exe',['-NoProfile','-NonInteractive','-Command',`@(Get-CimInstance Win32_Process -Filter "ParentProcessId = ${process.pid}" | Where-Object Name -eq 'python.exe' | Select-Object -ExpandProperty ProcessId) | ConvertTo-Json -Compress`],{encoding:'utf8',windowsHide:true,timeout:10000}).trim();return text?[].concat(JSON.parse(text)):[];}
async function main(){
const {defaultPolicy}=await import('../../packages/core/policy.mjs');const baseline={...process.env},root=path.resolve(__dirname,'../../.runtime/windows');
for(const variant of ['stripped','profile']){
const allowed=['SystemRoot','WINDIR','TEMP','TMP',...(variant==='profile'?['USERPROFILE','LOCALAPPDATA','APPDATA']:[])];for(const key of Object.keys(process.env))delete process.env[key];for(const key of allowed)if(baseline[key])process.env[key]=baseline[key];
let inspector,stage='startup',result;
try{inspector=startInspector(root,true);if(!inspector)throw Error('fixed-path-fault');await inspector.waitReady();stage='scan';const answer=await inspector.inspect(Buffer.from('public synthetic text'),defaultPolicy());result={variant,stage,decision:answer.decision,complete:answer.coverage.complete};}
catch{result={variant,stage,failed:true};}
finally{inspector?.stop();for(let count=0;count<20&&children().length;count++)await new Promise(resolve=>setTimeout(resolve,100));result.ownedParents=children().length;}
process.stdout.write(JSON.stringify(result)+'\n');if(result.ownedParents)throw Error('fixed-cleanup-fault');
}
}
main().catch(()=>{process.stderr.write('fixed-environment-proof-fault\n');process.exitCode=1;});
+29
View File
@@ -0,0 +1,29 @@
'use strict';
// Explicitly authorized synthetic fixture only. Private bounded in-memory OTLP
// receiver; no real management policy, content, token or production exporter.
const http=require('node:http');
const {createDiagnostics}=require('../../apps/browser/diagnostics.cjs');
async function createFixtureDiagnostics({enabled,policy,audit}){
if(!enabled)return {persist:audit.persist,run:(_attributes,fn)=>fn(),stage:(_name,_attributes,fn)=>fn(),finish:async()=>({enabled:false})};
const batches=[];let storedBytes=0,invalid=0;const spans=()=>batches.flatMap(batch=>(batch.resourceSpans||[]).flatMap(resource=>(resource.scopeSpans||[]).flatMap(scope=>scope.spans||[])));
const server=http.createServer({maxHeaderSize:8192},async(request,response)=>{
if(request.method==='GET'&&/^\/api\/trace\/[a-f0-9]{32}$/.test(request.url)){const id=request.url.split('/').pop();response.setHeader('content-type','application/json');response.end(JSON.stringify({spans:spans().filter(span=>span.traceId===id)}));return;}
if(request.method!=='POST'||!['/v1/traces','/v1/logs'].includes(request.url)){response.writeHead(404);response.end();return;}
const chunks=[];let size=0;
try{for await(const chunk of request){size+=chunk.length;if(size>1048576||storedBytes+size>4194304)throw Error('fixed-budget');chunks.push(chunk);}const text=Buffer.concat(chunks).toString();if(text.includes('SYNTHETIC_PRIVATE')||text.includes('proxy-password')||text.includes('%PDF-'))throw Error('fixed-content');const value=JSON.parse(text);if(request.url==='/v1/traces')batches.push(value);storedBytes+=size;response.setHeader('content-type','application/json');response.end('{}');}catch{invalid++;response.writeHead(400);response.end('{}');}
});server.maxConnections=8;server.listen(0,'127.0.0.1');await new Promise(resolve=>server.once('listening',resolve));
const endpoint=`http://127.0.0.1:${server.address().port}`,diagnostics=createDiagnostics();let active;
policy.diagnostics={...policy.diagnostics,enabled:true,mode:'debug',endpoint,sampleRate:1,debugSampleRate:1,maxRecordAgeMs:120000};
if(!diagnostics.configure(policy.diagnostics,{policyVersion:policy.version,deviceId:'native-production-fixture'}))throw Error('fixture-diagnostics-unavailable');
return {
stage:(name,attributes,fn)=>diagnostics.span(name,attributes,fn),
async trace(traceId){if(!/^[a-f0-9]{32}$/.test(traceId))throw Error('fixture-trace-invalid');await diagnostics.flush();const response=await fetch(endpoint+'/api/trace/'+traceId);if(!response.ok)throw Error('fixture-trace-unavailable');return response.json();},
persist:event=>diagnostics.withCorrelation(active,()=>diagnostics.spanSync('browser.management',{operation:'audit.deliver',component:'management'},()=>audit.persist({...event,...diagnostics.correlation()}))),
run:(attributes,fn)=>diagnostics.span('browser.request',{operation:'broker.request',component:'network',...attributes},async()=>{active=diagnostics.correlation();try{return await fn();}finally{active=undefined;}}),
async finish(){
try{await diagnostics.flush();const status=diagnostics.status();if(status.failedExports||status.lifetimeFailedExports||invalid)throw Error('fixture-diagnostics-export-failed');const event=audit.events().find(value=>value.traceId);if(!event)throw Error('fixture-diagnostics-correlation-missing');const response=await fetch(endpoint+'/api/trace/'+event.traceId),trace=await response.json();const child=trace.spans.find(value=>value.spanId===event.spanId),parent=trace.spans.find(value=>value.spanId===child?.parentSpanId);if(!child||!parent||parent.name!=='browser.request'||BigInt(parent.endTimeUnixNano)<=BigInt(parent.startTimeUnixNano))throw Error('fixture-diagnostics-parent-missing');const stages=trace.spans.filter(value=>value.name.startsWith('browser.broker.')).map(value=>({name:value.name,parentSpanId:value.parentSpanId,durationMs:Number(BigInt(value.endTimeUnixNano)-BigInt(value.startTimeUnixNano))/1e6}));return {enabled:true,traceId:event.traceId,auditSpanId:event.spanId,parentSpanId:parent.spanId,spanCount:spans().length,storedBytes,stages,invalid,failedExports:status.failedExports,lifetimeFailedExports:status.lifetimeFailedExports};}
finally{await diagnostics.shutdown();server.closeAllConnections();await new Promise(resolve=>server.close(resolve));}
}
};
}
module.exports={createFixtureDiagnostics};
+19
View File
@@ -0,0 +1,19 @@
'use strict';
// Synthetic classification belongs only in this explicitly test-only factory.
const fs=require('node:fs');
const path=require('node:path');
const https=require('node:https');
const {runBrokerProcess}=require('../../apps/network-broker/process-entry.cjs');
const {createConnectProxy}=require('../../apps/network-broker/connect-inspection-proxy.cjs');
const cert=fs.readFileSync(path.join(__dirname,'icap/cert.pem'));
const key=fs.readFileSync(path.join(__dirname,'icap/key.pem'));
runBrokerProcess(config=>{
if(Object.keys(config).join(',')!=='destination'||typeof config.destination!=='string'||!/^localhost:[1-9][0-9]{0,4}$/.test(config.destination))throw Error('invalid-test-config');
const port=Number(config.destination.split(':')[1]);if(port>65535)throw Error('invalid-test-config');
return createConnectProxy({authority:'synthetic-test-policy',current:()=>true,resolveCertificate:binding=>binding.authority===config.destination?{authority:config.destination,key,cert}:undefined,inspect:({body})=>({decision:body.toString().includes('SECRET')?'block':'allow'}),forward:({request,body,signal,maxResponseBytes})=>new Promise((resolve,reject)=>{
const outgoing=https.request({host:'127.0.0.1',port,path:new URL(request.url).pathname,method:request.method,servername:'localhost',ca:cert,rejectUnauthorized:true,signal,headers:{host:config.destination,'content-length':body.length}},res=>{
const chunks=[];let bytes=0;
res.on('data',chunk=>{bytes+=chunk.length;if(bytes>maxResponseBytes){outgoing.destroy();reject(Error('response-bound'));return;}chunks.push(Buffer.from(chunk));});res.on('end',()=>resolve({statusCode:res.statusCode,headers:res.headers,body:Buffer.concat(chunks)}));res.on('error',reject);
});outgoing.on('error',reject);outgoing.end(body);
}),deadlineMs:1000,authMode:'bearer'});
});
+17
View File
@@ -0,0 +1,17 @@
'use strict';
const {createFramedChannel}=require('../../apps/network-broker/framed-channel.cjs');
const channel=createFramedChannel({readable:process.stdin,writable:process.stdout,inboundFirstLimit:2097152});
channel.once('disconnect',()=>process.exit(0));
let context;
channel.on('message',message=>{
if(message.type==='start'){
context={version:1,generation:message.generation,policyVersion:message.policyVersion};
if(message.config.malformed){process.stdout.write(Buffer.from([1,0,0,0,0xff]));return;}
channel.send({type:'ready',...context,authMode:'basic',sequence:0,port:message.config.port,credentials:{username:'safetynet-'+'a'.repeat(32),password:'b'.repeat(43)}},error=>{
if(error)process.exit(2);
if(message.config.audit){const id='12345678-1234-4234-8234-123456789abc';channel.send({type:'audit',...context,sequence:1,requestId:id,event:{eventId:id,kind:'upload.authorized',ruleId:'broker-approved',policyVersion:context.policyVersion,request:{bytes:0,detectedType:'text'}}});}
});
}else if(message.type==='audit-receipt'){
if(message.receipt?.persisted!==true||message.receipt.eventId!==message.requestId)process.exit(3);
}else process.exit(4);
});