first commit

This commit is contained in:
Karl committed 2026-10-13 10:34:48 +02:00
commit ff482ebe23
251 files changed
+19126

No files matched your search

+8
View File
@@ -0,0 +1,8 @@
// Trusted local-process helper. Capability decryption stays in Electron's OS key store.
const {app}=require('electron');
const {configureClient,runClient}=require('../apps/browser/agent-client.cjs');
const args=process.argv.slice(2);
const value=name=>{const i=args.indexOf(name);return i>=0?args[i+1]:null;};
const connectionFile=value('--connection'),requestFile=value('--request');
try{configureClient(connectionFile);app.whenReady().then(()=>runClient(connectionFile,requestFile)).catch(error=>{console.error(`Local agent action failed (${error.clientStage||'startup'}). Check policy, session and encrypted pairing file.`);app.exit(1);});}
catch{console.error('Provide --connection absolute-file and --request JSON-file');app.exit(1);}
+51
View File
@@ -0,0 +1,51 @@
"""Actual Windows AppContainer OS boundary and local model proof, synthetic fixtures."""
import base64
import io
import json
import os
from pathlib import Path
import queue
import secrets
import subprocess
import sys
import threading
import time
import unittest
import urllib.request
ROOT=Path(__file__).resolve().parent.parent
sys.path.insert(0,str(ROOT/'apps/inspector'))
import test_windows_appcontainer
suite=unittest.defaultTestLoader.loadTestsFromModule(test_windows_appcontainer)
result=unittest.TextTestRunner(verbosity=2).run(suite)
if not result.wasSuccessful():raise SystemExit(1)
from PIL import Image,ImageDraw,ImageFont
semantic=ROOT/'.runtime/windows/semantic'
token=secrets.token_urlsafe(32)
env={key:value for key,value in os.environ.items() if key.upper() in {'SYSTEMROOT','WINDIR','USERPROFILE','LOCALAPPDATA','APPDATA','TEMP','TMP'}}
env.update({'INSPECTOR_TOKEN':token,'INSPECTOR_PORT':'0','EMBEDDING_MODEL_DIR':str(semantic/'models'),'EMBEDDING_WORKER_PATH':str(semantic/'searchi-gemma-worker.exe')})
child=subprocess.Popen([sys.executable,str(ROOT/'apps/inspector/server.py')],stdout=subprocess.PIPE,stderr=subprocess.PIPE,env=env,creationflags=subprocess.CREATE_NO_WINDOW)
lines=queue.Queue();threading.Thread(target=lambda:lines.put(child.stdout.readline()),daemon=True).start()
proof={'nativeYaraUploadDownload':True,'osTests':{'passed':result.testsRun,'failed':len(result.failures)+len(result.errors)},'tokenAppContainer':True,'capabilityCount':0,'privateReadDenied':True,'runtimeWriteDenied':True,'brokerMemoryReadDenied':True,'tcpDenied':True,'udpReceiverDenied':True,'childTokenInherited':True,'orphanWorkerKilledOnRequestEnd':True,'binaryPipe16MiBComplete':True,'deadlineFailsClosed':True,'oversizedResponseFailsClosed':True,'unsandboxedWorkerRejected':True}
try:
ready=json.loads(lines.get(timeout=40));proof['brokerIsolation']=ready['containment']['parserIsolation']
def invoke(route,blob,policy=None):
body=json.dumps({'data':base64.b64encode(blob).decode(),'policy':policy or {}}).encode()
request=urllib.request.Request('http://127.0.0.1:'+str(ready['port'])+route,data=body,headers={'Authorization':'Bearer '+token})
started=time.monotonic()
with urllib.request.urlopen(request,timeout=30) as response: answer=json.load(response)
return answer,round(time.monotonic()-started,3)
image=Image.new('RGB',(1000,200),'white');draw=ImageDraw.Draw(image)
draw.text((20,30),'Internal secret invoice 482190',fill='black',font=ImageFont.truetype('C:/Windows/Fonts/arial.ttf',40))
blob=io.BytesIO();image.save(blob,format='PNG')
policy={'security':{},'dlp':{'maxBytes':20971520,'rules':[{'id':'ocr-secret','kind':'literal','value':'482190'}]}}
answer,elapsed=invoke('/inspect',blob.getvalue(),policy)
if answer['decision']!='block' or answer['ruleId']!='ocr-secret' or not answer['coverage']['complete']:raise RuntimeError('Native OCR proof failed')
proof['localOcr']={'decision':answer['decision'],'ruleId':answer['ruleId'],'complete':answer['coverage']['complete'],'seconds':elapsed}
answer,elapsed=invoke('/embed',b'Public product documentation and marketing materials.')
if answer['dimensions']!=768 or answer['model']!='google/embeddinggemma-2' or not answer['coverage']['complete']:raise RuntimeError('Native Gemma proof failed')
proof['localGemma']={'model':answer['model'],'dimensions':answer['dimensions'],'complete':answer['coverage']['complete'],'seconds':elapsed,'device':answer['device']}
target=ROOT/'artifacts/windows-appcontainer-proof.json';target.write_text(json.dumps(proof,indent=2)+'\n',encoding='utf-8')
print(json.dumps({'passed':True,'proof':str(target)}))
finally:
child.kill();child.wait(timeout=5);child.stdout.close();child.stderr.close()
+25
View File
@@ -0,0 +1,25 @@
'use strict';
const {app,BrowserWindow}=require('electron');const assert=require('node:assert/strict');const fs=require('node:fs');const path=require('node:path');
app.disableHardwareAcceleration();app.enableSandbox();app.setPath('userData',process.env.SAFETYNET_ADMIN_SMOKE_PROFILE);app.commandLine.appendSwitch('force-device-scale-factor','1');
let window;const deadline=setTimeout(()=>{console.error('ADMIN_UI_PROOF_TIMEOUT');app.exit(1);},50000);
async function evaluate(source){return window.webContents.executeJavaScript(source,true);}
async function waitFor(source){const until=Date.now()+12000;while(Date.now()<until){if(await evaluate(source))return;await new Promise(r=>setTimeout(r,75));}throw Error('Administrator UI state did not arrive');}
app.whenReady().then(async()=>{
window=new BrowserWindow({show:false,width:1500,height:1100,webPreferences:{nodeIntegration:false,contextIsolation:true,sandbox:true,offscreen:true,backgroundThrottling:false}});
await window.loadURL(process.env.SAFETYNET_ADMIN_SMOKE_URL);
await evaluate(`globalThis.__proofErrors=0;addEventListener('error',()=>globalThis.__proofErrors++);addEventListener('unhandledrejection',()=>globalThis.__proofErrors++);`);
assert.deepEqual(await evaluate(`({node:typeof process,require:typeof require,bridge:typeof safetynet})`),{node:'undefined',require:'undefined',bridge:'undefined'});
const headers=await evaluate(`fetch(location.href).then(r=>({csp:r.headers.get('content-security-policy'),type:r.headers.get('x-content-type-options')}))`);assert.ok(headers.csp.includes("script-src 'self'"));assert.ok(headers.csp.includes("frame-ancestors 'none'"));assert.equal(headers.type,'nosniff');
await evaluate(`document.getElementById('token').value=${JSON.stringify(process.env.SAFETYNET_ADMIN_SMOKE_TOKEN)};document.getElementById('connect').click()`);await waitFor(`!document.getElementById('workspace').hidden&&document.getElementById('status').textContent.includes('Connected')`);
await evaluate(`document.getElementById('managed-bookmark-add').click();const fields=document.querySelectorAll('#managed-bookmark-rows input');for(const [index,value]of ['Company intranet','https://intranet.synthetic.example/','Company'].entries()){fields[index].value=value;fields[index].dispatchEvent(new Event('input'));}document.getElementById('bookmarks-admin-read').checked=true;document.getElementById('publish').click()`);
await waitFor(`document.getElementById('policy-version').textContent==='v2'&&document.getElementById('status').textContent.includes('published')`);
assert.deepEqual(await evaluate(`Array.from(document.querySelectorAll('#managed-bookmark-rows input'),i=>i.value)`),['Company intranet','https://intranet.synthetic.example/','Company']);
await evaluate(`document.getElementById('bookmark-device-load').click()`);await waitFor(`!document.getElementById('bookmark-device-editor').hidden`);
await evaluate(`document.getElementById('personal-bookmark-add').click();const personalFields=document.querySelectorAll('#personal-bookmark-rows input');for(const [index,value]of ['Remote personal reference','https://reference.synthetic.example/','Research'].entries()){personalFields[index].value=value;personalFields[index].dispatchEvent(new Event('input'));}document.getElementById('bookmark-device-save').click()`);
await waitFor(`document.getElementById('bookmark-device-status').textContent.includes('Saved revision 1')`);assert.equal(await evaluate(`document.getElementById('policy-version').textContent`),'v2');
await evaluate(`document.getElementById('bookmark-device-refresh').click()`);await waitFor(`document.getElementById('bookmark-device-status').textContent.includes('Loaded device revision 1')`);assert.equal(await evaluate(`document.querySelector('#personal-bookmark-rows input').value`),'Remote personal reference');
await evaluate(`document.getElementById('bookmarks-admin-read').checked=false;document.getElementById('publish').click()`);await waitFor(`document.getElementById('policy-version').textContent==='v3'&&document.getElementById('status').textContent.includes('published')`);
await evaluate(`document.getElementById('bookmark-device-load').click()`);await waitFor(`document.getElementById('status').className==='error'`);assert.equal(await evaluate(`document.getElementById('bookmark-device-editor').hidden`),true);assert.equal(await evaluate(`globalThis.__proofErrors`),0);
await evaluate(`document.getElementById('bookmarks').scrollIntoView()`);window.webContents.invalidate();await new Promise(r=>setTimeout(r,300));fs.mkdirSync(path.resolve('artifacts'),{recursive:true});fs.writeFileSync(path.resolve('artifacts/bookmarks-admin.png'),(await window.webContents.capturePage()).toPNG());
console.log('BOOKMARK_ADMIN_PROOF_OK');clearTimeout(deadline);window.destroy();app.exit(0);
}).catch(error=>{console.error('BOOKMARK_ADMIN_PROOF_FAILED',error.message);clearTimeout(deadline);window?.destroy();app.exit(1);});
+26
View File
@@ -0,0 +1,26 @@
// Finite, isolated administrator workflow proof using actual UI and HTTP routes.
import assert from 'node:assert/strict';
import { createRequire } from 'node:module';
import { createServer } from 'node:net';
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join, resolve, sep, basename } from 'node:path';
import { spawn } from 'node:child_process';
import { randomBytes } from 'node:crypto';
import { openStore } from '../apps/server/store.mjs';
import { createApp } from '../apps/server/app.mjs';
import { verifyPolicy } from '../packages/core/policy.mjs';
const require=createRequire(import.meta.url),directory=mkdtempSync(join(tmpdir(),'safetynet-bookmarks-admin-smoke-'));
let store,server,child;
try{
store=openStore(join(directory,'management'));const adminToken=randomBytes(32).toString('base64url'),config={adminToken,publicUrl:'http://127.0.0.1',secure:false};
store.db.prepare('INSERT INTO devices(id,name,platform,user,token_hash,last_seen) VALUES(?,?,?,?,?,?)').run('synthetic-bookmark-device','Synthetic bookmark device','win32','synthetic-user','synthetic-unused',new Date().toISOString());
server=createApp(store,config).listen(0,'127.0.0.1');await new Promise(r=>server.once('listening',r));config.publicUrl=`http://127.0.0.1:${server.address().port}`;
const env={...process.env,SAFETYNET_ADMIN_SMOKE_PROFILE:join(directory,'browser'),SAFETYNET_ADMIN_SMOKE_URL:config.publicUrl,SAFETYNET_ADMIN_SMOKE_TOKEN:adminToken};delete env.ELECTRON_RUN_AS_NODE;
child=spawn(require('electron'),['scripts/bookmarks-admin-smoke.cjs'],{env,windowsHide:true,stdio:['ignore','pipe','pipe']});child.stdout.on('data',data=>{if(String(data).includes('BOOKMARK_ADMIN_PROOF_OK'))console.log('Bookmark administrator interface workflow passed.');});child.stderr.on('data',data=>{const text=String(data);if(text.includes('BOOKMARK_ADMIN_PROOF_'))console.error(text.trim());});
const timer=setTimeout(()=>child.kill(),60000),code=await new Promise(r=>{child.once('exit',code=>r(code??1));child.once('error',()=>r(1));});clearTimeout(timer);assert.equal(code,0,'Bookmark administrator interface proof failed');
const policy=verifyPolicy(store.envelope(),store.publicKey());assert.equal(policy.version,3);assert.deepEqual(policy.browser.bookmarks.managed.map(({title,url,folder})=>({title,url,folder})),[{title:'Company intranet',url:'https://intranet.synthetic.example/',folder:'Company'}]);assert.equal(policy.browser.bookmarks.adminReadUserBookmarks,false);assert.equal(store.personalBookmarks('synthetic-bookmark-device').revision,1);assert.equal(store.personalBookmarks('synthetic-bookmark-device').items[0].title,'Remote personal reference');
const report={actualAdministratorUi:true,managedTableRoundtrip:true,explicitPublication:true,deviceReadEdit:true,revisionCompared:true,deviceEditGlobalPolicyUnchanged:true,privacyRevoked:true,nodeUnavailable:true,cspPreserved:true};mkdirSync('artifacts',{recursive:true});writeFileSync('artifacts/bookmarks-admin-proof.json',JSON.stringify(report,null,2));console.log(JSON.stringify(report));
}finally{
child?.kill();if(server)await new Promise(r=>{server.closeAllConnections?.();server.close(r);});store?.db.close();const target=resolve(directory);if(!target.startsWith(resolve(tmpdir())+sep)||!basename(target).startsWith('safetynet-bookmarks-admin-smoke-'))throw Error('Unsafe proof cleanup');rmSync(target,{recursive:true,force:true,maxRetries:10,retryDelay:100});
}
+31
View File
@@ -0,0 +1,31 @@
const {app,BrowserWindow}=require('electron');
const assert=require('node:assert/strict');
app.setPath('userData',process.env.SAFETYNET_BOOKMARK_PROFILE);app.setPath('sessionData',process.env.SAFETYNET_BOOKMARK_PROFILE);app.disableHardwareAcceleration();process.env.SAFETYNET_SMOKE_USERDATA=process.env.SAFETYNET_BOOKMARK_PROFILE;
require('../apps/browser/main.cjs');
const wait=ms=>new Promise(r=>setTimeout(r,ms)),deadline=setTimeout(()=>app.exit(1),110000);
app.whenReady().then(async()=>{try{
let win;for(let i=0;i<150;i++){win=BrowserWindow.getAllWindows()[0];if(win&&!win.webContents.isLoading()&&win.webContents.getURL().endsWith('index.html'))break;await wait(100);}assert.ok(win);
const call=(name,input)=>win.webContents.executeJavaScript(`window.safetynet[${JSON.stringify(name)}](${JSON.stringify(input)??''})`),state=async()=>(await call('state')).data;
const result=await call('enroll',{server:process.env.SAFETYNET_BOOKMARK_SERVER,code:process.env.SAFETYNET_BOOKMARK_CODE});assert.equal(result.ok,true,result.error);assert.equal(result.data.ready,true);
const id=result.data.deviceId,headers={authorization:`Bearer ${process.env.SAFETYNET_BOOKMARK_ADMIN}`,'content-type':'application/json'},base=process.env.SAFETYNET_BOOKMARK_SERVER;
async function api(route,body,method=body?'POST':'GET'){const r=await fetch(base+route,{method,headers,body:body?JSON.stringify(body):undefined});return {status:r.status,body:await r.json()};}
async function until(fn){for(let i=0;i<200;i++){if(await fn())return;await wait(100);}throw Error('Bookmark refresh timed out');}
async function mutate(action,bookmark){for(let i=0;i<20;i++){const s=await state();const r=await call('mutateBookmarks',{action,bookmark,expectedRevision:s.bookmarks.personal.revision,policyVersion:s.policyVersion});if(r.ok)return r;if(!/Management update in progress/.test(r.error||''))return r;await wait(100);}throw Error('Bookmark mutation unavailable');}
const initial=await state();assert.equal(initial.bookmarks.managed[0].id,'company-intranet');assert.equal(initial.bookmarks.personal.items.length,0);
assert.equal((await mutate('update',{...initial.bookmarks.managed[0],title:'User tamper'})).ok,false);
const personal={id:'personal-fixture',title:'Personal work link',url:process.env.SAFETYNET_BOOKMARK_ORIGIN+'personal',folder:'Work'};const added=await mutate('add',personal);assert.equal(added.ok,true,added.error);assert.equal(added.data.policyVersion,initial.policyVersion);assert.equal(added.data.bookmarks.personal.revision,1);
let adminRead=await api(`/api/admin/devices/${id}/bookmarks`);assert.equal(adminRead.status,200);assert.equal(adminRead.body.items[0].title,personal.title);
const otherCode=(await api('/api/admin/enrollments',{user:'public-other-user'})).body.code;
const other=(await api('/api/device/enroll',{code:otherCode,name:'Public other device',platform:'win32'})).body;
const edited={...personal,title:'Administrator edited work link',url:process.env.SAFETYNET_BOOKMARK_ORIGIN+'admin-edited'};const changed=await api(`/api/admin/devices/${id}/bookmarks`,{expectedRevision:adminRead.body.revision,policyVersion:initial.policyVersion,items:[edited]},'PUT');assert.equal(changed.status,200);
await until(async()=>{const s=await state();return s.ready&&s.bookmarks.personal.revision===2;});assert.equal((await state()).policyVersion,initial.policyVersion);assert.equal((await state()).bookmarks.personal.items[0].title,edited.title);
const otherBookmarks=await api(`/api/admin/devices/${other.id}/bookmarks`);assert.equal(otherBookmarks.status,200);assert.deepEqual(otherBookmarks.body.items,[]);assert.equal(otherBookmarks.body.revision,0);
const ui=await win.webContents.executeJavaScript("({company:document.getElementById('library-company')?.textContent,personal:document.getElementById('library-bookmarks')?.textContent})");assert.ok(JSON.stringify(ui).includes(edited.title),'Live authoritative bookmark missing from UI');
async function publish(mutator){const current=(await api('/api/admin/overview')).body.policy;mutator(current);current.version++;assert.equal((await api('/api/admin/policy',current,'PUT')).status,200);await until(async()=>{const s=await state();return s.ready&&s.policyVersion===current.version;});return current.version;}
const lockedVersion=await publish(p=>{p.browser.bookmarks.allowUserAdd=false;p.browser.bookmarks.allowUserEdit=false;p.browser.bookmarks.allowUserDelete=false;});assert.equal((await mutate('update',personal)).ok,false);const s=await state();assert.equal((await call('mutateBookmarks',{action:'delete',id:personal.id,expectedRevision:s.bookmarks.personal.revision,policyVersion:lockedVersion})).ok,false);
adminRead=await api(`/api/admin/devices/${id}/bookmarks`);assert.equal((await api(`/api/admin/devices/${id}/bookmarks`,{expectedRevision:adminRead.body.revision,policyVersion:lockedVersion,items:[]},'PUT')).status,200);await until(async()=>(await state()).bookmarks.personal.revision===3);
await publish(p=>p.browser.settings.visible=false);assert.equal((await state()).bookmarks.managed[0].id,'company-intranet','Hiding settings removed required company links');assert.equal((await state()).bookmarks.allowUserAdd,false);
await publish(p=>p.browser.bookmarks.adminReadUserBookmarks=false);assert.equal((await api(`/api/admin/devices/${id}/bookmarks`)).status,403);assert.equal((await api(`/api/admin/devices/${id}/bookmarks`,{expectedRevision:3,policyVersion:(await state()).policyVersion,items:[personal]},'PUT')).status,403);
const events=(await api('/api/admin/overview')).body.events;assert.equal(JSON.stringify(events).includes(edited.title),false);assert.equal(JSON.stringify(events).includes(personal.url),false);
console.log(JSON.stringify({nativeBookmarks:true,managedReadOnly:true,personalRemoteEdit:true,revisionStablePolicy:true,permissionLocks:true}));clearTimeout(deadline);app.quit();
}catch(error){console.error(JSON.stringify({nativeBookmarks:false,error:error.message}));clearTimeout(deadline);app.exit(1);}});
+22
View File
@@ -0,0 +1,22 @@
import assert from 'node:assert/strict';
import {createRequire} from 'node:module';
import {createServer} from 'node:http';
import {mkdtempSync,mkdirSync,writeFileSync} from 'node:fs';
import {tmpdir} from 'node:os';
import {join} from 'node:path';
import {spawn} from 'node:child_process';
import {randomBytes} from 'node:crypto';
import {createApp} from '../apps/server/app.mjs';
import {openStore,digest} from '../apps/server/store.mjs';
const temporary=mkdtempSync(join(tmpdir(),'safetynet-bookmarks-')),electron=createRequire(import.meta.url)('electron');
let store,management,sink,child;
try{
const admin=randomBytes(32).toString('base64url'),code=randomBytes(32).toString('base64url');
sink=createServer((_req,res)=>res.end('<!doctype html><title>Public bookmark fixture</title><h1>Public company intranet fixture</h1>')).listen(0,'127.0.0.1');await new Promise(r=>sink.once('listening',r));
store=openStore(join(temporary,'db'));const policy=store.get('policy');policy.browser.homeUrl=`http://127.0.0.1:${sink.address().port}/`;policy.browser.allowedHosts=['127.0.0.1'];policy.browser.bookmarks.managed=[{id:'company-intranet',title:'Company intranet',url:policy.browser.homeUrl+'intranet',folder:'Company'}];store.put('policy',policy);
store.db.prepare('INSERT INTO enrollments VALUES(?,?,?)').run(digest(code),Date.now()+60000,'public-bookmark-user');
const config={publicUrl:'http://127.0.0.1',secure:false,adminToken:admin,requirePQManagement:true};management=createApp(store,config).listen(0,'127.0.0.1');await new Promise(r=>management.once('listening',r));config.publicUrl=`http://127.0.0.1:${management.address().port}`;
const env={...process.env,SAFETYNET_BOOKMARK_PROFILE:join(temporary,'browser'),SAFETYNET_BOOKMARK_SERVER:config.publicUrl,SAFETYNET_BOOKMARK_ADMIN:admin,SAFETYNET_BOOKMARK_CODE:code,SAFETYNET_BOOKMARK_ORIGIN:policy.browser.homeUrl};delete env.ELECTRON_RUN_AS_NODE;
child=spawn(electron,['scripts/bookmarks-browser-smoke.cjs'],{windowsHide:true,stdio:'inherit',env});const timer=setTimeout(()=>child.kill(),120000);const status=await new Promise(r=>{child.once('exit',code=>r(code??1));child.once('error',()=>r(1));});clearTimeout(timer);assert.equal(status,0,'Native bookmarks proof failed');
const report={native:true,companyBookmarksReadOnly:true,personalSynced:true,administratorRemoteEdit:true,deviceRevisionIsolated:true,policyVersionStableOnPersonalEdit:true,remotePermissionsEnforced:true,adminReadPermissionEnforced:true};mkdirSync('artifacts',{recursive:true});writeFileSync('artifacts/bookmarks-browser-proof.json',JSON.stringify(report,null,2));console.log(JSON.stringify(report));
}finally{child?.kill();for(const server of [management,sink])if(server){server.closeAllConnections();await new Promise(r=>server.close(r));}store?.db.close();}
+7
View File
@@ -0,0 +1,7 @@
import { spawn } from 'node:child_process';
import { createRequire } from 'node:module';
const electron=createRequire(import.meta.url)('electron');
const env={...process.env};
for(const name of ['ADMIN_TOKEN','OIDC_CLIENT_SECRET','AI_API_KEY','INSPECTOR_TOKEN','SIEM_HTTP_TOKEN','SIEM_KEY_FILE'])delete env[name];
const child=spawn(electron,['.'],{stdio:'inherit',env,windowsHide:true});child.on('exit',code=>process.exit(code??1));
process.on('SIGINT',()=>child.kill());process.on('SIGTERM',()=>child.kill());
+7
View File
@@ -0,0 +1,7 @@
import { readdirSync } from 'node:fs';
import { join } from 'node:path';
import { spawnSync } from 'node:child_process';
let failed=false;
function walk(dir){for(const entry of readdirSync(dir,{withFileTypes:true})){const p=join(dir,entry.name);if(entry.isDirectory())walk(p);else if(/\.(mjs|cjs|js)$/.test(p)){const result=spawnSync(process.execPath,['--check',p],{encoding:'utf8'});if(result.status!==0){console.error(result.stderr);failed=true;}}}}
for(const directory of ['apps','packages','scripts','tests'])walk(directory);
if(failed)process.exit(1);console.log('All JavaScript syntax checks passed.');
+19
View File
@@ -0,0 +1,19 @@
'use strict';
if(!process.versions.electron){const {spawnSync}=require('node:child_process');const env={...process.env};delete env.ELECTRON_RUN_AS_NODE;const r=spawnSync(require('electron'),[__filename],{env,stdio:'inherit',windowsHide:true,timeout:20000});process.exit(r.status??1);}
else{
const {app,BrowserWindow,WebContentsView,clipboard,ClipboardItem}=require('electron');const {attachPageClipboardGuard,disposePageClipboardGuard}=require('../apps/browser/page-clipboard-guard.cjs');
app.enableSandbox();app.disableHardwareAcceleration();
app.whenReady().then(async()=>{let win,view,original;try{
win=new BrowserWindow({show:false});view=new WebContentsView({webPreferences:{sandbox:true,contextIsolation:true,nodeIntegration:false}});win.contentView.addChildView(view);await view.webContents.loadURL('about:blank');
let failed=false;await attachPageClipboardGuard(view.webContents,()=>{failed=true;});
await new Promise(resolve=>{view.webContents.once('devtools-opened',resolve);view.webContents.openDevTools({mode:'detach',activate:false});});
await new Promise(r=>setTimeout(r,500));
original=[];for(const item of await clipboard.read()){const data={};for(const type of item.types)data[type]=await item.getType(type);if(Object.keys(data).length)original.push(new ClipboardItem(data));}
const sentinel='SYNTHETIC_DEVTOOLS_DLP_BYPASS_PROBE';await clipboard.writeText('Public probe sentinel');
const front=view.webContents.devToolsWebContents;
const host=await front.executeJavaScript(`(()=>{if(typeof InspectorFrontendHost==='undefined'||typeof InspectorFrontendHost.copyText!=='function')return false;InspectorFrontendHost.copyText(${JSON.stringify(sentinel)});return true;})()`);
await new Promise(r=>setTimeout(r,200));
const result={devToolsOpened:view.webContents.isDevToolsOpened(),privateDebuggerAttached:view.webContents.debugger.isAttached(),guardFailure:failed,nativeFrontendCopyAvailable:host,frontendCopyBypassesSiteGuard:await clipboard.readText()===sentinel};
require('node:fs').writeFileSync('artifacts/devtools-privilege-probe.json',JSON.stringify(result,null,2));console.log(JSON.stringify(result));
}catch(e){console.error(e.message);process.exitCode=1;}finally{if(original!==undefined)await clipboard.write(original);if(view&&!view.webContents.isDestroyed()){disposePageClipboardGuard(view.webContents);view.webContents.closeDevTools();view.webContents.close({waitForBeforeUnload:false});}win?.destroy();app.exit(process.exitCode||0);}});
}
+16
View File
@@ -0,0 +1,16 @@
'use strict';
const {app,BrowserWindow,webContents}=require('electron'),assert=require('node:assert/strict'),fs=require('node:fs');const {disposePageClipboardGuard}=require('../apps/browser/page-clipboard-guard.cjs');
app.setPath('userData',process.env.SAFETYNET_DEVTOOLS_USERDATA);app.disableHardwareAcceleration();require('../apps/browser/main.cjs');const wait=ms=>new Promise(r=>setTimeout(r,ms));async function until(fn,label){for(let i=0;i<200;i++){if(await fn())return;await wait(100);}throw Error(label+' timed out');}
app.whenReady().then(async()=>{let win;try{
await until(()=>{win=BrowserWindow.getAllWindows()[0];return win&&!win.webContents.isLoading()&&win.webContents.getURL().endsWith('index.html');},'Shell');const call=async(name,arg)=>{const result=await win.webContents.executeJavaScript(`window.safetynet[${JSON.stringify(name)}](${JSON.stringify(arg)})`);assert.equal(result.ok,true,result.error);return result.data;};const state=()=>call('state');
await call('enroll',{server:process.env.SAFETYNET_DEVTOOLS_SERVER,code:process.env.SAFETYNET_DEVTOOLS_CODE});let page;await until(()=>{page=webContents.getAllWebContents().find(w=>w.getURL().startsWith(process.env.SAFETYNET_DEVTOOLS_SINK));return page&&!page.isLoading();},'Managed page');
const toolsOpened=()=>BrowserWindow.getAllWindows().some(w=>w!==win&&w.isVisible()&&!w.webContents.isLoading()&&w.webContents.getURL().startsWith('devtools://devtools/bundled/'));const key=async(code,modifiers=[])=>{page.focus();page.sendInputEvent({type:'keyDown',keyCode:code,modifiers});page.sendInputEvent({type:'keyUp',keyCode:code,modifiers});await wait(300);};
await key('F12');assert.equal(toolsOpened(),false,'Default policy opened DevTools');
const api=async(path,method,body)=>{const r=await fetch(process.env.SAFETYNET_DEVTOOLS_SERVER+path,{method,headers:{authorization:`Bearer ${process.env.SAFETYNET_DEVTOOLS_ADMIN}`,'content-type':'application/json'},body:JSON.stringify(body)});assert.equal(r.status,200);return r.json();};
await api('/api/admin/user-profile-configuration','PUT',{expectedVersion:1,categories:[],delegation:{devTools:true}});await api('/api/admin/user-profiles/developer','PUT',{expectedVersion:2,profile:{id:'developer',name:'Developer',deviceIds:[(await state()).deviceId],features:{devTools:'allow'}}});
await until(async()=>{const s=await state();return s.ready&&s.policyVersion===3&&!page.isLoading();},'Signed developer grant');
await key('F12');await until(()=>toolsOpened(),'Granted F12');assert.equal(page.debugger.isAttached(),true,'DevTools detached site security guard');assert.equal(win.webContents.isDevToolsOpened(),false,'Trusted chrome DevTools opened');
await key('F12');await until(()=>!toolsOpened(),'F12 close');await key('I',['control','shift']);await until(()=>toolsOpened(),'Granted CtrlShiftI');
await api('/api/admin/user-profiles/developer','DELETE',{expectedVersion:3});await until(async()=>{const s=await state();return s.policyVersion===4&&s.ready&&!toolsOpened();},'Live developer grant revocation');await key('F12');assert.equal(toolsOpened(),false,'Revoked developer grant reopened tools');assert.equal(page.debugger.isAttached(),true);
fs.mkdirSync('artifacts',{recursive:true});fs.writeFileSync('artifacts/devtools-profile-proof.json',JSON.stringify({actualNativeShortcut:true,defaultDenied:true,centralSignedProfileGranted:true,f12Opened:true,ctrlShiftIOpened:true,privateClipboardGuardRetained:true,trustedChromeToolsDenied:true,liveProfileRevocationClosed:true,revokedCannotReopen:true},null,2));console.log('Native developer profile deny/grant/revocation proof passed.');
}catch(error){console.error(error.message);process.exitCode=1;}finally{for(const contents of webContents.getAllWebContents())if(contents!==win?.webContents&&!contents.isDestroyed())disposePageClipboardGuard(contents);app.exit(process.exitCode||0);}});
+8
View File
@@ -0,0 +1,8 @@
import assert from 'node:assert/strict';import {createServer} from 'node:http';import {createRequire} from 'node:module';import {mkdtempSync,rmSync} from 'node:fs';import {tmpdir} from 'node:os';import {join,resolve,sep,basename} from 'node:path';import {spawn} from 'node:child_process';import {randomBytes} from 'node:crypto';import {createApp} from '../apps/server/app.mjs';import {openStore,digest} from '../apps/server/store.mjs';
const require=createRequire(import.meta.url),directory=mkdtempSync(join(tmpdir(),'safetynet-devtools-proof-'));let sink,server,store,child;
try{
sink=createServer((_req,res)=>{res.setHeader('content-type','text/html');res.end('<!doctype html><title>Developer fixture</title><h1>Synthetic developer page</h1>');}).listen(0,'127.0.0.1');await new Promise(r=>sink.once('listening',r));const sinkUrl=`http://127.0.0.1:${sink.address().port}`;
store=openStore(join(directory,'management'));const policy=store.get('policy');policy.browser.homeUrl=sinkUrl;policy.browser.allowedHosts=['127.0.0.1'];store.put('policy',policy);const code=randomBytes(32).toString('base64url'),adminToken=randomBytes(32).toString('base64url');store.db.prepare('INSERT INTO enrollments VALUES(?,?,?)').run(digest(code),Date.now()+600000,'synthetic-developer');const config={adminToken,publicUrl:'http://127.0.0.1',secure:false};server=createApp(store,config).listen(0,'127.0.0.1');await new Promise(r=>server.once('listening',r));config.publicUrl=`http://127.0.0.1:${server.address().port}`;
const env={...process.env,SAFETYNET_DEVTOOLS_SERVER:config.publicUrl,SAFETYNET_DEVTOOLS_CODE:code,SAFETYNET_DEVTOOLS_ADMIN:adminToken,SAFETYNET_DEVTOOLS_SINK:sinkUrl,SAFETYNET_DEVTOOLS_USERDATA:join(directory,'browser'),SAFETYNET_SMOKE_USERDATA:join(directory,'browser')};delete env.ELECTRON_RUN_AS_NODE;
child=spawn(require('electron'),['scripts/devtools-profile-smoke.cjs'],{env,windowsHide:true,stdio:['ignore','pipe','pipe']});child.stdout.on('data',b=>process.stdout.write(b));child.stderr.on('data',b=>process.stderr.write(String(b).replaceAll(code,'[fixture enrollment]').replaceAll(adminToken,'[fixture admin]')));const timer=setTimeout(()=>child.kill(),90000);const exit=await new Promise(r=>{child.once('exit',c=>r(c??1));child.once('error',()=>r(1));});clearTimeout(timer);assert.equal(exit,0,'Native developer-profile proof failed');
}finally{child?.kill();for(const service of [server,sink])if(service)await new Promise(r=>{service.closeAllConnections();service.close(r);});store?.db.close();const target=resolve(directory);if(!target.startsWith(resolve(tmpdir())+sep)||!basename(target).startsWith('safetynet-devtools-proof-'))throw Error('Unsafe fixture cleanup');rmSync(target,{recursive:true,force:true,maxRetries:10,retryDelay:100});}
+284
View File
@@ -0,0 +1,284 @@
const {app,BrowserWindow}=require('electron');
const fs=require('node:fs'),path=require('node:path'),assert=require('node:assert/strict');
fs.writeFileSync(path.join(process.env.SAFETYNET_SMOKE_ARTIFACTS,'smoke-entry.txt'),'Electron JavaScript started.\n');
app.setPath('userData',process.env.SAFETYNET_SMOKE_USERDATA);
app.disableHardwareAcceleration();
require('../apps/browser/main.cjs');
const wait=ms=>new Promise(r=>setTimeout(r,ms));
const log=message=>fs.appendFileSync(path.join(process.env.SAFETYNET_SMOKE_ARTIFACTS,'smoke-entry.txt'),message+'\n');
app.whenReady().then(async()=>{
try{
fs.appendFileSync(path.join(process.env.SAFETYNET_SMOKE_ARTIFACTS,'smoke-entry.txt'),'Electron ready.\n');
let win;
for(let n=0;n<100;n++){win=BrowserWindow.getAllWindows()[0];if(win&&!win.webContents.isLoading()&&win.webContents.getURL().endsWith('index.html'))break;await wait(100);}
await wait(300);
log('Reading initial shell state: '+win.webContents.getURL());
const initial=await win.webContents.executeJavaScript('window.safetynet.state()');assert.equal(initial.data.ready,false);
assert.equal((await win.webContents.executeJavaScript('window.safetynet.vaultCreate("fixture-master-password-only")')).ok,false,'Unenrolled vault access was allowed');
log('Starting enrollment');
const input={server:process.env.SAFETYNET_SMOKE_SERVER,code:process.env.SAFETYNET_SMOKE_CODE};
const result=await win.webContents.executeJavaScript(`window.safetynet.enroll(${JSON.stringify(input)})`);assert.equal(result.ok,true,result.error);assert.equal(result.data.ready,true);assert.equal(result.data.brand.name,'Acme Secure Browser');
await wait(600);
log('Enrollment passed; testing managed page');
const page=win.contentView.children.find(v=>v.webContents!==win.webContents).webContents;
log('Managed page URL: '+page.getURL());
const url=process.env.SAFETYNET_SMOKE_SINK;
const publicResult=await page.executeJavaScript(`fetch(${JSON.stringify(url+'/sink')},{method:'POST',body:'Public information'}).then(r=>r.text()).catch(e=>({error:e.message}))`);
log('Public request: '+JSON.stringify(publicResult));assert.equal(publicResult,'received');
const blocked=await page.executeJavaScript(`fetch(${JSON.stringify(url+'/sink')},{method:'POST',body:'Secret Roadmap'}).then(()=>false).catch(()=>true)`);assert.equal(blocked,true);
const counts=await (await fetch(url+'/count')).json();assert.equal(counts.posts,1,'Secret payload reached the destination');
log('Request blocking passed');
// Real Chromium gestures and the Windows clipboard: never execute fixture commands.
const {clipboard}=require('electron');
const originalClipboardText=await clipboard.readText();
const clipboardSentinel='SafetyNet public clipboard fixture';
async function clipboardKey(key,shift=false){page.focus();page.sendInputEvent({type:'keyDown',keyCode:key,modifiers:shift?['shift']:['control']});page.sendInputEvent({type:'keyUp',keyCode:key,modifiers:shift?['shift']:['control']});await wait(800);await clipboardWait(async()=>!(await win.webContents.executeJavaScript('window.safetynet.state()')).data.clipboardPending);}
async function clipboardWait(predicate){for(let attempt=0;attempt<200;attempt++){if(await predicate())return;await wait(100);}throw Error('Clipboard fixture operation timed out');}
async function selectClipboardText(text){await page.executeJavaScript(`(()=>{let node=document.getElementById('clipboard-source');if(!node){node=document.createElement('pre');node.id='clipboard-source';document.body.append(node)}node.textContent=${JSON.stringify(text)};const range=document.createRange();range.selectNodeContents(node);const selection=getSelection();selection.removeAllRanges();selection.addRange(range);})()`);}
try{
await clipboard.writeText(clipboardSentinel);
await selectClipboardText('Public code example');await clipboardKey('C');
await clipboardWait(async()=>await clipboard.readText()==='Public code example');
assert.equal(await clipboard.readText(),'Public code example','Allowed native copy failed');
await clipboard.writeText(clipboardSentinel);await selectClipboardText('Secret Roadmap');await clipboardKey('C');
assert.equal(await clipboard.readText(),clipboardSentinel,'Blocked secret reached OS clipboard');
await selectClipboardText('powershell -NoProfile -EncodedCommand VABFAFMAVAA=');await clipboardKey('C');
assert.equal(await clipboard.readText(),clipboardSentinel,'ClickFix command reached OS clipboard');
await selectClipboardText('SAFETYNET_BLOCK_TEST');await clipboardKey('C');
assert.equal(await clipboard.readText(),clipboardSentinel,'YARA-blocked clipboard text reached OS clipboard');
await page.executeJavaScript("document.addEventListener('copy',event=>{event.clipboardData.setData('text/plain','Secret Roadmap');event.preventDefault()},{once:true})");
await selectClipboardText('Public selection despite hostile copy handler');await clipboardKey('C');
assert.equal((await clipboard.readText()).includes('Secret Roadmap'),false,'Page copy handler bypassed inspection');
await clipboard.writeText(clipboardSentinel);
await page.executeJavaScript("(()=>{const e=document.getElementById('public-input');e.value='';e.focus()})()");await clipboardKey('V');
await clipboardWait(async()=>await page.executeJavaScript('document.getElementById("public-input").value')===clipboardSentinel);
assert.equal(await page.executeJavaScript('document.getElementById("public-input").value'),clipboardSentinel,'Allowed native paste failed');
await clipboard.writeText('Secret Roadmap');await clipboardKey('V');
assert.equal(await page.executeJavaScript('document.getElementById("public-input").value'),clipboardSentinel,'Secret was inserted by native paste');
await page.executeJavaScript("(()=>{const e=document.getElementById('public-input');e.value='Secret Roadmap';e.focus();e.select()})()");await clipboard.writeText(clipboardSentinel);await clipboardKey('X');
assert.equal(await clipboard.readText(),clipboardSentinel,'Blocked cut wrote OS clipboard');assert.equal(await page.executeJavaScript('document.getElementById("public-input").value'),'Secret Roadmap','Blocked cut deleted source');
await page.executeJavaScript("(()=>{const e=document.getElementById('public-input');e.value='Public cut sample';e.focus();e.select()})()");await clipboardKey('Delete',true);
assert.equal(await clipboard.readText(),'Public cut sample','Allowed Shift+Delete cut failed');assert.equal(await page.executeJavaScript('document.getElementById("public-input").value'),'','Allowed cut preserved deleted selection');
await clipboardKey('Insert',true);
assert.equal(await page.executeJavaScript('document.getElementById("public-input").value'),'Public cut sample','Allowed Shift+Insert paste failed');
await clipboard.writeText(clipboardSentinel);
// Programmatic legacy copy must not acquire the native user gesture capability.
await selectClipboardText('Secret Roadmap');await page.executeJavaScript("document.execCommand('copy')",true);await wait(250);
assert.equal(await clipboard.readText(),clipboardSentinel,'Legacy scripted copy bypassed clipboard gate');
const clipboardEvents=(await (await fetch(`${process.env.SAFETYNET_SMOKE_SERVER}/api/admin/overview`,{headers:{authorization:`Bearer ${process.env.SAFETYNET_SMOKE_ADMIN}`}})).json()).events.filter(event=>event.kind.startsWith('clipboard.'));
assert.ok(clipboardEvents.some(event=>event.kind==='clipboard.block'),'Clipboard blocks were not centrally audited');
assert.equal(JSON.stringify(clipboardEvents).includes('Secret Roadmap'),false,'Clipboard contents appeared in audit records');
assert.equal(JSON.stringify(clipboardEvents).includes('VABFAFMAVAA='),false,'Command contents appeared in audit records');
log('Native clipboard: safe copy/paste allowed, confidential copy/paste/cut held, ClickFix execution command and hostile copy handler blocked');
}finally{await clipboard.writeText(originalClipboardText);await page.executeJavaScript("document.getElementById('clipboard-source')?.remove();document.getElementById('public-input').value=''");}
const connection=await win.webContents.executeJavaScript('window.safetynet.agentConnection()');assert.equal(connection.ok,true,connection.error);
const agentRequest=path.join(process.env.SAFETYNET_SMOKE_USERDATA,'agent-request.json');
async function localAgent(body){
fs.writeFileSync(agentRequest,JSON.stringify(body));
const child=require('node:child_process').spawn(process.execPath,['scripts/agent-client.cjs','--connection',connection.data.credentialPath,'--request',agentRequest],{stdio:['ignore','pipe','pipe'],windowsHide:true});let output='',errors='';child.stdout.on('data',c=>output+=c);child.stderr.on('data',c=>errors+=c);
const exit=await new Promise((resolve,reject)=>{child.on('exit',resolve);child.on('error',reject);});return {exit,output,errors};
}
const sessionResult=await localAgent({action:'sessions'});assert.equal(sessionResult.exit,0,sessionResult.errors);const sessionId=JSON.parse(sessionResult.output).result[0].id;assert.match(sessionId,/^[0-9a-f-]{36}$/i);assert.equal(sessionId,(await win.webContents.executeJavaScript('window.safetynet.state()')).data.activeTabId);
const readResult=await localAgent({action:'read',args:{sessionId}});assert.equal(readResult.exit,0,readResult.errors);assert.equal(readResult.output.includes('never-export-this'),false);
const typeResult=await localAgent({action:'type',args:{sessionId,selector:'#public-input',text:'Agent typed public text'}});assert.equal(typeResult.exit,0,typeResult.errors);assert.equal(await page.executeJavaScript('document.getElementById("public-input").value'),'Agent typed public text');
const deniedType=await localAgent({action:'type',args:{sessionId,selector:'#private-input',text:'forbidden'}});assert.equal(deniedType.exit,1);
log('Authenticated agent sessions, sanitized read, type and sensitive-field denial passed');
async function agentApp(action,args={}){const response=await localAgent({action,args});assert.equal(response.exit,0,response.errors);return JSON.parse(response.output).result;}
const appStatus=await agentApp('application:state');assert.equal(appStatus.activeTabId,sessionId);
await agentApp('settings:update',{appearance:{mode:'dark'}});assert.equal((await agentApp('settings:get')).appearance.mode,'dark');
const library=await agentApp('bookmarks:list');const bookmark={id:'agent-native-proof',title:'Public fixture bookmark',url:url+'/'};
await agentApp('bookmarks:mutate',{action:'add',bookmark,expectedRevision:library.personal.revision,policyVersion:library.policyVersion});
const updatedLibrary=await agentApp('bookmarks:list');assert.equal(updatedLibrary.personal.items.some(item=>item.id===bookmark.id),true);
await agentApp('bookmarks:mutate',{action:'delete',id:bookmark.id,expectedRevision:updatedLibrary.personal.revision,policyVersion:updatedLibrary.policyVersion});
const createdTab=await agentApp('tabs:create',{group:'Agent proof'});assert.notEqual(createdTab.sessionId,sessionId);
await agentApp('tabs:group',{sessionId:createdTab.sessionId,group:'Public work'});
await agentApp('tabs:activate',{sessionId});await agentApp('tabs:close',{sessionId:createdTab.sessionId});
assert.equal((await agentApp('application:state')).activeTabId,sessionId);
log('First-class agent settings, centrally revisioned bookmarks and native tab controls passed');
const fixtureMaster='fixture-master-password-for-smoke-only';
assert.equal((await win.webContents.executeJavaScript(`window.safetynet.vaultCreate(${JSON.stringify(fixtureMaster)})`)).ok,true);
const generated=await win.webContents.executeJavaScript('window.safetynet.vaultGenerate()');assert.equal(generated.ok,true);assert.equal(generated.data.length,32);
const login={origin:'https://vault-login.test',label:'Fixture login',username:'fixture-user',password:generated.data};
const saved=await win.webContents.executeJavaScript(`window.safetynet.vaultSave(${JSON.stringify(login)})`);assert.equal(saved.ok,true);
const listed=await win.webContents.executeJavaScript('window.safetynet.vaultList()');assert.equal(listed.ok,true);assert.equal(listed.data[0].password,undefined);
const encryptedVault=fs.readFileSync(path.join(process.env.SAFETYNET_SMOKE_USERDATA,'password-vault.json'),'utf8');assert.equal(encryptedVault.includes(login.password),false);assert.equal(encryptedVault.includes(login.username),false);assert.equal(encryptedVault.includes(fixtureMaster),false);
assert.equal((await win.webContents.executeJavaScript(`window.safetynet.vaultFill(${JSON.stringify(saved.data.id)})`)).ok,false,'HTTP page accepted vault fill');
// Protocol fixture exercises Chromium's actual isolated DOM fill; production TLS remains mandatory.
await page.session.protocol.handle('https',request=>{if(new URL(request.url).origin!==login.origin)throw Error('Unexpected fixture origin');return new Response('<!doctype html><title>Vault login fixture</title><form method="post" action="/signin"><label>Username<input id="login-user" name="username" autocomplete="username"></label><label>Password<input id="login-password" type="password" autocomplete="current-password"></label><button type="submit">Sign in</button></form>',{headers:{'content-type':'text/html'}});});
try{
assert.equal((await win.webContents.executeJavaScript('window.safetynet.navigate("https://vault-login.test/login")')).ok,true);
const beforeScriptedClipboard=await clipboard.readText();
try{
await clipboard.writeText(clipboardSentinel);
const scriptWrite=await Promise.race([page.executeJavaScript("navigator.clipboard.writeText('Hidden page clipboard replacement').then(()=>true).catch(()=>false)",true),wait(3000).then(()=>false)]);
assert.equal(scriptWrite,false,'Secure page acquired unguarded Clipboard API write');
assert.equal(await clipboard.readText(),clipboardSentinel,'Secure page overwrote OS clipboard through Clipboard API');
await page.executeJavaScript("(()=>{const frame=document.createElement('iframe');frame.id='clipboard-child';frame.srcdoc='<p id=selected>Secret Roadmap</p>';document.body.append(frame)})()");await wait(350);
const childCapabilities=await page.executeJavaScript("(()=>{const child=document.getElementById('clipboard-child').contentWindow;return [typeof child.require,typeof child.process,typeof child.safetynet]})()");
assert.deepEqual(childCapabilities,['undefined','undefined','undefined'],'Child frame obtained Node or browser bridge capabilities');
assert.equal(page.getLastWebPreferences().sandbox,true,'Managed renderer sandbox was disabled');
await page.executeJavaScript("(()=>{const frame=document.getElementById('clipboard-child');try{const child=frame.contentWindow,d=child.document;if(!d.getElementById('selected'))return;const r=d.createRange();r.selectNodeContents(d.getElementById('selected'));child.getSelection().removeAllRanges();child.getSelection().addRange(r);child.focus();d.execCommand('copy')}catch{}finally{frame.remove()}})()",true);await wait(200);
assert.equal(await clipboard.readText(),clipboardSentinel,'Child frame legacy copy bypassed clipboard protection');
await page.executeJavaScript("(()=>{const frame=document.createElement('iframe');document.body.append(frame);try{const child=frame.contentWindow,d=child.document;d.body.textContent='Secret Roadmap';const r=d.createRange();r.selectNodeContents(d.body);child.getSelection().removeAllRanges();child.getSelection().addRange(r);child.focus();d.execCommand('copy')}finally{frame.remove()}})()",true);await wait(200);
assert.equal(await clipboard.readText(),clipboardSentinel,'Immediate about:blank child copy bypassed clipboard protection');
const childReset=await page.executeJavaScript("(()=>{const frame=document.createElement('iframe');document.body.append(frame);try{const child=frame.contentWindow,d=child.document;d.open();d.write('<p>Secret Roadmap</p>');d.close();const r=d.createRange();r.selectNodeContents(d.body);child.getSelection().removeAllRanges();child.getSelection().addRange(r);child.focus();d.execCommand('copy');return 'reset-completed'}catch(error){return error.name}finally{frame.remove()}})()",true);await wait(200);
assert.equal(childReset,'SecurityError','Child document replacement was not blocked');
assert.equal(await clipboard.readText(),clipboardSentinel,'Document reset bypassed child clipboard protection');
const mainReset=await page.executeJavaScript("(()=>{try{document.open();document.write('<p>Secret Roadmap</p>');document.close();const r=document.createRange();r.selectNodeContents(document.body);getSelection().removeAllRanges();getSelection().addRange(r);document.execCommand('copy');return 'reset-completed'}catch(error){return error.name}})()",true);await wait(200);
assert.equal(mainReset,'SecurityError','Main document replacement was not blocked');
assert.equal(await clipboard.readText(),clipboardSentinel,'Document reset bypassed main-frame clipboard protection');
assert.equal((await win.webContents.executeJavaScript('window.safetynet.navigate("https://vault-login.test/login")')).ok,true);
}finally{await clipboard.writeText(beforeScriptedClipboard);}
assert.equal((await win.webContents.executeJavaScript(`window.safetynet.vaultFill(${JSON.stringify(saved.data.id)})`)).ok,true,'Exact HTTPS origin fill failed');
assert.equal(await page.executeJavaScript('document.getElementById("login-user").value'),login.username);assert.equal(await page.executeJavaScript('document.getElementById("login-password").value'),login.password);
assert.equal(await page.executeJavaScript('typeof window.safetynet'),'undefined','Remote site obtained vault bridge');
await page.executeJavaScript('document.querySelector("form").action="https://different-origin.test/capture"');
assert.equal((await win.webContents.executeJavaScript(`window.safetynet.vaultFill(${JSON.stringify(saved.data.id)})`)).ok,false,'Cross-origin form accepted password');
}finally{await page.session.protocol.unhandle('https');await win.webContents.executeJavaScript(`window.safetynet.navigate(${JSON.stringify(url)})`);}
await win.webContents.executeJavaScript('document.getElementById("passwords").click()');await wait(200);
assert.equal(await win.webContents.executeJavaScript('document.getElementById("vault").hidden'),false);
try{fs.writeFileSync(path.join(process.env.SAFETYNET_SMOKE_ARTIFACTS,'browser-vault.png'),(await win.webContents.capturePage()).toPNG());}catch{log('Vault screenshot unavailable');}
win.emit('blur');await wait(100);assert.equal((await win.webContents.executeJavaScript('window.safetynet.vaultStatus()')).data.locked,true);
assert.equal((await win.webContents.executeJavaScript('window.safetynet.vaultList()')).ok,false);
assert.equal((await win.webContents.executeJavaScript('window.safetynet.vaultUnlock("wrong-fixture-password-only")')).ok,false);
assert.equal((await win.webContents.executeJavaScript(`window.safetynet.vaultUnlock(${JSON.stringify(fixtureMaster)})`)).ok,true);
assert.equal((await win.webContents.executeJavaScript('window.safetynet.vaultList()')).data.length,1);
await win.webContents.executeJavaScript('document.getElementById("vault-close").click()');await wait(100);
log('Real local vault: native ML-KEM, DPAPI, encrypted storage, masked metadata, isolated exact-HTTPS fill, hostile form denial, blur lock and reopen passed');
const {dialog}=require('electron'),originalSave=dialog.showSaveDialog;let saveCalls=0;
dialog.showSaveDialog=async(_win,options)=>{saveCalls++;return {canceled:false,filePath:path.join(process.env.SAFETYNET_SMOKE_USERDATA,path.basename(options.defaultPath))};};
try{
await page.executeJavaScript('document.getElementById("safe-download").click()');
const safeFile=path.join(process.env.SAFETYNET_SMOKE_USERDATA,'safe.bin');for(let n=0;n<600;n++){if(fs.existsSync(safeFile)&&fs.statSync(safeFile).size===5)break;await wait(100);}
assert.equal(fs.existsSync(safeFile),true,'Scanned benign download was not released');assert.deepEqual(fs.readFileSync(safeFile),Buffer.from([0,1,2,3,255]));assert.equal(saveCalls,1);
await page.executeJavaScript('document.getElementById("blocked-download").click()');
for(let n=0;n<300;n++){const s=await win.webContents.executeJavaScript('window.safetynet.state()');if(s.data.message.startsWith('Download blocked:'))break;await wait(100);}
assert.equal(fs.existsSync(path.join(process.env.SAFETYNET_SMOKE_USERDATA,'blocked.bin')),false);assert.equal(saveCalls,1,'Blocked download reached save dialog');
log('Real YARA download gate: safe binary saved; blocked file never reaches save dialog/filesystem');
}finally{dialog.showSaveDialog=originalSave;}
const sample=path.join(process.env.SAFETYNET_SMOKE_USERDATA,'secret-sample.docx');
const runtime=path.resolve('.runtime/windows/python/python.exe');
if(fs.existsSync(runtime)){
const create=require('node:child_process').spawnSync(runtime,['-c','import sys,zipfile; z=zipfile.ZipFile(sys.argv[1],"w"); z.writestr("word/document.xml",\'<document xmlns="urn:test"><t>Secret Roadmap</t></document>\'); z.close()',sample],{encoding:'utf8',windowsHide:true});assert.equal(create.status,0,create.stderr);
const {dialog}=require('electron'),originalChooser=dialog.showOpenDialog;
dialog.showOpenDialog=async()=>({canceled:false,filePaths:[sample]});
try{const inspection=await win.webContents.executeJavaScript('window.safetynet.inspectFile()');assert.equal(inspection.ok,true,inspection.error);assert.equal(inspection.data.ruleId,'secret-roadmap');assert.equal(inspection.data.contentType,'office');}finally{dialog.showOpenDialog=originalChooser;}
log('Bundled local document inspection passed');
}
await page.executeJavaScript(`fetch(${JSON.stringify(url+'/sink')},{method:'POST',body:new Uint8Array([255,254])}).catch(()=>{})`);
assert.equal((await (await fetch(url+'/count')).json()).posts,1,'Binary upload reached the destination');
log('Capturing browser');
try{fs.writeFileSync(path.join(process.env.SAFETYNET_SMOKE_ARTIFACTS,'browser.png'),(await win.webContents.capturePage()).toPNG());}catch(e){log('Screenshot unavailable: '+e.message);}
log('Loading admin console');
const admin=new BrowserWindow({show:false,width:1440,height:1100,webPreferences:{nodeIntegration:false,contextIsolation:true,sandbox:true}});
await admin.loadURL(process.env.SAFETYNET_SMOKE_SERVER);
await admin.webContents.executeJavaScript(`document.getElementById('token').value=${JSON.stringify(process.env.SAFETYNET_SMOKE_ADMIN)};document.getElementById('connect').click();`);
for(let n=0;n<30;n++){if(await admin.webContents.executeJavaScript('!document.getElementById("workspace").hidden'))break;await wait(100);}
assert.equal(await admin.webContents.executeJavaScript('document.getElementById("workspace").hidden'),false);
try{fs.writeFileSync(path.join(process.env.SAFETYNET_SMOKE_ARTIFACTS,'admin.png'),(await admin.webContents.capturePage()).toPNG());}catch(e){log('Screenshot unavailable: '+e.message);}
const headers={authorization:`Bearer ${process.env.SAFETYNET_SMOKE_ADMIN}`,'content-type':'application/json'};
const secondary=process.env.SAFETYNET_SMOKE_SECONDARY;
assert.equal(await page.executeJavaScript(`fetch(${JSON.stringify(secondary)}).then(r=>r.text())`),'secondary');
const beforeDNS=(await (await fetch(url+'/count')).json()).secondaryRequests;
const blocklistUpdate=await fetch(`${process.env.SAFETYNET_SMOKE_SERVER}/api/admin/security/blocklists`,{method:'PUT',headers,body:JSON.stringify({expectedVersion:1,blockedHosts:['blocked.test'],blockedIPs:['127.0.0.2']})});assert.equal(blocklistUpdate.status,200);
for(let n=0;n<200;n++){const updated=await win.webContents.executeJavaScript('window.safetynet.state()');if(updated.data.ready&&updated.data.policyVersion===2)break;await wait(100);}
assert.equal(await page.executeJavaScript(`fetch(${JSON.stringify(secondary)}).then(()=>false).catch(()=>true)`),true);
assert.equal((await (await fetch(url+'/count')).json()).secondaryRequests,beforeDNS,'Blocked IP receiver got the request');log('Live DNS/IP blocklist prevented a previously working destination');
const overview=await (await fetch(`${process.env.SAFETYNET_SMOKE_SERVER}/api/admin/overview`,{headers})).json();
const managedPolicy=overview.policy;managedPolicy.version+=1;managedPolicy.security.dns.blockedIPs=[];managedPolicy.proxy={mode:'fixed_servers',rules:`http=127.0.0.1:${new URL(url).port}`,bypass:''};
const publication=await fetch(`${process.env.SAFETYNET_SMOKE_SERVER}/api/admin/policy`,{method:'PUT',headers,body:JSON.stringify(managedPolicy)});assert.equal(publication.status,200);
for(let n=0;n<180;n++){const updated=await win.webContents.executeJavaScript('window.safetynet.state()');if(updated.data.ready&&updated.data.policyVersion===3)break;await wait(100);}
const navigation=await win.webContents.executeJavaScript(`window.safetynet.navigate('http://proxy-check.invalid/')`);assert.equal(navigation.ok,true,navigation.error);
assert.ok((await (await fetch(url+'/count')).json()).proxyRequests>0,'Managed proxy did not receive browser navigation');log('Managed proxy enforcement passed');
const reference='The confidential engineering roadmap contains restricted architecture budgets and unreleased customer contracts.';
const draftResponse=await fetch(`${process.env.SAFETYNET_SMOKE_SERVER}/api/admin/teaching`,{method:'POST',headers,body:JSON.stringify({label:'Internal engineering reference',filename:'internal.txt',data:Buffer.from(reference).toString('base64')})});assert.equal(draftResponse.status,200);
const draft=await draftResponse.json();assert.equal(draft.status,'draft');assert.ok(draft.reference.fragmentHashes.length>0);
const publicationResponse=await fetch(`${process.env.SAFETYNET_SMOKE_SERVER}/api/admin/teaching/${draft.id}/publish`,{method:'POST',headers,body:JSON.stringify({expectedVersion:3,approve:true})});assert.equal(publicationResponse.status,200);
for(let n=0;n<200;n++){const updated=await win.webContents.executeJavaScript('window.safetynet.state()');if(updated.data.ready&&updated.data.policyVersion===4)break;await wait(100);}
await page.executeJavaScript("fetch('/sink',{method:'POST',body:'Public text after teaching'}).then(r=>r.text())");
const beforeExcerpt=(await (await fetch(url+'/count')).json()).posts;
const excerpt='Public preface: engineering roadmap contains restricted architecture budgets and unreleased customer contracts. Public appendix.';
assert.equal(await page.executeJavaScript(`fetch('/sink',{method:'POST',body:${JSON.stringify(excerpt)}}).then(()=>false).catch(()=>true)`),true);
assert.equal((await (await fetch(url+'/count')).json()).posts,beforeExcerpt,'Registered confidential excerpt reached external receiver');
log('Governed document teaching published signed fragment rules and blocked an altered excerpt before transmission');
for(const [enabled,version] of [[false,5],[true,6]]){
const toggle=await fetch(`${process.env.SAFETYNET_SMOKE_SERVER}/api/admin/devices/${result.data.deviceId}/inspection`,{method:'PATCH',headers,body:JSON.stringify({expectedVersion:version-1,documentAnalysisEnabled:enabled})});assert.equal(toggle.status,200);
for(let n=0;n<200;n++){const s=await win.webContents.executeJavaScript('window.safetynet.state()');if(s.data.ready&&s.data.policyVersion===version)break;await wait(100);}
const scanState=await win.webContents.executeJavaScript('window.safetynet.state()');assert.equal(scanState.data.documentScanEnabled,enabled);
if(!enabled){const scan=await win.webContents.executeJavaScript('window.safetynet.inspectFile()');assert.equal(scan.ok,false);assert.match(scan.error,/disabled/);assert.equal(await page.executeJavaScript(`fetch('/sink',{method:'POST',body:'Secret Roadmap'}).then(()=>false).catch(()=>true)`),true);}
}
log('Signed per-browser document-analysis switch changed manual scanning without disabling mandatory DLP');
const displayPolicy=(await (await fetch(`${process.env.SAFETYNET_SMOKE_SERVER}/api/admin/overview`,{headers})).json()).policy;
displayPolicy.version+=1;displayPolicy.security.content.blockedPhrases=['restricted-display-marker'];
const displayPublication=await fetch(`${process.env.SAFETYNET_SMOKE_SERVER}/api/admin/policy`,{method:'PUT',headers,body:JSON.stringify(displayPolicy)});assert.equal(displayPublication.status,200);
for(let n=0;n<200;n++){const updated=await win.webContents.executeJavaScript('window.safetynet.state()');if(updated.data.ready&&updated.data.policyVersion===7)break;await wait(100);}
await page.executeJavaScript("document.body.append('restricted-display-marker')");
for(let n=0;n<50;n++){const s=await win.webContents.executeJavaScript('window.safetynet.state()');if(!s.data.ready)break;await wait(100);}
const contentState=await win.webContents.executeJavaScript('window.safetynet.state()');assert.equal(contentState.data.ready,false);assert.equal(contentState.data.message,'This page contains content blocked by company policy.');
assert.equal((await win.webContents.executeJavaScript(`window.safetynet.navigate(${JSON.stringify(page.getURL()+'#same-document')})`)).ok,false,'Hash-only navigation escaped content quarantine');
assert.equal((await win.webContents.executeJavaScript('window.safetynet.navigate("wss://example.test/")')).ok,false,'Unsupported navigation cleared quarantine');
assert.equal((await win.webContents.executeJavaScript('window.safetynet.state()')).data.ready,false);
log('Live signed content rule quarantined a changed document through isolated preload');
displayPolicy.version+=1;displayPolicy.security.content.blockedPhrases=[];
assert.equal((await fetch(`${process.env.SAFETYNET_SMOKE_SERVER}/api/admin/policy`,{method:'PUT',headers,body:JSON.stringify(displayPolicy)})).status,200);
for(let n=0;n<200;n++){const s=await win.webContents.executeJavaScript('window.safetynet.state()');if(s.data.ready&&s.data.policyVersion===8)break;await wait(100);}
assert.equal((await win.webContents.executeJavaScript('window.safetynet.state()')).data.ready,true);
const visualLogin='<!doctype html><meta charset="utf-8"><title>Visual identity fixture</title><style>body{font-family:Arial;background:#fff;color:#202124;margin:0}form{margin:60px auto;padding:32px;border:2px solid #3267cb;border-radius:12px;width:340px;height:330px;box-sizing:content-box}h1{color:#3267cb;font-size:27px}input{display:block;margin:20px 0;padding:12px;border:1px solid #aaa;width:260px}button{background:#3267cb;color:white;padding:12px}</style><form method="post" action="/sink"><h1>SafetyNet Identity Lab</h1><h2>Sign in</h2><p>Use your laboratory account</p><input name="username" type="email" autocomplete="username"><input type="password" autocomplete="current-password"><button type="submit">Continue</button></form>';
await page.session.protocol.handle('https',request=>{if(new URL(request.url).origin!=='https://identity.example.test')throw Error('Unexpected visual fixture URL');return new Response(visualLogin,{headers:{'content-type':'text/html'}});});
log('Visual fixture: navigating approved origin');
await Promise.race([win.webContents.executeJavaScript('window.safetynet.navigate("https://identity.example.test/login")'),wait(15000).then(()=>{throw Error('Visual fixture navigation timed out');})]);await wait(400);
log('Visual fixture: capturing approved form');
const formRect=await page.executeJavaScript('(()=>{const r=document.querySelector("form").getBoundingClientRect();return {x:Math.floor(r.x),y:Math.floor(r.y),width:Math.ceil(r.width),height:Math.ceil(r.height)}})()');
const referencePNG=await require('../apps/browser/visual-capture.cjs').capturePNG(page,formRect);
const referenceResponse=await fetch(`${process.env.SAFETYNET_SMOKE_SERVER}/api/admin/security/visual-reference`,{method:'POST',headers,body:JSON.stringify({expectedVersion:8,brandId:'identity-lab',label:'Controlled Identity Lab',allowedOrigins:['https://identity.example.test'],data:referencePNG.toString('base64'),scope:'login-form'})});assert.equal(referenceResponse.status,200);const visualDraft=await referenceResponse.json();
const visualPolicy=(await (await fetch(`${process.env.SAFETYNET_SMOKE_SERVER}/api/admin/overview`,{headers})).json()).policy;visualPolicy.version++;visualDraft.brand.requiredText=['SafetyNet Identity Lab'];visualPolicy.security.visualPhishing={enabled:true,failClosed:true,brands:[visualDraft.brand]};
assert.equal((await fetch(`${process.env.SAFETYNET_SMOKE_SERVER}/api/admin/policy`,{method:'PUT',headers,body:JSON.stringify(visualPolicy)})).status,200);
for(let n=0;n<200;n++){const s=await win.webContents.executeJavaScript('window.safetynet.state()');if(s.data.ready&&s.data.policyVersion===9&&!s.data.loginCheckPending)break;await wait(100);}
assert.equal((await win.webContents.executeJavaScript('window.safetynet.state()')).data.ready,true,'Approved visual origin blocked');
const postsBeforePhish=(await (await fetch(url+'/count')).json()).posts;
await win.webContents.executeJavaScript(`window.safetynet.navigate(${JSON.stringify(url+'/visual-login')})`);
for(let n=0;n<120;n++){const s=await win.webContents.executeJavaScript('window.safetynet.state()');if(!s.data.ready)break;await wait(100);}
const phishingState=(await win.webContents.executeJavaScript('window.safetynet.state()')).data;assert.equal(phishingState.ready,false);assert.equal(phishingState.message,'Blocked: this login resembles a protected brand on an unapproved origin.');
assert.equal((await win.webContents.executeJavaScript(`window.safetynet.navigate(${JSON.stringify(page.getURL()+'#same-document')})`)).ok,false,'Hash-only navigation escaped visual quarantine');
let visualEvents;await clipboardWait(async()=>{visualEvents=(await (await fetch(`${process.env.SAFETYNET_SMOKE_SERVER}/api/admin/overview`,{headers})).json()).events;return visualEvents.some(e=>e.kind==='phishing.block'&&e.metadata.ruleId==='identity-lab');});assert.ok(visualEvents.some(e=>e.kind==='phishing.block'&&e.metadata.ruleId==='identity-lab'),'Visual brand decision was not audited');
assert.equal((await (await fetch(url+'/count')).json()).posts,postsBeforePhish);
await wait(2500);assert.equal((await win.webContents.executeJavaScript('window.safetynet.state()')).data.ready,false,'Policy refresh cleared phishing quarantine');
const safeNavigation=await win.webContents.executeJavaScript(`window.safetynet.navigate(${JSON.stringify(url)})`);assert.equal(safeNavigation.ok,true,safeNavigation.error);
await page.session.protocol.unhandle('https');
log('Real screenshot-derived pHash: trusted origin allowed, identical login at unlisted origin blocked, no payload released, quarantine survived refresh and safe navigation recovered');
const managedClipboardPolicy=(await (await fetch(`${process.env.SAFETYNET_SMOKE_SERVER}/api/admin/overview`,{headers})).json()).policy;
const liveClipboardOriginal=await clipboard.readText();
try{
for(const allowed of [false,true]){
// A new policy intentionally reloads the managed document. Observe that
// reload before selecting text; otherwise the guard correctly rejects a
// selection whose document is replaced during inspection.
let policyDocumentLoaded=false;const onPolicyLoad=()=>{policyDocumentLoaded=true;};
page.once('did-finish-load',onPolicyLoad);
managedClipboardPolicy.version++;managedClipboardPolicy.security.clipboard.allowCopy=allowed;
assert.equal((await fetch(`${process.env.SAFETYNET_SMOKE_SERVER}/api/admin/policy`,{method:'PUT',headers,body:JSON.stringify(managedClipboardPolicy)})).status,200);
await clipboardWait(async()=>{const s=(await win.webContents.executeJavaScript('window.safetynet.state()')).data;return s.ready&&s.policyVersion===managedClipboardPolicy.version;});
await clipboardWait(async()=>policyDocumentLoaded&&!page.isLoading());page.removeListener('did-finish-load',onPolicyLoad);
await clipboard.writeText(clipboardSentinel);await selectClipboardText('Public live-policy sample');
// Adding the synthetic selection node triggers the preload's 150 ms
// visual-mutation debounce. Let that new document revision be checked
// before starting the deliberately slower isolated YARA scan.
await page.executeJavaScript('new Promise(resolve=>setTimeout(resolve,250))');
await clipboardWait(async()=>{const s=(await win.webContents.executeJavaScript('window.safetynet.state()')).data;return s.ready&&!s.loginCheckPending;});
await clipboardKey('C');
if(allowed&&await clipboard.readText()!=='Public live-policy sample'){const s=(await win.webContents.executeJavaScript('window.safetynet.state()')).data;log('Live copy gate state: '+JSON.stringify({ready:s.ready,policyVersion:s.policyVersion,message:s.message,clipboardPending:s.clipboardPending,loginCheckPending:s.loginCheckPending}));}
assert.equal(await clipboard.readText(),allowed?'Public live-policy sample':clipboardSentinel,'Native copy ignored centrally published permission');
await clipboard.writeText(clipboardSentinel);const share=await win.webContents.executeJavaScript('window.safetynet.shareURL()');
assert.equal(share.ok,allowed,'Share ignored centrally published copy permission');
assert.equal(await clipboard.readText(),allowed?new URL(url).toString():clipboardSentinel,'Share clipboard effect did not match signed copy policy');
}
log('Live signed clipboard permission blocked and re-enabled native Copy and Share without restart');
}finally{await clipboard.writeText(liveClipboardOriginal);await page.executeJavaScript("document.getElementById('clipboard-source')?.remove()");}
await fetch(`${process.env.SAFETYNET_SMOKE_SERVER}/api/admin/devices/${result.data.deviceId}/revoke`,{method:'POST',headers,body:'{}'});
for(let n=0;n<180;n++){const state=await win.webContents.executeJavaScript('window.safetynet.state()');if(!state.data.ready)break;await wait(100);}
assert.equal((await win.webContents.executeJavaScript('window.safetynet.state()')).data.ready,false,'Revocation did not quarantine browser');
console.log('Electron smoke passed: enrollment, clipboard DLP/ClickFix and live permissions, sandboxed frame bypass tests, agents, YARA pre-save downloads, local documents, live DNS/content, proxy, governed teaching and revocation.');
require('../apps/browser/page-clipboard-guard.cjs').disposePageClipboardGuard(page);
app.exit(0);
}catch(e){fs.appendFileSync(path.join(process.env.SAFETYNET_SMOKE_ARTIFACTS,'smoke-entry.txt'),e.stack+'\n');console.error(e.stack);app.exit(1);}
});
+37
View File
@@ -0,0 +1,37 @@
'use strict';
const {app,BrowserWindow}=require('electron');const assert=require('node:assert/strict');const fs=require('node:fs');const path=require('node:path');
app.disableHardwareAcceleration();app.enableSandbox();app.setPath('userData',process.env.SAFETYNET_ADMIN_SMOKE_PROFILE);app.commandLine.appendSwitch('force-device-scale-factor','1');
let window;const deadline=setTimeout(()=>{console.error('ADMIN_UI_PROOF_TIMEOUT');app.exit(1);},50000);
async function evaluate(source){return window.webContents.executeJavaScript(source,true);}
async function waitFor(source){const until=Date.now()+12000;while(Date.now()<until){if(await evaluate(source))return;await new Promise(r=>setTimeout(r,75));}throw Error('Administrator UI state did not arrive');}
app.whenReady().then(async()=>{
window=new BrowserWindow({show:false,width:1500,height:1100,webPreferences:{nodeIntegration:false,contextIsolation:true,sandbox:true,offscreen:true,backgroundThrottling:false}});
await window.loadURL(process.env.SAFETYNET_ADMIN_SMOKE_URL);
await evaluate(`globalThis.__proofErrors=0;addEventListener('error',()=>globalThis.__proofErrors++);addEventListener('unhandledrejection',()=>globalThis.__proofErrors++);`);
assert.deepEqual(await evaluate(`({node:typeof process,require:typeof require,bridge:typeof safetynet})`),{node:'undefined',require:'undefined',bridge:'undefined'});
const headers=await evaluate(`fetch(location.href).then(r=>({csp:r.headers.get('content-security-policy'),type:r.headers.get('x-content-type-options')}))`);assert.ok(headers.csp.includes("script-src 'self'"));assert.ok(headers.csp.includes("frame-ancestors 'none'"));assert.equal(headers.type,'nosniff');
await evaluate(`document.getElementById('token').value=${JSON.stringify(process.env.SAFETYNET_ADMIN_SMOKE_TOKEN)};document.getElementById('connect').click()`);await waitFor(`!document.getElementById('workspace').hidden&&document.getElementById('status').textContent.includes('Connected')`);
assert.equal(await evaluate(`document.querySelectorAll('nav a').length>=12`),true);assert.equal(await evaluate(`document.getElementById('draft-state').textContent`),'Published policy v1');assert.equal(await evaluate(`document.getElementById('token').value`),'');assert.equal(await evaluate(`document.getElementById('policy-version').textContent`),'v1');
await evaluate(`document.getElementById('preset-id').value='baseline';document.getElementById('preset-id').dispatchEvent(new Event('change'));document.getElementById('preset-preview').click()`);await waitFor(`!document.getElementById('preset-apply').disabled`);
assert.equal(await evaluate(`document.getElementById('policy-version').textContent`),'v1');assert.ok((await evaluate(`document.getElementById('preset-changes').textContent`)).includes('browser.allowDevTools'));
await evaluate(`document.getElementById('preset-apply').click()`);await waitFor(`document.getElementById('status').textContent.includes('Template added')`);assert.equal(await evaluate(`document.getElementById('devtools').checked`),false);assert.equal(await evaluate(`document.getElementById('policy-version').textContent`),'v1');
await evaluate(`document.getElementById('review-changes').click()`);assert.equal(await evaluate(`document.getElementById('change-review').open`),true);assert.ok((await evaluate(`document.getElementById('change-review-list').textContent`)).includes('browser.allowDevTools'));assert.equal(await evaluate(`document.getElementById('policy-version').textContent`),'v1');await evaluate(`document.getElementById('review-close').click()`);
await evaluate(`document.getElementById('publish').click()`);await waitFor(`document.getElementById('policy-version').textContent==='v2'&&document.getElementById('status').textContent.includes('published')`);
await evaluate(`const values={'enterprise-dns-mode':'secure','enterprise-dns-templates':'https://dns.synthetic.example/dns-query','enterprise-vpn-interfaces':'Synthetic Corporate VPN','enterprise-vpn-dns':'10.77.0.53','enterprise-icap-url':${JSON.stringify(process.env.SAFETYNET_ADMIN_SMOKE_ICAP)},'enterprise-icap-method':'RESPMOD','enterprise-icap-timeout':'10000','enterprise-icap-max':'1048576'};for(const [id,value]of Object.entries(values))document.getElementById(id).value=value;for(const id of ['enterprise-vpn-required','enterprise-icap-enabled'])document.getElementById(id).checked=true;document.getElementById('enterprise-icap-probe').click()`);
await waitFor(`document.getElementById('enterprise-icap-status').textContent.includes('passed')`);assert.equal(await evaluate(`document.getElementById('policy-version').textContent`),'v2');
await evaluate(`document.getElementById('diagnostics-enabled').checked=true;document.getElementById('diagnostics-mode').value='debug';document.getElementById('diagnostics-endpoint').value='https://collector.synthetic.example';document.getElementById('diagnostics-debug-sample').value='1';document.getElementById('agent-scope-bookmarks:mutate').checked=true;`);
await evaluate(`document.getElementById('publish').click()`);await waitFor(`document.getElementById('policy-version').textContent==='v3'&&document.getElementById('status').textContent.includes('published')`);
const fields=await evaluate(`({dns:document.getElementById('enterprise-dns-mode').value,vpn:document.getElementById('enterprise-vpn-required').checked,icap:document.getElementById('enterprise-icap-enabled').checked,method:document.getElementById('enterprise-icap-method').value,readiness:document.getElementById('integration-readiness').textContent,errors:globalThis.__proofErrors})`);assert.equal(fields.dns,'secure');assert.equal(fields.vpn,true);assert.equal(fields.icap,true);assert.equal(fields.method,'RESPMOD');assert.ok(fields.readiness.includes('configured'));assert.equal(fields.errors,0);
assert.equal(await evaluate(`document.getElementById('preset-changes').childElementCount`),0);assert.equal(await evaluate(`document.getElementById('preset-description').textContent`),'');
await evaluate(`scrollTo(0,0)`);window.webContents.invalidate();await new Promise(r=>setTimeout(r,300));fs.mkdirSync(path.resolve('artifacts'),{recursive:true});fs.writeFileSync(path.resolve('artifacts/enterprise-admin.png'),(await window.webContents.capturePage()).toPNG());
await evaluate(`document.getElementById('event-filter').value='no-such-synthetic-event';document.getElementById('event-filter').dispatchEvent(new Event('input'));`);assert.ok((await evaluate(`document.getElementById('event-filter-count').textContent`)).startsWith('0 of '));await evaluate(`document.getElementById('event-filter').value='';document.getElementById('event-filter').dispatchEvent(new Event('input'));document.getElementById('device-filter').value='synthetic';document.getElementById('device-filter').dispatchEvent(new Event('input'));`);assert.equal(await evaluate(`document.getElementById('device-filter-count').textContent`),'0 of 0 devices');
for(const theme of ['light','dark']){await evaluate(`document.getElementById('console-theme').value=${JSON.stringify(theme)};document.getElementById('console-theme').dispatchEvent(new Event('change'));`);assert.equal(await evaluate(`document.documentElement.dataset.theme`),theme);assert.equal(await evaluate(`localStorage.getItem('safetynet.admin.theme')`),theme);window.webContents.invalidate();await new Promise(r=>setTimeout(r,150));fs.writeFileSync(path.resolve(`artifacts/admin-console-${theme}.png`),(await window.webContents.capturePage()).toPNG());}
window.setSize(600,1000);await evaluate(`scrollTo(0,0)`);window.webContents.invalidate();await new Promise(r=>setTimeout(r,150));assert.equal(await evaluate(`document.documentElement.scrollWidth<=innerWidth`),true);fs.writeFileSync(path.resolve('artifacts/admin-console-mobile.png'),(await window.webContents.capturePage()).toPNG());assert.equal(await evaluate(`globalThis.__proofErrors`),0);
await evaluate(`document.getElementById('sessions-load').click()`);await waitFor(`document.getElementById('sessions-status').textContent.includes('0 active management sessions')`);
await evaluate(`globalThis.__adminPrincipal=currentPrincipal;applyOperatorPermissions({sub:'synthetic-auditor',role:'auditor',permissions:['overview.read','audit.read','policy.read','teaching.read']});`);assert.equal(await evaluate(`document.getElementById('publish').disabled&&document.getElementById('publish-shortcut').disabled&&document.getElementById('enroll').disabled&&document.getElementById('bookmark-device-load').disabled&&document.getElementById('access-sessions').hidden`),true);await evaluate(`applyOperatorPermissions(globalThis.__adminPrincipal);delete globalThis.__adminPrincipal;`);
assert.equal(await evaluate(`document.getElementById('diagnostics-enabled').checked&&document.getElementById('diagnostics-mode').value==='debug'&&document.getElementById('agent-scope-bookmarks:mutate').checked`),true);
await evaluate(`applyOperatorPermissions({sub:'synthetic-auditor',role:'auditor',permissions:['overview.read','audit.read','policy.read']});`);
assert.equal(await evaluate(`document.getElementById('diagnostics-enabled').disabled&&document.getElementById('agent-scope-bookmarks:mutate').disabled`),true);
console.log('ADMIN_UI_PROOF_OK');clearTimeout(deadline);window.destroy();app.exit(0);
}).catch(error=>{console.error('ADMIN_UI_PROOF_FAILED',error.message);clearTimeout(deadline);window?.destroy();app.exit(1);});
+28
View File
@@ -0,0 +1,28 @@
// Finite, isolated administrator workflow proof using actual UI and HTTP routes.
import assert from 'node:assert/strict';
import { createRequire } from 'node:module';
import { createServer } from 'node:net';
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join, resolve, sep, basename } from 'node:path';
import { spawn } from 'node:child_process';
import { randomBytes } from 'node:crypto';
import { openStore } from '../apps/server/store.mjs';
import { createApp } from '../apps/server/app.mjs';
import { verifyPolicy } from '../packages/core/policy.mjs';
const require=createRequire(import.meta.url),directory=mkdtempSync(join(tmpdir(),'safetynet-enterprise-admin-smoke-'));
let store,server,icap,child;const exchanges=[];
try{
store=openStore(join(directory,'management'));const original=store.get('policy');original.browser.allowDevTools=true;original.browser.allowWebSockets=true;store.put('policy',original);
const adminToken=randomBytes(32).toString('base64url'),config={adminToken,publicUrl:'http://127.0.0.1',secure:false};
server=createApp(store,config).listen(0,'127.0.0.1');await new Promise(r=>server.once('listening',r));config.publicUrl=`http://127.0.0.1:${server.address().port}`;
icap=createServer(socket=>{let received=Buffer.alloc(0);socket.on('data',chunk=>{received=Buffer.concat([received,chunk]);if(received.length>16384){socket.destroy();return;}if(received.includes('\r\n\r\n')){exchanges.push(received.toString('ascii'));socket.end('ICAP/1.0 200 OK\r\nMethods: RESPMOD, REQMOD\r\nISTag: "synthetic-test-service"\r\nAllow: 204\r\nEncapsulated: null-body=0\r\n\r\n');}});}).listen(0,'127.0.0.1');await new Promise(r=>icap.once('listening',r));
const env={...process.env,SAFETYNET_ADMIN_SMOKE_PROFILE:join(directory,'browser'),SAFETYNET_ADMIN_SMOKE_URL:config.publicUrl,SAFETYNET_ADMIN_SMOKE_TOKEN:adminToken,SAFETYNET_ADMIN_SMOKE_ICAP:`icap://127.0.0.1:${icap.address().port}/scan`};delete env.ELECTRON_RUN_AS_NODE;
child=spawn(require('electron'),['scripts/enterprise-admin-smoke.cjs'],{env,windowsHide:true,stdio:['ignore','pipe','pipe']});child.stdout.on('data',data=>{if(String(data).includes('ADMIN_UI_PROOF_OK'))console.log('Administrator interface workflow passed.');});child.stderr.on('data',data=>{const message=String(data);if(message.includes('ADMIN_UI_PROOF_'))console.error(message.trim());});
const timer=setTimeout(()=>child.kill(),60000),code=await new Promise(r=>{child.once('exit',code=>r(code??1));child.once('error',()=>r(1));});clearTimeout(timer);assert.equal(code,0,'Administrator interface proof failed');
const policy=verifyPolicy(store.envelope(),store.publicKey());assert.equal(policy.version,3);assert.equal(policy.browser.allowDevTools,false);assert.equal(policy.browser.allowWebSockets,false);assert.deepEqual(policy.enterprise.dns,{mode:'secure',templates:['https://dns.synthetic.example/dns-query']});assert.deepEqual(policy.enterprise.vpn,{required:true,interfaceNames:['Synthetic Corporate VPN'],requiredDnsServers:['10.77.0.53']});assert.equal(policy.enterprise.icap.enabled,true);assert.equal(policy.enterprise.icap.url,env.SAFETYNET_ADMIN_SMOKE_ICAP);assert.equal(exchanges.length,1);assert.ok(exchanges[0].startsWith('OPTIONS '));assert.equal(exchanges[0].split('\r\n\r\n')[1],'');
assert.equal(policy.diagnostics.enabled,true);assert.equal(policy.diagnostics.mode,'debug');assert.equal(policy.diagnostics.endpoint,'https://collector.synthetic.example');assert.ok(policy.agents.scopes.includes('bookmarks:mutate'));
const report={signedDiagnosticsUi:true,newAgentScopesUi:true,adminUi:true,isolatedControlPlane:true,previewDidNotPublish:true,explicitSignedPublication:true,integrationFormRoundtrip:true,optionsOnlyProbe:true,probeContentSent:false,cspPreserved:true,nodeUnavailable:true,hiddenCpuWindow:true,policyVersion:policy.version,groupedNavigation:true,draftChangeReview:true,reviewDoesNotPublish:true,fleetAndAuditFilters:true,consoleThemePersistence:true,mobileNoHorizontalOverflow:true,readOnlyRoleControls:true,sessionInventoryUi:true};mkdirSync('artifacts',{recursive:true});writeFileSync('artifacts/enterprise-admin-proof.json',JSON.stringify(report,null,2));console.log(JSON.stringify(report));
}finally{
child?.kill();for(const service of [server,icap])if(service)await new Promise(r=>{service.closeAllConnections?.();service.close(r);});store?.db.close();const target=resolve(directory);if(!target.startsWith(resolve(tmpdir())+sep)||!basename(target).startsWith('safetynet-enterprise-admin-smoke-'))throw Error('Unsafe proof cleanup');rmSync(target,{recursive:true,force:true,maxRetries:10,retryDelay:100});
}
+27
View File
@@ -0,0 +1,27 @@
const {app,BrowserWindow,dialog,session}=require('electron');
const fs=require('node:fs'),assert=require('node:assert/strict');
app.setPath('userData',process.env.SAFETYNET_ENTERPRISE_PROFILE);app.setPath('sessionData',process.env.SAFETYNET_ENTERPRISE_PROFILE);app.disableHardwareAcceleration();
let dialogs=0;dialog.showSaveDialog=async()=>{dialogs++;return {canceled:false,filePath:process.env.SAFETYNET_ENTERPRISE_FILE};};
require('../apps/browser/main.cjs');
const wait=ms=>new Promise(r=>setTimeout(r,ms)),deadline=setTimeout(()=>app.exit(1),110000);
app.whenReady().then(async()=>{try{
let win;for(let i=0;i<150;i++){win=BrowserWindow.getAllWindows()[0];if(win&&!win.webContents.isLoading()&&win.webContents.getURL().endsWith('index.html'))break;await wait(100);}assert.ok(win);
const shell=code=>win.webContents.executeJavaScript(code),state=async()=>(await shell('window.safetynet.state()')).data;
const result=await shell(`window.safetynet.enroll(${JSON.stringify({server:process.env.SAFETYNET_ENTERPRISE_SERVER,code:process.env.SAFETYNET_ENTERPRISE_CODE})})`);assert.equal(result.ok,true);assert.equal(result.data.ready,true);
const page=win.contentView.children.find(c=>c.webContents!==win.webContents).webContents;for(let i=0;i<100&&page.isLoading();i++)await wait(100);
const origin=process.env.SAFETYNET_ENTERPRISE_SINK,headers={authorization:`Bearer ${process.env.SAFETYNET_ENTERPRISE_ADMIN}`,'content-type':'application/json'};
async function overview(){return (await fetch(process.env.SAFETYNET_ENTERPRISE_SERVER+'/api/admin/overview',{headers})).json();}
async function publish(mutator){const p=(await overview()).policy;mutator(p);p.version++;const r=await fetch(process.env.SAFETYNET_ENTERPRISE_SERVER+'/api/admin/policy',{method:'PUT',headers,body:JSON.stringify(p)});assert.equal(r.status,200);return p.version;}
async function until(fn,ms=20000){const end=Date.now()+ms;while(Date.now()<end){if(await fn())return;await wait(100);}throw Error('Enterprise fixture deadline exceeded');}
async function post(text){return page.executeJavaScript(`fetch('/receiver',{method:'POST',body:${JSON.stringify(text)}}).then(r=>r.ok).catch(()=>false)`);}
assert.equal(await post('public ordinary upload'),true);assert.equal(await post('PUBLIC_MALWARE_FIXTURE'),false);
assert.equal((await fetch(origin+'/proof-stats').then(r=>r.json())).posts,1);
await page.executeJavaScript("(()=>{const a=document.createElement('a');a.href='/download/blocked';document.body.append(a);a.click();})()");
await until(async()=> (await overview()).events.some(e=>e.kind==='download.block'&&e.metadata.ruleId?.includes('icap')));assert.equal(dialogs,0);assert.equal(fs.existsSync(process.env.SAFETYNET_ENTERPRISE_FILE),false);
await page.executeJavaScript("(()=>{const a=document.createElement('a');a.href='/download/clean';document.body.append(a);a.click();})()");await until(()=>fs.existsSync(process.env.SAFETYNET_ENTERPRISE_FILE));assert.equal(dialogs,1);assert.deepEqual(fs.readFileSync(process.env.SAFETYNET_ENTERPRISE_FILE),Buffer.from([0,1,2,3,65,66,67,255]));
const pausedVersion=await publish(p=>p.enterprise.vpn={required:true,interfaceNames:['SafetyNet nonexistent proof interface'],requiredDnsServers:[]});await until(async()=>{const s=await state();return s.policyVersion===pausedVersion&&!s.ready;});
const baseline=(await fetch(origin+'/proof-stats').then(r=>r.json())).websiteRequests;assert.equal(await post('public blocked by VPN gate'),false);await wait(500);assert.equal((await fetch(origin+'/proof-stats').then(r=>r.json())).websiteRequests,baseline);
const resumedVersion=await publish(p=>p.enterprise.vpn.required=false);await until(async()=>{const s=await state();return s.policyVersion===resumedVersion&&s.ready;});
assert.equal(await session.fromPartition('persist:safetynet-management').resolveProxy(origin),await session.fromPartition('persist:safetynet-managed').resolveProxy(origin));
console.log(JSON.stringify({nativeEnterprise:true,icapUploadAllow:true,icapUploadBlock:true,blockedDownloadDialogAbsent:true,cleanDownloadBytesVerified:true,requiredVpnBlocksWebsiteRequests:true,remotePolicyRecovery:true,managementProxyParity:true}));clearTimeout(deadline);app.quit();
}catch(error){console.error(JSON.stringify({nativeEnterprise:false,error:error.message}));clearTimeout(deadline);app.exit(1);}});
+24
View File
@@ -0,0 +1,24 @@
import assert from 'node:assert/strict';
import {createRequire} from 'node:module';
import {createServer} from 'node:http';
import net from 'node:net';
import {mkdtempSync,mkdirSync,writeFileSync} from 'node:fs';
import {tmpdir} from 'node:os';
import {join} from 'node:path';
import {spawn} from 'node:child_process';
import {randomBytes} from 'node:crypto';
import {createApp} from '../apps/server/app.mjs';
import {openStore,digest} from '../apps/server/store.mjs';
const electron=createRequire(import.meta.url)('electron'),temporary=mkdtempSync(join(tmpdir(),'safetynet-enterprise-proof-'));
const marker='PUBLIC_MALWARE_FIXTURE',clean=Buffer.from([0,1,2,3,65,66,67,255]);
const report={local:true,icapScans:0,icapBlocks:0,posts:0,websiteRequests:0};
const sockets=new Set();let icap,sink,management,store,child;
try{
icap=net.createServer(socket=>{sockets.add(socket);socket.on('error',()=>{});socket.on('close',()=>sockets.delete(socket));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, REQMOD\r\nISTag: "local-fixture"\r\nAllow: 204\r\nEncapsulated: null-body=0\r\n\r\n');report.icapScans++;if(input.includes(Buffer.from(marker))){report.icapBlocks++;socket.end('ICAP/1.0 200 OK\r\nISTag: "local-fixture"\r\nEncapsulated: res-hdr=0, res-body=99\r\n\r\nHTTP/1.1 403 Forbidden');}else socket.end('ICAP/1.0 204 No Content\r\nISTag: "local-fixture"\r\n\r\n');});}).listen(0,'127.0.0.1');await new Promise(r=>icap.once('listening',r));
sink=createServer((req,res)=>{if(req.url==='/proof-stats'){res.setHeader('content-type','application/json');return res.end(JSON.stringify(report));}report.websiteRequests++;if(req.method==='POST'){const chunks=[];req.on('data',c=>chunks.push(c));req.on('end',()=>{report.posts++;assert.equal(Buffer.concat(chunks).includes(Buffer.from(marker)),false,'Blocked fixture reached receiver');res.end('accepted');});return;}if(req.url.startsWith('/download/')){const bytes=req.url.endsWith('/blocked')?Buffer.from(marker):clean;res.setHeader('content-disposition','attachment; filename="fixture.bin"');res.setHeader('content-type','application/octet-stream');res.setHeader('content-length',bytes.length);return res.end(bytes);}res.setHeader('content-type','text/html');res.end('<!doctype html><title>Enterprise native proof</title><h1>Public local fixture</h1>');}).listen(0,'127.0.0.1');await new Promise(r=>sink.once('listening',r));
const code=randomBytes(32).toString('base64url'),adminToken=randomBytes(32).toString('base64url');store=openStore(join(temporary,'store'));const p=store.get('policy');p.browser.homeUrl=`http://127.0.0.1:${sink.address().port}`;p.browser.allowedHosts=['127.0.0.1'];p.browser.allowDownloads=true;p.dlp.rules=[];p.security.yara.enabled=false;p.security.yara.rules=[];p.proxy.mode='system';p.enterprise.icap={...p.enterprise.icap,enabled:true,url:`icap://127.0.0.1:${icap.address().port}/av`};store.put('policy',p);store.db.prepare('INSERT INTO enrollments VALUES(?,?,?)').run(digest(code),Date.now()+600000,'synthetic-enterprise-user');
const config={publicUrl:'http://127.0.0.1',secure:false,adminToken,requirePQManagement:true};management=createApp(store,config).listen(0,'127.0.0.1');await new Promise(r=>management.once('listening',r));config.publicUrl=`http://127.0.0.1:${management.address().port}`;
const env={...process.env,SAFETYNET_ENTERPRISE_PROFILE:join(temporary,'browser'),SAFETYNET_ENTERPRISE_SERVER:config.publicUrl,SAFETYNET_ENTERPRISE_CODE:code,SAFETYNET_ENTERPRISE_ADMIN:adminToken,SAFETYNET_ENTERPRISE_SINK:p.browser.homeUrl,SAFETYNET_ENTERPRISE_FILE:join(temporary,'released.bin'),SAFETYNET_SMOKE_USERDATA:join(temporary,'browser')};delete env.ELECTRON_RUN_AS_NODE;
child=spawn(electron,['scripts/enterprise-browser-smoke.cjs'],{windowsHide:true,stdio:'inherit',env});const timer=setTimeout(()=>child.kill(),120000);const status=await new Promise(r=>{child.once('exit',c=>r(c??1));child.once('error',()=>r(1));});clearTimeout(timer);assert.equal(status,0,'Native enterprise fixture failed');assert.equal(report.posts,1);assert.ok(report.icapBlocks>=2);Object.assign(report,{nativeBrowserPassed:true,icapOnlyUpload:true,icapBeforeDownloadDialog:true,requiredVpnPaused:true,remotePolicyRecovery:true,managementProtectedChannel:true,managementProxyParity:true});mkdirSync('artifacts',{recursive:true});writeFileSync('artifacts/enterprise-browser-proof.json',JSON.stringify(report,null,2));console.log(JSON.stringify(report));
}finally{child?.kill();for(const socket of sockets)socket.destroy();for(const server of [management,sink,icap])if(server){server.closeAllConnections?.();await new Promise(r=>server.close(r));}store?.db.close();}
+37
View File
@@ -0,0 +1,37 @@
'use strict';
const {app,BrowserWindow}=require('electron');const assert=require('node:assert/strict');const fs=require('node:fs');const path=require('node:path');
app.disableHardwareAcceleration();app.enableSandbox();app.setPath('userData',process.env.SAFETYNET_ADMIN_SMOKE_PROFILE);app.commandLine.appendSwitch('force-device-scale-factor','1');
let window;const deadline=setTimeout(()=>{console.error('ADMIN_UI_PROOF_TIMEOUT');app.exit(1);},50000);
async function evaluate(source){return window.webContents.executeJavaScript(source,true);}
async function waitFor(source){const until=Date.now()+12000;while(Date.now()<until){if(await evaluate(source))return;await new Promise(r=>setTimeout(r,75));}throw Error('Administrator UI state did not arrive: '+await evaluate(`document.getElementById('status').textContent`));}
app.whenReady().then(async()=>{
window=new BrowserWindow({show:false,width:1500,height:1100,webPreferences:{nodeIntegration:false,contextIsolation:true,sandbox:true,offscreen:true,backgroundThrottling:false}});
await window.loadURL(process.env.SAFETYNET_ADMIN_SMOKE_URL);
await evaluate(`globalThis.__proofErrors=0;addEventListener('error',()=>globalThis.__proofErrors++);addEventListener('unhandledrejection',()=>globalThis.__proofErrors++);`);
assert.deepEqual(await evaluate(`({node:typeof process,require:typeof require,bridge:typeof safetynet})`),{node:'undefined',require:'undefined',bridge:'undefined'});
const headers=await evaluate(`fetch(location.href).then(r=>({csp:r.headers.get('content-security-policy'),type:r.headers.get('x-content-type-options')}))`);assert.ok(headers.csp.includes("script-src 'self'"));assert.ok(headers.csp.includes("frame-ancestors 'none'"));assert.equal(headers.type,'nosniff');
const reviewProof=process.env.SAFETYNET_GROUP_REVIEW_PROOF==='1';
if(reviewProof){await window.webContents.session.cookies.set({url:process.env.SAFETYNET_ADMIN_SMOKE_URL,name:'sn_session',value:process.env.SAFETYNET_GROUP_OPERATOR_TOKEN,httpOnly:true,sameSite:'lax'});await window.reload();await waitFor(`!document.getElementById('workspace').hidden&&document.getElementById('status').textContent.includes('Connected')`);}
else {
await evaluate(`document.getElementById('token').value=${JSON.stringify(process.env.SAFETYNET_ADMIN_SMOKE_TOKEN)};document.getElementById('connect').click()`);await waitFor(`!document.getElementById('workspace').hidden&&document.getElementById('status').textContent.includes('Connected')`);}
await evaluate(`document.getElementById('group-id').value='engineering';document.getElementById('group-name').value='Engineering';for(const input of document.querySelectorAll('#group-members input'))input.checked=['pilot-device','member-device'].includes(input.value);document.getElementById('group-members').dispatchEvent(new Event('change'));for(const input of document.querySelectorAll('#group-cohort input'))input.checked=input.value==='pilot-device';document.getElementById('group-disable-ai').checked=true;document.getElementById('group-blocked-hosts').value='restricted.synthetic.example';document.getElementById('group-save').click()`);
if(reviewProof){
await waitFor(`document.getElementById('status').textContent.includes('prepared for independent approval')`);assert.equal(await evaluate(`document.getElementById('policy-version').textContent`),'v1');assert.equal(await evaluate(`document.querySelectorAll('#groups-rows tr').length`),0);
await window.webContents.session.cookies.set({url:process.env.SAFETYNET_ADMIN_SMOKE_URL,name:'sn_session',value:process.env.SAFETYNET_GROUP_REVIEWER_TOKEN,httpOnly:true,sameSite:'lax'});await window.reload();await waitFor(`!document.getElementById('workspace').hidden&&document.querySelector('#reviews-rows button')`);
await evaluate(`document.querySelector('#reviews-rows button').click()`);await waitFor(`!document.getElementById('independent-review-detail').hidden`);
const operation=await evaluate(`document.getElementById('independent-review-operation').textContent`);for(const value of ['engineering','pilot-device','member-device','disableAI','restricted.synthetic.example'])assert.ok(operation.includes(value),`Exact proposal missing ${value}`);
await evaluate(`document.getElementById('independent-review-confirm').checked=true;document.getElementById('independent-review-confirm').dispatchEvent(new Event('change'));document.getElementById('independent-review-approve').click()`);await waitFor(`document.getElementById('policy-version').textContent==='v2'`);assert.equal(await evaluate(`document.querySelector('#groups-rows tr td:nth-child(3)').textContent.startsWith('pilot')`),true);
console.log('GROUP_ADMIN_PROOF_OK');clearTimeout(deadline);window.destroy();app.exit(0);return;
}
await waitFor(`document.getElementById('policy-version').textContent==='v2'&&document.getElementById('status').textContent.includes('published')`);
assert.equal(await evaluate(`document.querySelector('#groups-rows tr td:nth-child(3)').textContent.startsWith('pilot')`),true);
await evaluate(`document.getElementById('group-preview-device').value='pilot-device';document.getElementById('group-preview').click()`);await waitFor(`document.getElementById('group-preview-summary').textContent.includes('engineering')`);
assert.equal(await evaluate(`document.getElementById('group-preview-diff').textContent.includes('/browser/blockedHosts')`),true);
await evaluate(`document.getElementById('group-preview-device').value='outside-device';document.getElementById('group-preview').click()`);await waitFor(`document.getElementById('group-preview-summary').textContent.includes('baseline only')`);
assert.equal(await evaluate(`document.getElementById('group-preview-diff').textContent.includes('restricted.synthetic.example')`),false);
await evaluate(`document.getElementById('group-stage').value='all';document.getElementById('group-stage').dispatchEvent(new Event('change'));document.getElementById('group-save').click()`);await waitFor(`document.getElementById('policy-version').textContent==='v3'&&document.getElementById('status').textContent.includes('published')`);
assert.equal(await evaluate(`document.querySelector('#groups-rows tr td:nth-child(3)').textContent`),'All members');assert.equal(await evaluate(`document.getElementById('group-device-rows').textContent.includes('Awaiting target version')`),true);assert.equal(await evaluate(`globalThis.__proofErrors`),0);
await evaluate(`document.getElementById('policy-groups').scrollIntoView()`);window.webContents.invalidate();await new Promise(r=>setTimeout(r,300));fs.mkdirSync(path.resolve('artifacts'),{recursive:true});fs.writeFileSync(path.resolve('artifacts/groups-admin.png'),(await window.webContents.capturePage()).toPNG());
console.log('GROUP_ADMIN_PROOF_OK');clearTimeout(deadline);window.destroy();app.exit(0);
}).catch(error=>{console.error('GROUP_ADMIN_PROOF_FAILED',error.stack);clearTimeout(deadline);window?.destroy();app.exit(1);});
+29
View File
@@ -0,0 +1,29 @@
// Finite, isolated administrator workflow proof using actual UI and HTTP routes.
import assert from 'node:assert/strict';
import { createRequire } from 'node:module';
import { createServer } from 'node:net';
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join, resolve, sep, basename } from 'node:path';
import { spawn } from 'node:child_process';
import { randomBytes } from 'node:crypto';
import { digest } from '../apps/server/store.mjs';
import { openStore } from '../apps/server/store.mjs';
import { createApp } from '../apps/server/app.mjs';
import { verifyPolicy } from '../packages/core/policy.mjs';
const require=createRequire(import.meta.url),directory=mkdtempSync(join(tmpdir(),'safetynet-groups-admin-smoke-'));
let store,server,child;
try{
store=openStore(join(directory,'management'));const adminToken=randomBytes(32).toString('base64url'),config={adminToken,publicUrl:'http://127.0.0.1',secure:false,requireIndependentPolicyApproval:process.env.SAFETYNET_GROUP_REVIEW_PROOF==='1'};
for(const id of ['pilot-device','member-device','outside-device'])store.db.prepare('INSERT INTO devices(id,name,platform,user,token_hash,last_seen) VALUES(?,?,?,?,?,?)').run(id,id,'win32','synthetic-user',`synthetic-${id}`,new Date().toISOString());
const operatorToken=randomBytes(32).toString('base64url'),reviewerToken=randomBytes(32).toString('base64url');for(const [value,sub,role]of [[operatorToken,'group-operator','operator'],[reviewerToken,'group-reviewer','admin']])store.db.prepare('INSERT INTO sessions VALUES(?,?,?)').run(digest(value),Date.now()+60000,JSON.stringify({sub,role}));
server=createApp(store,config).listen(0,'127.0.0.1');await new Promise(r=>server.once('listening',r));config.publicUrl=`http://127.0.0.1:${server.address().port}`;
const env={...process.env,SAFETYNET_ADMIN_SMOKE_PROFILE:join(directory,'browser'),SAFETYNET_ADMIN_SMOKE_URL:config.publicUrl,SAFETYNET_ADMIN_SMOKE_TOKEN:adminToken,SAFETYNET_GROUP_OPERATOR_TOKEN:operatorToken,SAFETYNET_GROUP_REVIEWER_TOKEN:reviewerToken};delete env.ELECTRON_RUN_AS_NODE;
child=spawn(require('electron'),['scripts/groups-admin-smoke.cjs'],{env,windowsHide:true,stdio:['ignore','pipe','pipe']});child.stdout.on('data',data=>{if(String(data).includes('GROUP_ADMIN_PROOF_OK'))console.log('Group administrator interface workflow passed.');});child.stderr.on('data',data=>{const text=String(data);if(text.includes('GROUP_ADMIN_PROOF_'))console.error(text.trim());});
const timer=setTimeout(()=>child.kill(),60000),code=await new Promise(r=>{child.once('exit',code=>r(code??1));child.once('error',()=>r(1));});clearTimeout(timer);assert.equal(code,0,'Group administrator interface proof failed');
const policy=verifyPolicy(store.envelope(),store.publicKey());assert.equal(policy.version,config.requireIndependentPolicyApproval?2:3);const group=store.getRaw('policyGroups').find(group=>group.id==='engineering');assert.equal(group.rollout.stage,config.requireIndependentPolicyApproval?'pilot':'all');assert.deepEqual([...group.memberDeviceIds].sort(),['member-device','pilot-device']);assert.equal(group.restrictions.disableAI,true);
const report={actualAdministratorUi:true,explicitGroupMembership:true,pilotCohortPublished:true,noNode:true,cspPreserved:true,...(config.requireIndependentPolicyApproval?{operatorProposalLeftPolicyUnchanged:true,exactMembersCohortRestrictionsReviewed:true,distinctAdministratorApproval:true}:{effectivePreview:true,explicitExpansion:true,reportedVersionDisplayed:true})};mkdirSync('artifacts',{recursive:true});writeFileSync(config.requireIndependentPolicyApproval?'artifacts/groups-review-admin-proof.json':'artifacts/groups-admin-proof.json',JSON.stringify(report,null,2));console.log(JSON.stringify(report));
}finally{
child?.kill();if(server)await new Promise(r=>{server.closeAllConnections?.();server.close(r);});store?.db.close();const target=resolve(directory);if(!target.startsWith(resolve(tmpdir())+sep)||!basename(target).startsWith('safetynet-groups-admin-smoke-'))throw Error('Unsafe proof cleanup');rmSync(target,{recursive:true,force:true,maxRetries:10,retryDelay:100});
}
+38
View File
@@ -0,0 +1,38 @@
'use strict';
// Isolated feasibility harness: never loaded by the managed browser.
const fs=require('node:fs'),os=require('node:os'),path=require('node:path'),assert=require('node:assert/strict'),crypto=require('node:crypto');
if(!process.versions.electron){
const {spawn}=require('node:child_process');const env={...process.env};delete env.ELECTRON_RUN_AS_NODE;
const child=spawn(require('electron'),[__filename],{env,windowsHide:true,stdio:'inherit'});const timer=setTimeout(()=>child.kill(),60000);child.once('exit',code=>{clearTimeout(timer);process.exit(code??1);});
}else{
const {app,BrowserWindow,session}=require('electron');app.disableHardwareAcceleration();app.enableSandbox();
const owned=fs.mkdtempSync(path.join(os.tmpdir(),'safetynet-upload-probe-'));app.setPath('userData',owned);
const {createServer}=require('node:http');let server,win;const report={electron:process.versions.electron,productionEnabled:false};
app.whenReady().then(async()=>{
const original=Buffer.from('PUBLIC IMMUTABLE FILE CONTENT'),changed=Buffer.from('SECRET MUTATED FILE CONTENT!!');const file=path.join(owned,'fixture.txt');fs.writeFileSync(file,original);
const received=[];server=createServer(async(req,res)=>{const chunks=[];for await(const chunk of req)chunks.push(chunk);received.push({url:req.url,headers:req.headers,bytes:Buffer.concat(chunks)});if(req.url==='/redirect'){res.writeHead(307,{location:'/redirect-target'});res.end();return;}res.setHeader('content-type','text/html');res.end('<input id="file" type="file"><script>async function upload(){let f=new FormData();f.append("document",document.querySelector("input").files[0]);return fetch("/upload",{method:"POST",body:f}).then(r=>r.text());}</script>');}).listen(0,'127.0.0.1');await new Promise(r=>server.once('listening',r));
const origin=`http://127.0.0.1:${server.address().port}`,ses=session.fromPartition('upload-proof');let snapshot;
ses.protocol.handle('http',async request=>{
if(new URL(request.url).origin!==origin)return new Response('Denied',{status:403});
const body=request.body?Buffer.from(await request.arrayBuffer()):undefined;
if(request.url.includes('/cookie-')){report.requestCredentials??={};report.requestCredentials[new URL(request.url).pathname]=request.credentials;report.requestCookiePresence??={};report.requestCookiePresence[new URL(request.url).pathname]=request.headers.has('cookie');}
if(request.method==='POST'){snapshot=body;report.requestBodyAvailable=Boolean(body?.length);report.initiatorOrigin=request.initiatorOrigin||null;fs.writeFileSync(file,changed);report.mutatedAfterSnapshot=true;}
try{return await ses.fetch(request.url,{method:request.method,headers:request.headers,body:body?new Blob([body]):undefined,redirect:'error',bypassCustomProtocolHandlers:true});}catch{return Response.error();}
});
win=new BrowserWindow({show:false,webPreferences:{session:ses,sandbox:true,contextIsolation:true,nodeIntegration:false}});await win.loadURL(origin);
win.webContents.debugger.attach('1.3');const {root}=await win.webContents.debugger.sendCommand('DOM.getDocument');const {nodeId}=await win.webContents.debugger.sendCommand('DOM.querySelector',{nodeId:root.nodeId,selector:'#file'});await win.webContents.debugger.sendCommand('DOM.setFileInputFiles',{nodeId,files:[file]});
await win.webContents.executeJavaScript('upload()');const upload=received.find(r=>r.url==='/upload');assert(upload);assert(snapshot);assert.deepEqual(upload.bytes,snapshot);assert(upload.bytes.includes(original));assert(!upload.bytes.includes(changed));report.receiverSha256=crypto.createHash('sha256').update(upload.bytes).digest('hex');report.snapshotSha256=crypto.createHash('sha256').update(snapshot).digest('hex');report.exactBytes=true;
await ses.cookies.set({url:origin,name:'synthetic_session',value:'fixture',sameSite:'strict'});
await win.webContents.executeJavaScript('fetch("/cookie-include",{credentials:"include"}).then(r=>r.text())');
await win.webContents.executeJavaScript('fetch("/cookie-omit",{credentials:"omit"}).then(r=>r.text())');
report.includeCookie=Boolean(received.find(r=>r.url==='/cookie-include').headers.cookie);
report.omitCookie=Boolean(received.find(r=>r.url==='/cookie-omit').headers.cookie);
report.credentialsPreserved=report.includeCookie&&!report.omitCookie;
// A known unsafe expansion is asserted here so the evidence cannot be mistaken
// for approval to ship the transparent bridge. No real credentials are used.
assert.equal(report.credentialsPreserved,false,'Reassess Electron credential behavior before integration');
report.redirectDenied=await win.webContents.executeJavaScript('fetch("/redirect").then(()=>false,()=>true)');
assert.equal(report.redirectDenied,true);assert.equal(received.some(r=>r.url==='/redirect-target'),false);
fs.mkdirSync(path.resolve('artifacts'),{recursive:true});fs.writeFileSync('artifacts/immutable-upload-probe.json',JSON.stringify(report,null,2));console.log(JSON.stringify(report));
}).catch(error=>{console.error(error);process.exitCode=1;}).finally(async()=>{win?.destroy();if(server){server.closeAllConnections();await new Promise(r=>server.close(r));}app.exit(process.exitCode||0);});
}
+22
View File
@@ -0,0 +1,22 @@
'use strict';
const {app,BrowserWindow}=require('electron'),assert=require('node:assert/strict'),fs=require('node:fs'),path=require('node:path');
app.disableHardwareAcceleration();app.enableSandbox();app.setPath('userData',process.env.SAFETYNET_ADMIN_SMOKE_PROFILE);let window;const deadline=setTimeout(()=>app.exit(1),50000);
const evaluate=source=>window.webContents.executeJavaScript(source,true);
async function waitFor(source){const until=Date.now()+12000;while(Date.now()<until){if(await evaluate(source))return;await new Promise(r=>setTimeout(r,75));}throw Error('Incident UI state missing: '+await evaluate(`document.getElementById('status').textContent`));}
app.whenReady().then(async()=>{
window=new BrowserWindow({show:false,width:1500,height:1100,webPreferences:{nodeIntegration:false,contextIsolation:true,sandbox:true,offscreen:true,backgroundThrottling:false}});await window.loadURL(process.env.SAFETYNET_ADMIN_SMOKE_URL);
assert.deepEqual(await evaluate(`({node:typeof process,require:typeof require})`),{node:'undefined',require:'undefined'});assert.ok((await evaluate(`fetch(location.href).then(r=>r.headers.get('content-security-policy'))`)).includes("script-src 'self'"));
await evaluate(`document.getElementById('token').value=${JSON.stringify(process.env.SAFETYNET_ADMIN_SMOKE_TOKEN)};document.getElementById('connect').click()`);await waitFor(`document.getElementById('status').textContent.includes('Connected')`);
await evaluate(`document.querySelector('[data-incident-create]').click()`);await waitFor(`!document.getElementById('incident-detail').hidden`);assert.equal(await evaluate(`document.getElementById('incident-event').textContent.includes('NEVER_SHOW_DOCUMENT_CONTENT')`),false);
await evaluate(`document.getElementById('incident-state').value='investigating';document.getElementById('incident-severity').value='high';document.getElementById('incident-assignee').value='Synthetic SOC';document.getElementById('incident-comment').value='Synthetic investigation started. <img src=x onerror=alert(1)>';document.getElementById('incident-save').click()`);await waitFor(`document.getElementById('incident-revision').textContent.includes('revision 2')`);
assert.ok(await evaluate(`document.getElementById('incident-history').textContent.includes('Synthetic investigation started. <img src=x onerror=alert(1)>')`));assert.equal(await evaluate(`document.querySelectorAll('#incident-history img').length`),0);
const id=await evaluate(`document.querySelector('#incident-rows tr').dataset.incidentId`);
await evaluate(`fetch('/api/admin/incidents/'+${JSON.stringify(id)},{method:'PATCH',headers:{authorization:'Bearer '+${JSON.stringify(process.env.SAFETYNET_ADMIN_SMOKE_TOKEN)},'content-type':'application/json'},body:JSON.stringify({expectedRevision:2,status:'resolved'})}).then(r=>{if(!r.ok)throw Error('Concurrent synthetic update failed')})`);
await evaluate(`document.getElementById('incident-comment').value='Preserved concurrent edit';document.getElementById('incident-save').click()`);await waitFor(`document.getElementById('incident-detail-status').textContent.includes('revision conflict')`);assert.equal(await evaluate(`document.getElementById('incident-comment').value`),'Preserved concurrent edit');
await evaluate(`document.getElementById('incident-detail-refresh').click()`);await waitFor(`document.getElementById('incident-revision').textContent.includes('revision 3')`);
await evaluate(`document.getElementById('incident-status-filter').value='open';document.getElementById('incident-status-filter').dispatchEvent(new Event('change'))`);await waitFor(`document.querySelectorAll('#incident-rows tr').length===0`);
await evaluate(`document.getElementById('incident-status-filter').value='resolved';document.getElementById('incident-status-filter').dispatchEvent(new Event('change'))`);await waitFor(`document.querySelectorAll('#incident-rows tr').length===1`);
await window.webContents.session.cookies.set({url:process.env.SAFETYNET_ADMIN_SMOKE_URL,name:'sn_session',value:process.env.SAFETYNET_INCIDENT_AUDITOR_TOKEN,httpOnly:true,sameSite:'lax'});await window.reload();await waitFor(`document.getElementById('status').textContent.includes('Connected')`);await evaluate(`document.querySelector('#incident-rows button').click()`);await waitFor(`!document.getElementById('incident-detail').hidden`);assert.equal(await evaluate(`document.getElementById('incident-save').disabled`),true);assert.equal(await evaluate(`document.querySelector('[data-incident-create]').disabled`),true);
const forbidden=await evaluate(`fetch('/api/admin/incidents/'+${JSON.stringify(id)},{method:'PATCH',headers:{'content-type':'application/json'},body:JSON.stringify({expectedRevision:3,status:'open'})}).then(r=>r.status)`);assert.equal(forbidden,403);
await evaluate(`document.getElementById('incidents').scrollIntoView()`);await new Promise(r=>setTimeout(r,250));fs.mkdirSync('artifacts',{recursive:true});fs.writeFileSync(path.resolve('artifacts/incident-admin.png'),(await window.webContents.capturePage()).toPNG());console.log('INCIDENT_ADMIN_PROOF_OK');clearTimeout(deadline);window.destroy();app.exit(0);
}).catch(error=>{console.error('INCIDENT_ADMIN_PROOF_FAILED',error.stack);clearTimeout(deadline);window?.destroy();app.exit(1);});
+29
View File
@@ -0,0 +1,29 @@
// Finite, isolated administrator workflow proof using actual UI and HTTP routes.
import assert from 'node:assert/strict';
import { createRequire } from 'node:module';
import { createServer } from 'node:net';
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join, resolve, sep, basename } from 'node:path';
import { spawn } from 'node:child_process';
import { randomBytes } from 'node:crypto';
import { digest } from '../apps/server/store.mjs';
import { openStore } from '../apps/server/store.mjs';
import { createApp } from '../apps/server/app.mjs';
import { verifyPolicy } from '../packages/core/policy.mjs';
const require=createRequire(import.meta.url),directory=mkdtempSync(join(tmpdir(),'safetynet-incident-admin-smoke-'));
let store,server,child;
try{
store=openStore(join(directory,'management'));const adminToken=randomBytes(32).toString('base64url'),config={adminToken,publicUrl:'http://127.0.0.1',secure:false};
store.event('synthetic-device','dlp.blocked',{decision:'block',ruleId:'synthetic-rule',policyVersion:1,prompt:'NEVER_SHOW_DOCUMENT_CONTENT'});
const auditorToken=randomBytes(32).toString('base64url');store.db.prepare('INSERT INTO sessions VALUES(?,?,?)').run(digest(auditorToken),Date.now()+60000,JSON.stringify({sub:'incident-auditor',role:'auditor'}));
server=createApp(store,config).listen(0,'127.0.0.1');await new Promise(r=>server.once('listening',r));config.publicUrl=`http://127.0.0.1:${server.address().port}`;
const env={...process.env,SAFETYNET_ADMIN_SMOKE_PROFILE:join(directory,'browser'),SAFETYNET_ADMIN_SMOKE_URL:config.publicUrl,SAFETYNET_ADMIN_SMOKE_TOKEN:adminToken,SAFETYNET_INCIDENT_AUDITOR_TOKEN:auditorToken};delete env.ELECTRON_RUN_AS_NODE;
child=spawn(require('electron'),['scripts/incident-admin-smoke.cjs'],{env,windowsHide:true,stdio:['ignore','pipe','pipe']});child.stdout.on('data',data=>{if(String(data).includes('INCIDENT_ADMIN_PROOF_OK'))console.log('Incident administrator interface workflow passed.');});child.stderr.on('data',data=>{if(String(data).includes('INCIDENT_ADMIN_PROOF_'))console.error(String(data).trim());});
const timer=setTimeout(()=>child.kill(),60000),code=await new Promise(r=>{child.once('exit',code=>r(code??1));child.once('error',()=>r(1));});clearTimeout(timer);assert.equal(code,0,'Incident administrator interface proof failed');
const row=store.db.prepare('SELECT * FROM incident_cases').get();assert.equal(row.revision,3);assert.equal(row.status,'resolved');assert.equal(row.assignee,'Synthetic SOC');
const report={actualAdministratorUi:true,createFromSecurityEvent:true,statusSeverityAssignment:true,revisionConflictPreservesEdits:true,historyShown:true,adversarialNotesRenderedAsText:true,filters:true,auditorReadOnly:true,rawContentExcluded:true,noNode:true,cspPreserved:true};mkdirSync('artifacts',{recursive:true});writeFileSync('artifacts/incident-admin-proof.json',JSON.stringify(report,null,2));console.log(JSON.stringify(report));
}finally{
child?.kill();if(server)await new Promise(r=>{server.closeAllConnections?.();server.close(r);});store?.db.close();const target=resolve(directory);if(!target.startsWith(resolve(tmpdir())+sep)||!basename(target).startsWith('safetynet-incident-admin-smoke-'))throw Error('Unsafe proof cleanup');rmSync(target,{recursive:true,force:true,maxRetries:10,retryDelay:100});
}
@@ -0,0 +1,35 @@
'use strict';
const {app,BrowserWindow,session}=require('electron'),assert=require('node:assert/strict'),fs=require('node:fs'),path=require('node:path');
app.disableHardwareAcceleration();app.enableSandbox();app.setPath('userData',process.env.SAFETYNET_ADMIN_SMOKE_PROFILE);
let window;const deadline=setTimeout(()=>app.exit(1),55000);const evaluate=s=>window.webContents.executeJavaScript(s,true);
async function waitFor(s){for(let n=0;n<200;n++){if(await evaluate(s))return;await new Promise(r=>setTimeout(r,60));}throw Error('UI state timeout: '+s+' | '+await evaluate(`document.getElementById('status').textContent`));}
async function identity(value){await session.defaultSession.cookies.set({url:process.env.SAFETYNET_ADMIN_SMOKE_URL,name:'sn_session',value,httpOnly:true,sameSite:'strict'});await window.loadURL(process.env.SAFETYNET_ADMIN_SMOKE_URL);await waitFor(`!document.getElementById('workspace').hidden&&document.getElementById('reviews-status').textContent.includes('loaded')`);}
async function prepare(name){await evaluate(`document.getElementById('status').textContent='Preparing';document.getElementById('brand-name').value=${JSON.stringify(name)};document.getElementById('publish').click()`);await waitFor(`document.getElementById('status').textContent.includes('prepared for independent approval')`);}
app.whenReady().then(async()=>{
window=new BrowserWindow({show:false,width:1500,height:1100,webPreferences:{nodeIntegration:false,contextIsolation:true,sandbox:true,offscreen:true,backgroundThrottling:false}});
await identity('synthetic-review-author');assert.equal(await evaluate('typeof require'),'undefined');
assert.equal(await evaluate(`document.getElementById('publish').textContent`),'Prepare for independent approval');
await prepare('Independently approved');await prepare('Stale candidate');await prepare('Rejected candidate');
assert.equal(await evaluate(`document.getElementById('policy-version').textContent`),'v1');
await evaluate(`document.querySelector('#reviews-rows button').click()`);await waitFor(`!document.getElementById('independent-review-detail').hidden`);
assert.equal(await evaluate(`document.getElementById('independent-review-approve').disabled`),true);
const self=await evaluate(`fetch('/api/admin/policy-reviews/'+selectedIndependentReview.id+'/approve',{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify({payloadHash:selectedIndependentReview.payloadHash,expectedVersion:selectedIndependentReview.expectedVersion,approve:true})}).then(r=>r.status)`);assert.equal(self,403);
await identity('synthetic-review-admin');
await evaluate(`document.querySelector('#reviews-rows button').click()`);await waitFor(`!document.getElementById('independent-review-detail').hidden`);
assert.ok((await evaluate(`document.getElementById('independent-review-diff').textContent`)).includes('Rejected candidate'));
await evaluate(`document.getElementById('independent-review-reject').click()`);await waitFor(`document.getElementById('reviews-rows').textContent.includes('rejected')`);
await evaluate(`document.querySelectorAll('#reviews-rows button')[2].click()`);await waitFor(`!document.getElementById('independent-review-detail').hidden`);
assert.ok((await evaluate(`document.getElementById('independent-review-diff').textContent`)).includes('Independently approved'));
await evaluate(`document.getElementById('independent-review-confirm').checked=true;document.getElementById('independent-review-confirm').dispatchEvent(new Event('change'));document.getElementById('independent-review-approve').click()`);await waitFor(`document.getElementById('policy-version').textContent==='v2'`);
assert.ok((await evaluate(`document.getElementById('reviews-rows').textContent`)).includes('stale'));
await evaluate(`document.querySelectorAll('#reviews-rows button')[1].click()`);await waitFor(`document.getElementById('independent-review-title').textContent.includes('stale')`);assert.equal(await evaluate(`document.getElementById('independent-review-approve').disabled`),true);
await evaluate(`document.getElementById('policy-reviews').scrollIntoView();document.getElementById('console-theme').value='dark';document.getElementById('console-theme').dispatchEvent(new Event('change'))`);await new Promise(r=>setTimeout(r,200));fs.mkdirSync('artifacts',{recursive:true});fs.writeFileSync(path.resolve('artifacts/independent-review-admin.png'),(await window.webContents.capturePage()).toPNG());
await identity('synthetic-review-operator');assert.equal(await evaluate(`document.getElementById('publish').disabled`),false);await prepare('Operator proposed');assert.equal(await evaluate(`document.getElementById('policy-version').textContent`),'v2');await evaluate(`document.querySelector('#reviews-rows button').click()`);await waitFor(`!document.getElementById('independent-review-detail').hidden`);assert.equal(await evaluate(`document.getElementById('independent-review-approve').disabled`),true);
await evaluate(`document.getElementById('status').textContent='Preparing inspection';Array.from(document.querySelectorAll('#device-rows button')).find(button=>button.textContent==='Enable manual document scans').click()`);await waitFor(`document.getElementById('status').textContent.includes('prepared for independent approval')`);
assert.equal(await evaluate(`document.getElementById('policy-version').textContent`),'v2');assert.ok(await evaluate(`Array.from(document.querySelectorAll('#device-rows button')).some(button=>button.textContent==='Enable manual document scans')`));
await identity('synthetic-review-admin');await evaluate(`document.querySelector('#reviews-rows button').click()`);await waitFor(`!document.getElementById('independent-review-detail').hidden`);
const operation=await evaluate(`document.getElementById('independent-review-operation').textContent`);assert.ok(operation.includes('synthetic-bookmark-device'));assert.ok(operation.includes('Enable'));assert.ok(operation.includes('Mandatory upload DLP'));
await evaluate(`document.getElementById('independent-review-confirm').checked=true;document.getElementById('independent-review-confirm').dispatchEvent(new Event('change'));document.getElementById('independent-review-approve').click()`);await waitFor(`document.getElementById('policy-version').textContent==='v3'`);assert.ok(await evaluate(`Array.from(document.querySelectorAll('#device-rows button')).some(button=>button.textContent==='Disable manual document scans')`));
console.log('INDEPENDENT_ADMIN_PROOF_OK');clearTimeout(deadline);window.destroy();app.exit(0);
}).catch(error=>{console.error('INDEPENDENT_ADMIN_PROOF_FAILED',error.message);clearTimeout(deadline);window?.destroy();app.exit(1);});
@@ -0,0 +1,28 @@
// Finite, isolated administrator workflow proof using actual UI and HTTP routes.
import assert from 'node:assert/strict';
import { createRequire } from 'node:module';
import { createServer } from 'node:net';
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join, resolve, sep, basename } from 'node:path';
import { spawn } from 'node:child_process';
import { randomBytes } from 'node:crypto';
import { openStore, digest } from '../apps/server/store.mjs';
import { createApp } from '../apps/server/app.mjs';
import { verifyPolicy } from '../packages/core/policy.mjs';
const require=createRequire(import.meta.url),directory=mkdtempSync(join(tmpdir(),'safetynet-independent-review-admin-smoke-'));
let store,server,child;
try{
store=openStore(join(directory,'management'));const adminToken=randomBytes(32).toString('base64url'),config={adminToken,publicUrl:'http://127.0.0.1',secure:false,requireIndependentPolicyApproval:true};
for(const [credential,role,sub] of [['synthetic-review-author','admin','synthetic-author'],['synthetic-review-admin','admin','synthetic-reviewer'],['synthetic-review-operator','operator','synthetic-operator']])store.db.prepare('INSERT INTO sessions VALUES(?,?,?)').run(digest(credential),Date.now()+3600000,JSON.stringify({sub,role}));
store.db.prepare('INSERT INTO devices(id,name,platform,user,token_hash,last_seen) VALUES(?,?,?,?,?,?)').run('synthetic-bookmark-device','Synthetic bookmark device','win32','synthetic-user','synthetic-unused',new Date().toISOString());
store.db.prepare('UPDATE devices SET document_analysis_enabled=0 WHERE id=?').run('synthetic-bookmark-device');
server=createApp(store,config).listen(0,'127.0.0.1');await new Promise(r=>server.once('listening',r));config.publicUrl=`http://127.0.0.1:${server.address().port}`;
const env={...process.env,SAFETYNET_ADMIN_SMOKE_PROFILE:join(directory,'browser'),SAFETYNET_ADMIN_SMOKE_URL:config.publicUrl,SAFETYNET_ADMIN_SMOKE_TOKEN:adminToken};delete env.ELECTRON_RUN_AS_NODE;
child=spawn(require('electron'),['scripts/independent-review-admin-smoke.cjs'],{env,windowsHide:true,stdio:['ignore','pipe','pipe']});child.stdout.on('data',data=>{if(String(data).includes('INDEPENDENT_ADMIN_PROOF_OK'))console.log('Independent policy approval administrator interface workflow passed.');});child.stderr.on('data',data=>{const text=String(data);if(text.includes('INDEPENDENT_ADMIN_PROOF_'))console.error(text.trim());});
const timer=setTimeout(()=>child.kill(),60000),code=await new Promise(r=>{child.once('exit',code=>r(code??1));child.once('error',()=>r(1));});clearTimeout(timer);assert.equal(code,0,'Independent policy approval administrator interface proof failed');
const policy=verifyPolicy(store.envelope(),store.publicKey());assert.equal(policy.version,3);assert.equal(store.db.prepare('SELECT document_analysis_enabled FROM devices WHERE id=?').get('synthetic-bookmark-device').document_analysis_enabled,1);assert.equal(policy.brand.name,'Independently approved');
const report={actualAdministratorUi:true,mandatoryIndependentApproval:true,payloadDiff:true,selfApprovalHttpDenied:true,distinctReviewer:true,operatorPrepareOnly:true,inspectionOperationVisible:true,inspectionUnchangedUntilApproval:true,rejectedAndStaleVisible:true,publishedOnlyAfterApproval:true,nodeUnavailable:true};mkdirSync('artifacts',{recursive:true});writeFileSync('artifacts/independent-review-admin-proof.json',JSON.stringify(report,null,2));console.log(JSON.stringify(report));
}finally{
child?.kill();if(server)await new Promise(r=>{server.closeAllConnections?.();server.close(r);});store?.db.close();const target=resolve(directory);if(!target.startsWith(resolve(tmpdir())+sep)||!basename(target).startsWith('safetynet-independent-review-admin-smoke-'))throw Error('Unsafe proof cleanup');rmSync(target,{recursive:true,force:true,maxRetries:10,retryDelay:100});
}
+12
View File
@@ -0,0 +1,12 @@
import { existsSync, readFileSync, writeFileSync, appendFileSync } from 'node:fs';
import { randomBytes } from 'node:crypto';
if(existsSync('.env'))console.log('.env already exists; preserved existing configuration.');
else {const template=readFileSync('.env.example','utf8');writeFileSync('.env',template.replace('ADMIN_TOKEN=','ADMIN_TOKEN='+randomBytes(32).toString('base64url')),{mode:0o600});console.log('Created .env with a random bootstrap administrator token. Open .env locally to use it; never commit this file.');}
let existing=readFileSync('.env','utf8');
if(!/^INSPECTOR_URL=/m.test(existing)){appendFileSync('.env','\nINSPECTOR_URL=http://127.0.0.1:4311\n');existing=readFileSync('.env','utf8');}
if(!/^INSPECTOR_TOKEN=.+/m.test(existing)){
const secret=randomBytes(32).toString('base64url');
if(/^INSPECTOR_TOKEN=/m.test(existing))writeFileSync('.env',existing.replace(/^INSPECTOR_TOKEN=.*$/m,'INSPECTOR_TOKEN='+secret),{mode:0o600});
else appendFileSync('.env','INSPECTOR_TOKEN='+secret+'\n',{mode:0o600});
console.log('Configured a private inspector credential.');
}
+12
View File
@@ -0,0 +1,12 @@
import { spawn } from 'node:child_process';
import { resolve } from 'node:path';
import {createRequire} from 'node:module';
const files=createRequire(import.meta.url)('../apps/browser/inspection.cjs').privateInspectorPaths(resolve('.'));
if(!files)throw Error('Provision the private Windows runtime; external or linked inspector overrides are rejected');
const {python,script}=files;
const environment={...process.env,INSPECTOR_PARENT_PID:String(process.pid)};
environment.EMBEDDING_MODEL_DIR ||= resolve('.runtime/windows/semantic/models');
environment.EMBEDDING_WORKER_PATH ||= resolve('.runtime/windows/semantic/searchi-gemma-worker.exe');
for(const key of ['ADMIN_TOKEN','OIDC_CLIENT_SECRET','AI_API_KEY','SIEM_HTTP_TOKEN','SIEM_KEY_FILE'])delete environment[key];
const child=spawn(python,[script],{stdio:'inherit',env:environment,windowsHide:true});
process.on('SIGINT',()=>child.kill());process.on('SIGTERM',()=>child.kill());child.on('exit',code=>process.exit(code??1));
+26
View File
@@ -0,0 +1,26 @@
const {app,BrowserWindow,safeStorage}=require('electron');
const fs=require('node:fs'),path=require('node:path');
const assert=require('node:assert/strict');
app.setPath('userData',process.env.SAFETYNET_SETTINGS_PROFILE);app.setPath('sessionData',process.env.SAFETYNET_SETTINGS_PROFILE);app.disableHardwareAcceleration();
process.env.SAFETYNET_SMOKE_USERDATA=process.env.SAFETYNET_SETTINGS_PROFILE;
require('../apps/browser/main.cjs');
const wait=ms=>new Promise(resolve=>setTimeout(resolve,ms));
const deadline=setTimeout(()=>app.exit(1),90000);
app.whenReady().then(async()=>{try{
let win;for(let i=0;i<150;i++){win=BrowserWindow.getAllWindows()[0];if(win&&!win.webContents.isLoading()&&win.webContents.getURL().endsWith('index.html'))break;await wait(100);}assert.ok(win,'Trusted shell unavailable');
const call=(name,input)=>win.webContents.executeJavaScript(`window.safetynet[${JSON.stringify(name)}](${JSON.stringify(input)??''})`);
const enrolled=await call('enroll',{server:process.env.SAFETYNET_SETTINGS_SERVER,code:process.env.SAFETYNET_SETTINGS_CODE});assert.equal(enrolled.ok,true,'Enrollment failed');assert.equal(enrolled.data.ready,true,'Management did not become ready');
const enrollment=JSON.parse(safeStorage.decryptString(Buffer.from(JSON.parse(fs.readFileSync(path.join(process.env.SAFETYNET_SETTINGS_PROFILE,'enrollment.json'),'utf8')).encryptedEnrollment,'base64')));
assert.equal((await fetch(`${process.env.SAFETYNET_SETTINGS_SERVER}/api/device/policy`,{headers:{authorization:`Bearer ${enrollment.token}`}})).status,403,'Plaintext policy route was not rejected');
async function state(){return (await call('state')).data;}
async function rejected(name,input){assert.equal((await call(name,input)).ok,false,`Privileged ${name} bypassed administrator settings`);}
assert.deepEqual((await state()).settings.appearance,{mode:'dark',accent:'violet',tabMode:'compact'});
await rejected('updateSettings',{mode:'light'});await rejected('vaultStatus');await rejected('vaultCreate','synthetic-not-a-real-password');await rejected('vaultSave',{});await rejected('inspectFile');await rejected('agentConnection');assert.equal((await call('vaultLock')).ok,true);
const headers={authorization:`Bearer ${process.env.SAFETYNET_SETTINGS_ADMIN}`,'content-type':'application/json'};
async function publish(settings){const overview=await (await fetch(`${process.env.SAFETYNET_SETTINGS_SERVER}/api/admin/overview`,{headers})).json();const policy=overview.policy;assert.ok(policy,'Admin policy unavailable');policy.version++;policy.browser.settings=settings;const response=await fetch(`${process.env.SAFETYNET_SETTINGS_SERVER}/api/admin/policy`,{method:'PUT',headers,body:JSON.stringify(policy)});assert.equal(response.status,200,'Central policy publication failed');for(let i=0;i<100;i++){const current=await state();if(current.ready&&current.policyVersion===policy.version)return current;await wait(100);}throw Error('Live central settings update timed out');}
await publish({visible:false,hiddenSections:[],lockedSections:[],appearance:{mode:'light',accent:'teal',tabMode:'separate'}});
await rejected('setChromeLayout',{height:104,sidebarOpen:false,startPageOpen:false,overviewOpen:false,toolsOpen:true});await rejected('updateSettings',{mode:'dark'});assert.equal((await call('toggleAI',true)).ok,true,'Hiding settings disabled approved AI use');await call('toggleAI',false);assert.equal((await call('vaultLock')).ok,true);
const opened=await publish({visible:true,hiddenSections:[],lockedSections:[],appearance:{mode:'system',accent:'blue',tabMode:'separate'}});assert.equal(opened.settings.visible,true);const change=await call('updateSettings',{mode:'dark',accent:'teal',tabMode:'compact'});assert.equal(change.ok,true);assert.deepEqual(change.data.appearance,{mode:'dark',accent:'teal',tabMode:'compact'});
const ui=await win.webContents.executeJavaScript('({theme:document.documentElement.dataset.theme,accent:document.documentElement.dataset.accent,tabMode:document.documentElement.dataset.tabMode})');assert.deepEqual(ui,{theme:'dark',accent:'teal',tabMode:'compact'});
console.log(JSON.stringify({nativeSettingsEnforcement:true,liveCentralUpdate:true,directIPCBypassRejected:true}));clearTimeout(deadline);app.quit();
}catch(error){console.error(JSON.stringify({nativeSettingsEnforcement:false,error:error.message}));clearTimeout(deadline);app.exit(1);}});
+31
View File
@@ -0,0 +1,31 @@
// Actual signed central publication and native browser IPC, isolated synthetic device.
import assert from 'node:assert/strict';
import {createRequire} from 'node:module';
import {createServer} from 'node:http';
import {mkdtempSync,mkdirSync,writeFileSync} from 'node:fs';
import {tmpdir} from 'node:os';
import {join} from 'node:path';
import {spawn} from 'node:child_process';
import {randomBytes} from 'node:crypto';
import {createApp} from '../apps/server/app.mjs';
import {openStore,digest} from '../apps/server/store.mjs';
const electron=createRequire(import.meta.url)('electron');
const temporary=mkdtempSync(join(tmpdir(),'safetynet-managed-settings-'));
let store,management,sink,child;
try{
const adminToken=randomBytes(32).toString('base64url'),code=randomBytes(32).toString('base64url');
sink=createServer((_req,res)=>{res.setHeader('content-type','text/html');res.end('<!doctype html><title>Managed settings fixture</title><h1>Public local test page</h1>');}).listen(0,'127.0.0.1');
await new Promise(resolve=>sink.once('listening',resolve));
store=openStore(join(temporary,'management.sqlite'));
const initial=store.get('policy');initial.browser.homeUrl=`http://127.0.0.1:${sink.address().port}`;initial.browser.allowedHosts=['127.0.0.1'];initial.browser.settings={visible:true,hiddenSections:['passwords','documentScan','agents'],lockedSections:['appearance'],appearance:{mode:'dark',accent:'violet',tabMode:'compact'}};store.put('policy',initial);
store.db.prepare('INSERT INTO enrollments VALUES(?,?,?)').run(digest(code),Date.now()+600000,'synthetic-settings-user');
const config={publicUrl:'http://127.0.0.1',secure:false,adminToken,requirePQManagement:true};
management=createApp(store,config).listen(0,'127.0.0.1');await new Promise(resolve=>management.once('listening',resolve));config.publicUrl=`http://127.0.0.1:${management.address().port}`;
const env={...process.env,SAFETYNET_SETTINGS_PROFILE:join(temporary,'browser'),SAFETYNET_SETTINGS_SERVER:config.publicUrl,SAFETYNET_SETTINGS_CODE:code,SAFETYNET_SETTINGS_ADMIN:adminToken};delete env.ELECTRON_RUN_AS_NODE;
child=spawn(electron,['scripts/managed-settings-smoke.cjs'],{windowsHide:true,stdio:'inherit',env});const timer=setTimeout(()=>child.kill(),100000);
const status=await new Promise(resolve=>{child.once('exit',code=>resolve(code??1));child.once('error',()=>resolve(1));});clearTimeout(timer);assert.equal(status,0,'Native managed settings proof failed');
const report={native:true,centralSignedPublication:true,plaintextPolicyRejected:true,lockedAppearanceDirectIPCRejected:true,hiddenSectionsDirectIPCRejected:true,globalSettingsHiddenRejected:true,liveUnlockApplied:true,vaultLockAlwaysAvailable:true,contentPersisted:false};
mkdirSync('artifacts',{recursive:true});writeFileSync('artifacts/managed-settings-proof.json',JSON.stringify(report,null,2));console.log(JSON.stringify(report));
}finally{
child?.kill();for(const server of [management,sink])if(server){server.closeAllConnections();await new Promise(resolve=>server.close(resolve));}store?.db.close();
}
+35
View File
@@ -0,0 +1,35 @@
const {app,BrowserWindow,webContents}=require('electron');const assert=require('node:assert/strict'),fs=require('node:fs'),path=require('node:path');
app.setPath('userData',process.env.SAFETYNET_TABS_USERDATA);app.disableHardwareAcceleration();require('../apps/browser/main.cjs');
function finish(code){for(const contents of webContents.getAllWebContents()){if(contents.getURL().endsWith('index.html'))continue;require('../apps/browser/page-clipboard-guard.cjs').disposePageClipboardGuard(contents);}app.exit(code);}
const wait=ms=>new Promise(r=>setTimeout(r,ms));async function until(fn,label){for(let i=0;i<150;i++){if(await fn())return;await wait(100);}throw Error(label+' timed out');}
app.whenReady().then(async()=>{try{
let win;await until(()=>{win=BrowserWindow.getAllWindows()[0];return win&&!win.webContents.isLoading()&&win.webContents.getURL().endsWith('index.html');},'Shell');
const run=code=>win.webContents.executeJavaScript(code),state=async()=>{const r=await run('window.safetynet.state()');assert.equal(r.ok,true,r.error);return r.data;};
const invoke=async(method,value)=>{const r=await run(`window.safetynet[${JSON.stringify(method)}](${JSON.stringify(value)})`);assert.equal(r.ok,true,r.error);return r.data;};
await invoke('enroll',{server:process.env.SAFETYNET_TABS_SERVER,code:process.env.SAFETYNET_TABS_CODE});const base=process.env.SAFETYNET_TABS_SINK;
await until(async()=>{const s=await state();return s.tabs?.length===1&&s.tabs[0].url===base+'/';},'Initial managed native tab');
const aId=(await state()).activeTabId;const a=webContents.getAllWebContents().find(w=>w.getURL()===base+'/');assert.ok(a);await until(()=>!a.isLoading(),'Initial page');
assert.deepEqual(await a.executeJavaScript('({node:typeof require,bridge:typeof window.safetynet})'),{node:'undefined',bridge:'undefined'});
await a.executeJavaScript("document.getElementById('remember').value='A survives';window.scrollTo(0,800)");
const before=(await (await fetch(base+'/counts')).json()).requests['/'];
await run("document.getElementById('new-tab').click()");await until(async()=>{const s=await state();return s.tabs.length===2&&s.activeTabId!==aId;},'New tab UI');
const bId=(await state()).activeTabId;assert.equal((await state()).tabs.find(t=>t.id===bId).startPage,true);
await run(`document.getElementById('address').value=${JSON.stringify(base+'/b')};document.getElementById('address-form').requestSubmit()`);
await until(async()=>{const s=await state();return s.tabs.find(t=>t.id===bId)?.url===base+'/b';},'Second native page');const b=webContents.getAllWebContents().find(w=>w.getURL()===base+'/b');assert.ok(b);await until(()=>!b.isLoading(),'Second page');assert.notEqual(a.id,b.id);
await b.executeJavaScript("document.getElementById('remember').value='B survives'");
const clickTab=id=>run(`(()=>{const element=[...document.querySelectorAll('#tab-strip .browser-tab')].find(el=>el.dataset.tabId===${JSON.stringify(id)});if(!element)throw Error('Tab UI missing');element.querySelector('.tab-label').click()})()`);
await clickTab(aId);await until(async()=>(await state()).activeTabId===aId,'Switch A');assert.equal(await a.executeJavaScript("document.getElementById('remember').value"),'A survives');assert.equal(await a.executeJavaScript('Math.round(scrollY)'),800);assert.equal((await (await fetch(base+'/counts')).json()).requests['/'],before,'Selecting a tab reloaded it');
await a.executeJavaScript("document.getElementById('next').click()",true);await until(()=>a.getURL()===base+'/a-two'&&!a.isLoading(),'A history');await invoke('back');await until(()=>a.getURL()===base+'/'&&!a.isLoading(),'A back');
await clickTab(bId);await until(async()=>(await state()).activeTabId===bId,'Switch B');assert.equal(await b.executeJavaScript("document.getElementById('remember').value"),'B survives');await b.executeJavaScript("document.getElementById('next').click()",true);await until(()=>b.getURL()===base+'/b-two'&&!b.isLoading(),'B history');await invoke('back');await until(()=>b.getURL()===base+'/b'&&!b.isLoading(),'B back');assert.equal(a.getURL(),base+'/','B history changed A');
for(const page of [a,b]){const blocked=await page.executeJavaScript(`fetch(${JSON.stringify(base+'/blocked')},{method:'POST',body:'TAB_FIXTURE_SECRET'}).then(()=>false).catch(()=>true)`);assert.equal(blocked,true,'Inactive/active tab DLP bypass');assert.deepEqual(await page.executeJavaScript('({node:typeof require,bridge:typeof window.safetynet})'),{node:'undefined',bridge:'undefined'});assert.equal(await page.executeJavaScript('navigator.clipboard.writeText("TAB_FIXTURE_SECRET").then(()=>false).catch(()=>true)'),true,'Site clipboard bypass');}
fs.mkdirSync('artifacts',{recursive:true});fs.writeFileSync('artifacts/native-tabs.png',(await win.webContents.capturePage()).toPNG());
await invoke('closeTab',aId);assert.equal(a.isDestroyed(),true);await invoke('closeTab',bId);assert.equal(b.isDestroyed(),true);const final=await state();assert.equal(final.tabs.length,1);assert.equal(final.tabs[0].startPage,true);assert.notEqual(final.activeTabId,bId);await until(async()=>await run("!document.getElementById('start-page').hidden"),'Fresh start page');
const fresh=webContents.getAllWebContents().find(w=>w!==win.webContents&&w.getURL()==='about:blank');assert.ok(fresh,'Closing last tab did not create native replacement');assert.deepEqual(await fresh.executeJavaScript('({node:typeof require,bridge:typeof window.safetynet})'),{node:'undefined',bridge:'undefined'});
const revokedA=final.activeTabId;await invoke('navigate',{url:base+'/revoke-a',tabId:revokedA});await until(()=>webContents.getAllWebContents().some(w=>w.getURL()===base+'/revoke-a'&&!w.isLoading()),'Revocation A');const revokePageA=webContents.getAllWebContents().find(w=>w.getURL()===base+'/revoke-a');
await invoke('createTab',{});const revokedB=(await state()).activeTabId;await invoke('navigate',{url:base+'/revoke-b',tabId:revokedB});await until(()=>webContents.getAllWebContents().some(w=>w.getURL()===base+'/revoke-b'&&!w.isLoading()),'Revocation B');const revokePageB=webContents.getAllWebContents().find(w=>w.getURL()===base+'/revoke-b');
const collectorStatus=async()=>await (await fetch(process.env.SAFETYNET_TABS_COLLECTOR+'/status')).json();await until(async()=>{const status=await collectorStatus();return ['browser.ipc','browser.navigation','browser.dns','browser.request'].every(name=>status.names.includes(name))&&status.logs>0&&status.parentChild&&status.correlatedLogs;},'Actual native diagnostics export');
const enrolled=(await state()).deviceId;const response=await fetch(`${process.env.SAFETYNET_TABS_SERVER}/api/admin/devices/${enrolled}/revoke`,{method:'POST',headers:{Authorization:`Bearer ${process.env.SAFETYNET_TABS_ADMIN}`,'content-type':'application/json'},body:'{}'});assert.equal(response.status,200);await until(async()=>!(await state()).ready,'Central revocation');
for(const page of [revokePageA,revokePageB]){assert.equal(page.isDestroyed(),false,'Revocation proof lost native view before request assertion');assert.equal(await page.executeJavaScript(`fetch(${JSON.stringify(base+'/revoked-public')},{method:'POST',body:'Public after revocation'}).then(()=>false).catch(()=>true)`),true,'Revoked background/foreground page sent request');}
await wait(500);const stoppedExports=(await collectorStatus()).exports;for(let i=0;i<5;i++)await state();await wait(600);assert.equal((await collectorStatus()).exports,stoppedExports,'Revoked browser continued diagnostic export');
const report={actualNativeWebContents:true,actualChromeUi:true,independentDomAndScroll:true,noReloadOnSwitch:true,independentHistory:true,allTabsDlp:true,siteClipboardDenied:true,remoteNodeUnavailable:true,closedContentsDestroyed:true,lastTabFreshGuard:true,centralRevocationAllTabs:true,actualBrowserDiagnostics:true,diagnosticsStoppedOnRevocation:true};fs.mkdirSync('artifacts',{recursive:true});fs.writeFileSync('artifacts/native-tabs-proof.json',JSON.stringify(report,null,2));console.log('NATIVE_TABS_PROOF_OK '+JSON.stringify(report));finish(0);
}catch(error){console.error('NATIVE_TABS_PROOF_FAILED '+error.stack);finish(1);}});
+28
View File
@@ -0,0 +1,28 @@
import assert from 'node:assert/strict';
import {createServer} from 'node:http';
import {createRequire} from 'node:module';
import {mkdtempSync,rmSync,mkdirSync,writeFileSync} from 'node:fs';
import {tmpdir} from 'node:os';
import {join,resolve,sep,basename} from 'node:path';
import {spawn} from 'node:child_process';
import {randomBytes} from 'node:crypto';
import {createApp} from '../apps/server/app.mjs';
import {openStore,digest} from '../apps/server/store.mjs';
const require=createRequire(import.meta.url),directory=mkdtempSync(join(tmpdir(),'safetynet-native-tabs-'));
let sink,management,collector,store,child;const requests={},posts=[],diagnosticRequests=[];let privateSentinels=[];
const diagnosticStatus=()=>{const spans=diagnosticRequests.filter(r=>r.path.endsWith('/traces')).flatMap(r=>r.payload.resourceSpans||[]).flatMap(r=>r.scopeSpans||[]).flatMap(r=>r.spans||[]);const logs=diagnosticRequests.filter(r=>r.path.endsWith('/logs')).flatMap(r=>r.payload.resourceLogs||[]).flatMap(r=>r.scopeLogs||[]).flatMap(r=>r.logRecords||[]);return {exports:diagnosticRequests.length,names:[...new Set(spans.map(span=>span.name))],spans:spans.length,logs:logs.length,timings:spans.every(span=>BigInt(span.endTimeUnixNano)>=BigInt(span.startTimeUnixNano)&&span.attributes.some(a=>a.key==='safetynet.duration.ms')),parentChild:spans.some(child=>child.parentSpanId&&spans.some(parent=>parent.spanId===child.parentSpanId&&parent.traceId===child.traceId)),correlatedLogs:logs.some(log=>log.traceId&&spans.some(span=>span.traceId===log.traceId&&span.spanId===log.spanId)),sensitivePresent:privateSentinels.some(secret=>JSON.stringify(diagnosticRequests).includes(secret))};};
try{
collector=createServer((req,res)=>{if(req.method==='GET'&&req.url==='/status'){res.setHeader('content-type','application/json');res.end(JSON.stringify(diagnosticStatus()));return;}const chunks=[];req.on('data',chunk=>chunks.push(chunk));req.on('end',()=>{diagnosticRequests.push({path:req.url,payload:JSON.parse(Buffer.concat(chunks).toString())});res.setHeader('content-type','application/json');res.end('{}');});}).listen(0,'127.0.0.1');await new Promise(r=>collector.once('listening',r));const collectorUrl=`http://127.0.0.1:${collector.address().port}`;
sink=createServer((req,res)=>{const path=new URL(req.url,'http://localhost').pathname;requests[path]=(requests[path]||0)+1;
if(path==='/counts'){res.setHeader('content-type','application/json');res.end(JSON.stringify({requests,posts}));return;}
if(req.method==='POST'){posts.push(path);req.resume();res.end('received');return;}
res.setHeader('content-type','text/html');res.end(`<!doctype html><title>${path}</title><h1>Native tab ${path}</h1><input id="remember"><a id="next" href="${path==='/'?'/a-two':'/b-two'}">Next page</a><div style="height:4000px">Unstyled fixture content</div>`);
}).listen(0,'127.0.0.1');await new Promise(r=>sink.once('listening',r));const url=`http://127.0.0.1:${sink.address().port}`;
store=openStore(join(directory,'management'));const policy=store.get('policy');policy.diagnostics={...policy.diagnostics,enabled:true,mode:'debug',endpoint:collectorUrl,sampleRate:1,debugSampleRate:1,flushIntervalMs:250};policy.browser.homeUrl=url;policy.browser.allowedHosts=['127.0.0.1'];policy.dlp.rules=[{id:'fixture-secret',label:'Fixture secret',kind:'literal',value:'TAB_FIXTURE_SECRET',action:'block'}];store.put('policy',policy);
const code=randomBytes(32).toString('base64url'),adminToken=randomBytes(32).toString('base64url');privateSentinels=[code,adminToken,'TAB_FIXTURE_SECRET'];store.db.prepare('INSERT INTO enrollments VALUES(?,?,?)').run(digest(code),Date.now()+600000,'synthetic-native-tabs-user');
const config={adminToken,publicUrl:'http://127.0.0.1',secure:false};management=createApp(store,config).listen(0,'127.0.0.1');await new Promise(r=>management.once('listening',r));config.publicUrl=`http://127.0.0.1:${management.address().port}`;
const env={...process.env,SAFETYNET_TABS_COLLECTOR:collectorUrl,SAFETYNET_TABS_SERVER:config.publicUrl,SAFETYNET_TABS_CODE:code,SAFETYNET_TABS_ADMIN:adminToken,SAFETYNET_TABS_SINK:url,SAFETYNET_TABS_USERDATA:join(directory,'browser'),SAFETYNET_SMOKE_USERDATA:join(directory,'browser')};delete env.ELECTRON_RUN_AS_NODE;
child=spawn(require('electron'),['scripts/native-tabs-smoke.cjs'],{env,windowsHide:true,stdio:['ignore','pipe','pipe']});child.stdout.on('data',b=>process.stdout.write(b));child.stderr.on('data',b=>{const message=String(b).replaceAll(code,'[fixture enrollment]').replaceAll(adminToken,'[fixture admin]');process.stderr.write(message);});
const timer=setTimeout(()=>child.kill(),120000);const codeExit=await new Promise(r=>{child.once('exit',c=>r(c??1));child.once('error',()=>r(1));});clearTimeout(timer);assert.equal(codeExit,0,'Actual native tabs proof failed');
assert.equal(posts.length,0,'Blocked fixture data reached receiver');const diagnostics=diagnosticStatus();assert.ok(diagnostics.spans>0&&diagnostics.logs>0&&diagnostics.timings&&diagnostics.parentChild&&diagnostics.correlatedLogs);assert.equal(diagnostics.sensitivePresent,false);for(const name of ['browser.ipc','browser.navigation','browser.dns','browser.request'])assert.ok(diagnostics.names.includes(name),`Missing native timing ${name}`);writeFileSync('artifacts/native-browser-diagnostics-proof.json',JSON.stringify(diagnostics,null,2));mkdirSync('artifacts',{recursive:true});writeFileSync('artifacts/native-tabs-receiver-proof.json',JSON.stringify({noBlockedPosts:true,requests,posts},null,2));
}finally{child?.kill();for(const server of [management,sink,collector])if(server)await new Promise(r=>{server.closeAllConnections?.();server.close(r);});store?.db.close();const target=resolve(directory);if(!target.startsWith(resolve(tmpdir())+sep)||!basename(target).startsWith('safetynet-native-tabs-'))throw Error('Unsafe fixture cleanup');rmSync(target,{recursive:true,force:true,maxRetries:10,retryDelay:100});}
+23
View File
@@ -0,0 +1,23 @@
import { spawnSync } from 'node:child_process';
import {readFileSync,readdirSync} from 'node:fs';
import {createHash} from 'node:crypto';
import {createRequire} from 'node:module';
import path from 'node:path';
const platform=process.argv[2];if(platform!=='win'||process.platform!=='win32')throw Error('Windows is the active build target; other platforms are deferred');
const runtime=spawnSync(process.env.SAFETYNET_BUILD_PYTHON||'python',['scripts/provision-windows-runtime.py'],{stdio:'inherit'});if(runtime.status!==0)process.exit(runtime.status??1);
const semantic=spawnSync(process.env.SAFETYNET_BUILD_PYTHON||'python',['scripts/provision-semantic-runtime.py','--verify'],{stdio:'inherit'});if(semantic.status!==0)process.exit(semantic.status??1);
const name=process.env.BRAND_NAME||'SafetyNet',id=process.env.BRAND_APP_ID||'enterprise.safetynet.browser';
if(!/^[\w .-]{1,40}$/.test(name)||!/^[a-z][a-z0-9]*(?:\.[a-z][a-z0-9]*){2,}$/.test(id))throw Error('Invalid white-label product name or app ID');
const configuration=JSON.parse(readFileSync('package.json','utf8')),workspace=path.resolve('.'),output=path.resolve(configuration.build.directories.output);
if(!output.startsWith(workspace+path.sep))throw Error('Build output must stay inside the workspace');
// Reuse the pinned installed distribution already exercised by native tests.
// This avoids a second archive extraction and Windows directory-rename locks.
const electronDirectory=path.dirname(createRequire(import.meta.url)('electron'));
if(readFileSync(path.join(electronDirectory,'version'),'utf8').trim().replace(/^v/,'')!==configuration.devDependencies.electron)throw Error('Installed Electron does not match the build pin');
function sourceSnapshot(){const entries=[];function walk(directory){for(const item of readdirSync(directory,{withFileTypes:true})){const file=path.join(directory,item.name);if(item.isDirectory())walk(file);else if(item.isFile())entries.push([file,createHash('sha256').update(readFileSync(file)).digest('hex')]);}}for(const directory of ['apps/browser','packages/core'])walk(directory);entries.push(['package.json',createHash('sha256').update(readFileSync('package.json')).digest('hex')]);return JSON.stringify(entries.sort((a,b)=>a[0].localeCompare(b[0])));}
const sourcesBefore=sourceSnapshot();
const r=spawnSync(process.execPath,['node_modules/electron-builder/out/cli/cli.js',`--${platform}`,'--dir',`--config.electronDist=${electronDirectory}`,`--config.productName=${name}`,`--config.appId=${id}`],{stdio:'inherit',env:process.env});
if(r.status!==0)process.exit(r.status??1);
if(sourceSnapshot()!==sourcesBefore)throw Error('Browser sources changed during packaging; discard this artifact and rebuild from stable sources');
const resources=path.join(output,'win-unpacked/resources');
const acl=spawnSync(path.join(resources,'python/python.exe'),[path.join(resources,'inspector/provision_runtime_acl.py'),'--provision'],{stdio:'inherit',windowsHide:true});process.exit(acl.status??1);
+30
View File
@@ -0,0 +1,30 @@
'use strict';
if(!process.versions.electron){
const {spawnSync}=require('node:child_process');const env={...process.env};delete env.ELECTRON_RUN_AS_NODE;
const result=spawnSync(require('electron'),[__filename],{env,stdio:'inherit',windowsHide:true,timeout:45000});process.exit(result.status??1);
}else{
const {app,BrowserWindow,WebContentsView,session}=require('electron');
const fs=require('node:fs'),path=require('node:path'),https=require('node:https'),assert=require('node:assert/strict');
const {X509Certificate}=require('node:crypto');const {fillScript}=require('../apps/browser/password-fill.cjs');
app.enableSandbox();app.disableHardwareAcceleration();
app.whenReady().then(async()=>{let server,win;const views=[];try{
const cert=fs.readFileSync(path.join(__dirname,'../tests/fixtures/icap/cert.pem')),key=fs.readFileSync(path.join(__dirname,'../tests/fixtures/icap/key.pem'));
const fingerprint=new X509Certificate(cert).fingerprint256;
server=https.createServer({cert,key},(_req,res)=>{res.setHeader('content-type','text/html');res.end('<!doctype html><form method="post" action="/signin"><input name="username" autocomplete="username"><input type="password" autocomplete="current-password"></form>');}).listen(0,'127.0.0.1');await new Promise(r=>server.once('listening',r));
const origin=`https://127.0.0.1:${server.address().port}`,ses=session.fromPartition('password-focus-proof');
// Trust only this public synthetic certificate on loopback, in this fixture.
ses.setCertificateVerifyProc((request,callback)=>callback(request.hostname==='127.0.0.1'&&new X509Certificate(request.certificate.data).fingerprint256===fingerprint?0:-2));
win=new BrowserWindow({show:true,width:700,height:500});
for(let i=0;i<2;i++){const v=new WebContentsView({webPreferences:{session:ses,nodeIntegration:false,contextIsolation:true,sandbox:true}});views.push(v);win.contentView.addChildView(v);v.setBounds({x:0,y:0,width:700,height:500});await v.webContents.loadURL(origin+'/login');}
const a=views[0],b=views[1],credential={origin,username:'fixture-user',password:'synthetic-focus-proof-password'};
const execute=()=>a.webContents.executeJavaScriptInIsolatedWorld(999,[{code:fillScript(origin+'/login',credential)}],false);
b.setVisible(false);a.setVisible(true);win.focus();a.webContents.focus();
await new Promise(r=>setTimeout(r,200));assert.equal((await execute()).completed,true);
await a.webContents.executeJavaScript('document.querySelectorAll("input").forEach(e=>e.value="")');
a.setVisible(false);b.setVisible(true);b.webContents.focus();await new Promise(r=>setTimeout(r,200));
await assert.rejects(execute());
assert.equal(await a.webContents.executeJavaScript('document.querySelector("input[type=password]").value'),'');
fs.mkdirSync(path.join(__dirname,'../artifacts'),{recursive:true});fs.writeFileSync(path.join(__dirname,'../artifacts/password-focus-proof.json'),JSON.stringify({actualNativeViews:true,foregroundAllowed:true,hiddenBlurredFillDenied:true,noCredentialWriteToHiddenTab:true},null,2));
console.log('Native password foreground proof passed.');
}catch(error){console.error(error.message);process.exitCode=1;}finally{for(const v of views)if(!v.webContents.isDestroyed())v.webContents.close({waitForBeforeUnload:false});win?.destroy();if(server)await new Promise(r=>{server.closeAllConnections();server.close(r);});app.exit(process.exitCode||0);}});
}
+27
View File
@@ -0,0 +1,27 @@
'use strict';
const {app,BrowserWindow}=require('electron');const assert=require('node:assert/strict');const fs=require('node:fs');const path=require('node:path');
app.disableHardwareAcceleration();app.enableSandbox();app.setPath('userData',process.env.SAFETYNET_ADMIN_SMOKE_PROFILE);app.commandLine.appendSwitch('force-device-scale-factor','1');
let window;const deadline=setTimeout(()=>{console.error('ADMIN_UI_PROOF_TIMEOUT');app.exit(1);},50000);
async function evaluate(source){return window.webContents.executeJavaScript(source,true);}
async function waitFor(source){const until=Date.now()+12000;while(Date.now()<until){if(await evaluate(source))return;await new Promise(r=>setTimeout(r,75));}throw Error('Administrator UI state did not arrive');}
app.whenReady().then(async()=>{
window=new BrowserWindow({show:false,width:1500,height:1100,webPreferences:{nodeIntegration:false,contextIsolation:true,sandbox:true,offscreen:true,backgroundThrottling:false}});
await window.loadURL(process.env.SAFETYNET_ADMIN_SMOKE_URL);
await evaluate(`globalThis.__proofErrors=0;addEventListener('error',()=>globalThis.__proofErrors++);addEventListener('unhandledrejection',()=>globalThis.__proofErrors++);`);
assert.deepEqual(await evaluate(`({node:typeof process,require:typeof require,bridge:typeof safetynet})`),{node:'undefined',require:'undefined',bridge:'undefined'});
const headers=await evaluate(`fetch(location.href).then(r=>({csp:r.headers.get('content-security-policy'),type:r.headers.get('x-content-type-options')}))`);assert.ok(headers.csp.includes("script-src 'self'"));assert.ok(headers.csp.includes("frame-ancestors 'none'"));assert.equal(headers.type,'nosniff');
await evaluate(`document.getElementById('token').value=${JSON.stringify(process.env.SAFETYNET_ADMIN_SMOKE_TOKEN)};document.getElementById('connect').click()`);await waitFor(`!document.getElementById('workspace').hidden&&document.getElementById('status').textContent.includes('Connected')`);
await evaluate(`document.getElementById('brand-name').value='History test brand';document.getElementById('security-dns-hosts').value='blocked.synthetic.example';document.getElementById('security-dns-ips').value='203.0.113.10';document.getElementById('security-content-phrases').value='synthetic forbidden project';document.getElementById('agent-enabled').checked=true;document.getElementById('agent-hosts').value='*.synthetic.example';document.getElementById('agent-scope-read').checked=true;document.getElementById('publish').click()`);
await waitFor(`document.getElementById('policy-version').textContent==='v2'&&document.getElementById('status').textContent.includes('published')`);
assert.equal(await evaluate(`document.getElementById('security-dns-hosts').value`),'blocked.synthetic.example');assert.equal(await evaluate(`document.getElementById('agent-enabled').checked`),true);assert.equal(await evaluate(`document.getElementById('agent-scope-read').checked`),true);
await evaluate(`document.getElementById('security-controls').scrollIntoView()`);window.webContents.invalidate();await new Promise(r=>setTimeout(r,200));fs.mkdirSync(path.resolve('artifacts'),{recursive:true});fs.writeFileSync(path.resolve('artifacts/admin-security-controls.png'),(await window.webContents.capturePage()).toPNG());
await evaluate(`document.getElementById('brand-name').value='Unpublished draft';document.getElementById('history-load').click()`);await waitFor(`document.querySelectorAll('#history-rows tr').length===2`);
assert.equal(await evaluate(`document.getElementById('brand-name').value`),'Unpublished draft');
await evaluate(`document.querySelectorAll('#history-rows button')[1].click()`);await waitFor(`!document.getElementById('history-review').hidden`);
assert.equal(await evaluate(`document.getElementById('history-restore').disabled`),true);assert.equal(await evaluate(`document.getElementById('brand-name').value`),'Unpublished draft');assert.equal(await evaluate(`document.getElementById('policy-version').textContent`),'v2');assert.ok((await evaluate(`document.getElementById('history-diff-list').textContent`)).includes('/brand/name'));
await evaluate(`document.getElementById('history-review').scrollIntoView();document.getElementById('console-theme').value='dark';document.getElementById('console-theme').dispatchEvent(new Event('change'))`);window.webContents.invalidate();await new Promise(r=>setTimeout(r,300));fs.mkdirSync(path.resolve('artifacts'),{recursive:true});fs.writeFileSync(path.resolve('artifacts/policy-history-admin.png'),(await window.webContents.capturePage()).toPNG());
await evaluate(`globalThis.__originalPrincipal=currentPrincipal;applyOperatorPermissions({sub:'synthetic-auditor',role:'auditor',permissions:['overview.read','audit.read','policy.read','teaching.read']});`);assert.equal(await evaluate(`document.getElementById('history-approve').disabled&&document.getElementById('history-restore').disabled&&document.getElementById('agent-enabled').disabled`),true);await evaluate(`applyOperatorPermissions(globalThis.__originalPrincipal);delete globalThis.__originalPrincipal`);
await evaluate(`document.getElementById('history-approve').checked=true;document.getElementById('history-approve').dispatchEvent(new Event('change'));document.getElementById('history-restore').click()`);await waitFor(`document.getElementById('policy-version').textContent==='v3'&&document.getElementById('status').textContent.includes('restored')`);
assert.equal(await evaluate(`document.getElementById('brand-name').value`),'SafetyNet');assert.equal(await evaluate(`document.getElementById('agent-enabled').checked`),false);assert.equal(await evaluate(`document.getElementById('security-dns-hosts').value`),'');assert.equal(await evaluate(`document.querySelectorAll('#history-rows tr').length`),3);assert.equal(await evaluate(`globalThis.__proofErrors`),0);
console.log('HISTORY_ADMIN_PROOF_OK');clearTimeout(deadline);window.destroy();app.exit(0);
}).catch(error=>{console.error('HISTORY_ADMIN_PROOF_FAILED',error.message);clearTimeout(deadline);window?.destroy();app.exit(1);});
+26
View File
@@ -0,0 +1,26 @@
// Finite, isolated administrator workflow proof using actual UI and HTTP routes.
import assert from 'node:assert/strict';
import { createRequire } from 'node:module';
import { createServer } from 'node:net';
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join, resolve, sep, basename } from 'node:path';
import { spawn } from 'node:child_process';
import { randomBytes } from 'node:crypto';
import { openStore } from '../apps/server/store.mjs';
import { createApp } from '../apps/server/app.mjs';
import { verifyPolicy } from '../packages/core/policy.mjs';
const require=createRequire(import.meta.url),directory=mkdtempSync(join(tmpdir(),'safetynet-policy-history-admin-smoke-'));
let store,server,child;
try{
store=openStore(join(directory,'management'));const adminToken=randomBytes(32).toString('base64url'),config={adminToken,publicUrl:'http://127.0.0.1',secure:false};
store.db.prepare('INSERT INTO devices(id,name,platform,user,token_hash,last_seen) VALUES(?,?,?,?,?,?)').run('synthetic-bookmark-device','Synthetic bookmark device','win32','synthetic-user','synthetic-unused',new Date().toISOString());
server=createApp(store,config).listen(0,'127.0.0.1');await new Promise(r=>server.once('listening',r));config.publicUrl=`http://127.0.0.1:${server.address().port}`;
const env={...process.env,SAFETYNET_ADMIN_SMOKE_PROFILE:join(directory,'browser'),SAFETYNET_ADMIN_SMOKE_URL:config.publicUrl,SAFETYNET_ADMIN_SMOKE_TOKEN:adminToken};delete env.ELECTRON_RUN_AS_NODE;
child=spawn(require('electron'),['scripts/policy-history-admin-smoke.cjs'],{env,windowsHide:true,stdio:['ignore','pipe','pipe']});child.stdout.on('data',data=>{if(String(data).includes('HISTORY_ADMIN_PROOF_OK'))console.log('Policy history administrator interface workflow passed.');});child.stderr.on('data',data=>{const text=String(data);if(text.includes('HISTORY_ADMIN_PROOF_'))console.error(text.trim());});
const timer=setTimeout(()=>child.kill(),60000),code=await new Promise(r=>{child.once('exit',code=>r(code??1));child.once('error',()=>r(1));});clearTimeout(timer);assert.equal(code,0,'Policy history administrator interface proof failed');
const policy=verifyPolicy(store.envelope(),store.publicKey());assert.equal(policy.version,3);assert.equal(policy.brand.name,'SafetyNet');assert.equal(policy.agents.enabled,false);assert.deepEqual(policy.security.dns.blockedHosts,[]);assert.deepEqual(policy.security.content.blockedPhrases,[]);
const report={actualAdministratorUi:true,persistedHistory:true,serverDiff:true,explicitRestoreApproval:true,monotonicRestore:true,draftPreservedDuringReview:true,structuredDnsContentAgentControls:true,nodeUnavailable:true,cspPreserved:true};mkdirSync('artifacts',{recursive:true});writeFileSync('artifacts/policy-history-admin-proof.json',JSON.stringify(report,null,2));console.log(JSON.stringify(report));
}finally{
child?.kill();if(server)await new Promise(r=>{server.closeAllConnections?.();server.close(r);});store?.db.close();const target=resolve(directory);if(!target.startsWith(resolve(tmpdir())+sep)||!basename(target).startsWith('safetynet-policy-history-admin-smoke-'))throw Error('Unsafe proof cleanup');rmSync(target,{recursive:true,force:true,maxRetries:10,retryDelay:100});
}
+34
View File
@@ -0,0 +1,34 @@
'use strict';
const {app,BrowserWindow}=require('electron');const assert=require('node:assert/strict');const fs=require('node:fs');const path=require('node:path');
app.disableHardwareAcceleration();app.enableSandbox();app.setPath('userData',process.env.SAFETYNET_ADMIN_SMOKE_PROFILE);app.commandLine.appendSwitch('force-device-scale-factor','1');
let window;const deadline=setTimeout(()=>{console.error('ADMIN_UI_PROOF_TIMEOUT');app.exit(1);},50000);
async function evaluate(source){return window.webContents.executeJavaScript(source,true);}
async function waitFor(source){const until=Date.now()+12000;while(Date.now()<until){if(await evaluate(source))return;await new Promise(r=>setTimeout(r,75));}throw Error('Administrator UI state did not arrive: '+await evaluate(`document.getElementById('status').textContent`));}
app.whenReady().then(async()=>{
window=new BrowserWindow({show:false,width:1500,height:1100,webPreferences:{nodeIntegration:false,contextIsolation:true,sandbox:true,offscreen:true,backgroundThrottling:false}});
window.webContents.on('did-finish-load',()=>evaluate(`globalThis.__proofErrors=0;addEventListener('error',()=>globalThis.__proofErrors++);addEventListener('unhandledrejection',()=>globalThis.__proofErrors++);`).catch(()=>{}));
await window.loadURL(process.env.SAFETYNET_ADMIN_SMOKE_URL);
await evaluate(`globalThis.__proofErrors=0;addEventListener('error',()=>globalThis.__proofErrors++);addEventListener('unhandledrejection',()=>globalThis.__proofErrors++);`);
assert.deepEqual(await evaluate(`({node:typeof process,require:typeof require,bridge:typeof safetynet})`),{node:'undefined',require:'undefined',bridge:'undefined'});
const headers=await evaluate(`fetch(location.href).then(r=>({csp:r.headers.get('content-security-policy'),type:r.headers.get('x-content-type-options')}))`);assert.ok(headers.csp.includes("script-src 'self'"));assert.ok(headers.csp.includes("frame-ancestors 'none'"));assert.equal(headers.type,'nosniff');
const reviewProof=process.env.SAFETYNET_PROFILE_REVIEW_PROOF==='1';
if(reviewProof){await window.webContents.session.cookies.set({url:process.env.SAFETYNET_ADMIN_SMOKE_URL,name:'sn_session',value:process.env.SAFETYNET_PROFILE_OPERATOR_TOKEN,httpOnly:true,sameSite:'lax'});await window.reload();await waitFor(`!document.getElementById('workspace').hidden&&document.getElementById('status').textContent.includes('Connected')`);}
else {
await evaluate(`document.getElementById('token').value=${JSON.stringify(process.env.SAFETYNET_ADMIN_SMOKE_TOKEN)};document.getElementById('connect').click()`);await waitFor(`!document.getElementById('workspace').hidden&&document.getElementById('status').textContent.includes('Connected')`);}
await evaluate(`document.getElementById('profile-template').value='employee';document.getElementById('profile-use-template').click();document.getElementById('profile-id').value='research-europe';document.getElementById('profile-name').value='Research Europe';for(const input of document.querySelectorAll('#profile-devices input'))input.checked=input.value==='pilot-device';document.getElementById('profile-blocked').value='restricted.synthetic.example';document.getElementById('profile-save').click()`);
if(reviewProof){
await waitFor(`document.getElementById('status').textContent.includes('prepared for independent approval')`);assert.equal(await evaluate(`document.getElementById('policy-version').textContent`),'v1');assert.equal(await evaluate(`document.querySelectorAll('#profiles-rows tr').length`),0);
await window.webContents.session.cookies.set({url:process.env.SAFETYNET_ADMIN_SMOKE_URL,name:'sn_session',value:process.env.SAFETYNET_PROFILE_REVIEWER_TOKEN,httpOnly:true,sameSite:'lax'});await window.reload();await waitFor(`!document.getElementById('workspace').hidden&&document.querySelector('#reviews-rows button')`);
await evaluate(`document.querySelector('#reviews-rows button').click()`);await waitFor(`!document.getElementById('independent-review-detail').hidden`);
const operation=await evaluate(`document.getElementById('independent-review-operation').textContent`);for(const value of ['research-europe','pilot-device','devTools','restricted.synthetic.example'])assert.ok(operation.includes(value),`Exact proposal missing ${value}`);
await evaluate(`document.getElementById('independent-review-confirm').checked=true;document.getElementById('independent-review-confirm').dispatchEvent(new Event('change'));document.getElementById('independent-review-approve').click()`);await waitFor(`document.getElementById('policy-version').textContent==='v2'`);
}else{await waitFor(`document.getElementById('policy-version').textContent==='v2'&&document.getElementById('status').textContent.includes('published')`);}
assert.equal(await evaluate(`document.querySelector('#profiles-rows tr td:nth-child(3)').textContent`),'deny');
await evaluate(`document.getElementById('profile-preview-device').value='pilot-device';document.getElementById('profile-preview').click()`);await waitFor(`document.getElementById('profile-preview-summary').textContent.includes('research-europe')`);
assert.equal(await evaluate(`document.getElementById('profile-preview-diff').textContent.includes('restricted.synthetic.example')`),true);
await evaluate(`document.getElementById('profile-preview-device').value='outside-device';document.getElementById('profile-preview').click()`);await waitFor(`document.getElementById('profile-preview-summary').textContent.includes('baseline only')`);
assert.equal(await evaluate(`document.getElementById('profile-preview-diff').textContent.includes('restricted.synthetic.example')`),false);assert.equal(await evaluate(`globalThis.__proofErrors`),0);
await evaluate(`document.getElementById('user-profiles').scrollIntoView()`);window.webContents.invalidate();await new Promise(r=>setTimeout(r,300));fs.mkdirSync(path.resolve('artifacts'),{recursive:true});fs.writeFileSync(path.resolve('artifacts/profiles-admin.png'),(await window.webContents.capturePage()).toPNG());
console.log('PROFILE_ADMIN_PROOF_OK');clearTimeout(deadline);window.destroy();app.exit(0);
}).catch(error=>{console.error('PROFILE_ADMIN_PROOF_FAILED',error.stack);clearTimeout(deadline);window?.destroy();app.exit(1);});
+29
View File
@@ -0,0 +1,29 @@
// Finite, isolated administrator workflow proof using actual UI and HTTP routes.
import assert from 'node:assert/strict';
import { createRequire } from 'node:module';
import { createServer } from 'node:net';
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join, resolve, sep, basename } from 'node:path';
import { spawn } from 'node:child_process';
import { randomBytes } from 'node:crypto';
import { digest } from '../apps/server/store.mjs';
import { openStore } from '../apps/server/store.mjs';
import { createApp } from '../apps/server/app.mjs';
import { verifyPolicy } from '../packages/core/policy.mjs';
const require=createRequire(import.meta.url),directory=mkdtempSync(join(tmpdir(),'safetynet-profiles-admin-smoke-'));
let store,server,child;
try{
store=openStore(join(directory,'management'));const adminToken=randomBytes(32).toString('base64url'),config={adminToken,publicUrl:'http://127.0.0.1',secure:false,requireIndependentPolicyApproval:process.env.SAFETYNET_PROFILE_REVIEW_PROOF==='1'};
for(const id of ['pilot-device','member-device','outside-device'])store.db.prepare('INSERT INTO devices(id,name,platform,user,token_hash,last_seen) VALUES(?,?,?,?,?,?)').run(id,id,'win32','synthetic-user',`synthetic-${id}`,new Date().toISOString());
const operatorToken=randomBytes(32).toString('base64url'),reviewerToken=randomBytes(32).toString('base64url');for(const [value,sub,role]of [[operatorToken,'group-operator','operator'],[reviewerToken,'group-reviewer','admin']])store.db.prepare('INSERT INTO sessions VALUES(?,?,?)').run(digest(value),Date.now()+60000,JSON.stringify({sub,role}));
server=createApp(store,config).listen(0,'127.0.0.1');await new Promise(r=>server.once('listening',r));config.publicUrl=`http://127.0.0.1:${server.address().port}`;
const env={...process.env,SAFETYNET_ADMIN_SMOKE_PROFILE:join(directory,'browser'),SAFETYNET_ADMIN_SMOKE_URL:config.publicUrl,SAFETYNET_ADMIN_SMOKE_TOKEN:adminToken,SAFETYNET_PROFILE_OPERATOR_TOKEN:operatorToken,SAFETYNET_PROFILE_REVIEWER_TOKEN:reviewerToken};delete env.ELECTRON_RUN_AS_NODE;
child=spawn(require('electron'),['scripts/profiles-admin-smoke.cjs'],{env,windowsHide:true,stdio:['ignore','pipe','pipe']});child.stdout.on('data',data=>{if(String(data).includes('PROFILE_ADMIN_PROOF_OK'))console.log('Profile administrator interface workflow passed.');});child.stderr.on('data',data=>{const text=String(data);if(text.includes('PROFILE_ADMIN_PROOF_'))console.error(text.trim());});
const timer=setTimeout(()=>child.kill(),60000),code=await new Promise(r=>{child.once('exit',code=>r(code??1));child.once('error',()=>r(1));});clearTimeout(timer);assert.equal(code,0,'Profile administrator interface proof failed');
const policy=verifyPolicy(store.envelope(),store.publicKey());assert.equal(policy.version,2);
const report={actualAdministratorUi:true,explicitDeviceAssignments:true,employeeDeveloperFlags:true,websiteRestrictions:true,noNode:true,cspPreserved:true,...(config.requireIndependentPolicyApproval?{operatorProposalLeftPolicyUnchanged:true,exactProfileReviewed:true,distinctAdministratorApproval:true}:{effectivePreview:true})};mkdirSync('artifacts',{recursive:true});writeFileSync(config.requireIndependentPolicyApproval?'artifacts/profiles-review-admin-proof.json':'artifacts/profiles-admin-proof.json',JSON.stringify(report,null,2));console.log(JSON.stringify(report));
}finally{
child?.kill();if(server)await new Promise(r=>{server.closeAllConnections?.();server.close(r);});store?.db.close();const target=resolve(directory);if(!target.startsWith(resolve(tmpdir())+sep)||!basename(target).startsWith('safetynet-profiles-admin-smoke-'))throw Error('Unsafe proof cleanup');rmSync(target,{recursive:true,force:true,maxRetries:10,retryDelay:100});
}
+4
View File
@@ -0,0 +1,4 @@
"""Compatibility entry point for verified offline semantic provisioning."""
from runpy import run_path
from pathlib import Path
run_path(str(Path(__file__).with_name('provision-semantic-runtime.py')), run_name='__main__')
+70
View File
@@ -0,0 +1,70 @@
"""Provision an offline, verified EmbeddingGemma 2 Windows distribution."""
import argparse
import hashlib
import json
from pathlib import Path
import shutil
import tempfile
ROOT = Path(__file__).resolve().parents[1]
DEST = ROOT / '.runtime/windows/semantic'
PIN = 'bfcd298762cc34d0357ece5ebdd31791a3a374d8'
MODELS = {
'embeddinggemma-2-Q8_0.gguf': (309855456, '2188ac1deca4b77dffefd603c2776a9d76d9d74ec01841392982ebb840b09135'),
'mmproj-embeddinggemma-2-Q8_0.gguf': (554821024, 'c4a8a52691ecef40618438928bdf9e68379b854e24166f292592353db0aab64f'),
}
def verify(base, item):
name = item['path']
if Path(name).name != name or ':' in name or '\\' in name or '/' in name:
raise ValueError('Invalid artifact name')
file = base / name
if file.is_symlink() or not file.is_file() or file.stat().st_size != item['bytes']:
raise ValueError('Artifact missing or incorrect size: ' + name)
digest = hashlib.sha256()
with file.open('rb') as stream:
while block := stream.read(1024 * 1024): digest.update(block)
if digest.hexdigest() != item['sha256']: raise ValueError('Artifact digest mismatch: ' + name)
def validate(base):
manifest = json.loads((base / 'models/model-manifest.json').read_text('utf-8'))
if (manifest['model_id'], manifest['revision'], manifest['dimensions'], manifest['quantization'], manifest['runtime_tag']) != ('google/embeddinggemma-2', PIN, 768, 'Q8_0', 'b11461'):
raise ValueError('Model identity mismatch')
for name, (size, digest) in MODELS.items(): verify(base / 'models', {'path': name, 'bytes': size, 'sha256': digest})
files = json.loads((base / 'runtime-manifest.json').read_text('utf-8'))['files']
if not 1 <= len(files) <= 64 or len({item['path'].lower() for item in files}) != len(files): raise ValueError('Invalid runtime inventory')
if not any(item['path'] == 'searchi-gemma-worker.exe' for item in files): raise ValueError('Worker absent')
for item in files: verify(base, item)
if {p.name.lower() for p in base.glob('*.dll')} != {i['path'].lower() for i in files if i['path'].lower().endswith('.dll')}: raise ValueError('Unverified DLL')
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--source-project', type=Path)
parser.add_argument('--verify', action='store_true')
args = parser.parse_args()
if DEST.exists():
validate(DEST)
print('Verified offline EmbeddingGemma 2 model and Windows runtime.')
return
if args.verify or args.source_project is None: raise ValueError('Provision semantic runtime with --source-project before packaging')
source = args.source_project.resolve()
runtime = source / '.searchi/runtime/auto/Release'
inventory = json.loads((runtime / 'runtime-libraries.json').read_text('utf-8'))
worker = runtime / 'searchi-gemma-worker.exe'
files = [{'path': worker.name, 'bytes': worker.stat().st_size, 'sha256': inventory['worker_sha256']}, *inventory['libraries']]
for item in files: verify(runtime, item)
DEST.parent.mkdir(parents=True, exist_ok=True)
candidate = Path(tempfile.mkdtemp(prefix='semantic-stage-', dir=DEST.parent))
# A failed stage is retained for diagnosis; never delete another project's assets.
(candidate / 'models').mkdir()
for item in files: shutil.copy2(runtime / item['path'], candidate / item['path'])
(candidate / 'runtime-manifest.json').write_text(json.dumps({'files': files}, indent=2), 'utf-8')
shutil.copy2(source / 'tools/embeddinggemma2/model-manifest.json', candidate / 'models/model-manifest.json')
for name in MODELS: shutil.copy2(source / '.searchi/models/embeddinggemma2' / name, candidate / 'models' / name)
shutil.copy2(source / '.searchi/references/llama.cpp/LICENSE', candidate / 'LLAMA-LICENSE.txt')
for name in ('MSVC-REDISTRIBUTION.txt', 'VULKAN-LICENSE.txt'): shutil.copy2(runtime / name, candidate / name)
validate(candidate)
candidate.rename(DEST)
print('Provisioned verified offline EmbeddingGemma 2 model and Windows runtime.')
if __name__ == '__main__': main()
+45
View File
@@ -0,0 +1,45 @@
"""Build a pinned private Windows x64 inspector runtime; no machine-wide install."""
import hashlib
import json
import shutil
import subprocess
import sys
import urllib.request
import zipfile
from pathlib import Path
if sys.platform!='win32': raise SystemExit('Windows runtime provisioning runs on Windows only')
VERSION='3.13.16'
CHECKSUM='97dae5274cc54867065e8d5a3226e48c35017ed332a0fdb0e27d5b5821961297'
root=Path.cwd().resolve()
directory=root/'.runtime'/'windows'/'python'
directory.mkdir(parents=True,exist_ok=True)
requirements=root/'apps'/'inspector'/'requirements.lock.txt'
requirements_hash=hashlib.sha256(requirements.read_bytes()).hexdigest()
manifest=directory/'safetynet-runtime.json'
expected={'python':VERSION,'architecture':'amd64','sha256':CHECKSUM,'requirementsHash':requirements_hash}
if not manifest.exists() or json.loads(manifest.read_text())!=expected:
archive=directory.parent/f'python-{VERSION}-embed-amd64.zip'
if not archive.exists() or hashlib.sha256(archive.read_bytes()).hexdigest()!=CHECKSUM:
with urllib.request.urlopen(f'https://www.python.org/ftp/python/{VERSION}/python-{VERSION}-embed-amd64.zip',timeout=60) as response:
payload=response.read(20*1024*1024)
if hashlib.sha256(payload).hexdigest()!=CHECKSUM: raise SystemExit('Python runtime checksum mismatch')
archive.write_bytes(payload)
with zipfile.ZipFile(archive) as package:
for entry in package.infolist():
target=(directory/entry.filename).resolve()
if not target.is_relative_to(directory): raise SystemExit('Runtime archive path rejected')
if not entry.is_dir():
target.parent.mkdir(parents=True,exist_ok=True)
target.write_bytes(package.read(entry))
(directory/'python313._pth').write_text('python313.zip\n.\nLib/site-packages\n../inspector\nimport site\n')
subprocess.run([sys.executable,'-m','pip','install','--target',str(directory/'Lib'/'site-packages'),
'--platform','win_amd64','--python-version','3.13','--implementation','cp','--abi','cp313',
'--only-binary=:all:','--require-hashes','--upgrade','-r',str(requirements)],check=True)
manifest.write_text(json.dumps(expected,indent=2))
inspector=directory.parent/'inspector'
inspector.mkdir(exist_ok=True)
for name in ['engine.py','server.py','semantic.py','windows_containment.py','windows_appcontainer.py','sandbox_worker.py','provision_runtime_acl.py']:
shutil.copyfile(root/'apps'/'inspector'/name,inspector/name)
subprocess.run([str(directory/'python.exe'),'-c','import pypdf, PIL, defusedxml, yara, engine; assert engine.inspect_content(b"public", {"dlp":{"maxBytes":1024,"rules":[],"semantic":{"enabled":False}}})["decision"] == "allow"; assert yara.compile(source="rule test { condition: true }").match(data=b"test"); engine.local_ocr(); print("Bundled Windows inspector, YARA and offline ONNX OCR runtime verified.")'],check=True)
subprocess.run([str(directory/'python.exe'),str(root/'apps/inspector/provision_runtime_acl.py'),'--provision'],check=True)
+34
View File
@@ -0,0 +1,34 @@
// Finite native fixture: synthetic teaching data, real signed policy and CPU model.
const {app,BrowserWindow,clipboard,ClipboardItem}=require('electron');
const fs=require('node:fs'),path=require('node:path'),assert=require('node:assert/strict');
app.setPath('userData',process.env.SAFETYNET_SEMANTIC_PROFILE);
app.setPath('sessionData',process.env.SAFETYNET_SEMANTIC_PROFILE);
app.disableHardwareAcceleration();
require('../apps/browser/main.cjs');
const wait=ms=>new Promise(resolve=>setTimeout(resolve,ms));
const deadline=setTimeout(()=>app.exit(1),90000);
app.whenReady().then(async()=>{let original;try{
let win;
for(let i=0;i<150;i++){win=BrowserWindow.getAllWindows()[0];if(win&&!win.webContents.isLoading()&&win.webContents.getURL().endsWith('index.html'))break;await wait(100);}
assert.ok(win,'Trusted shell unavailable');
const enrolled=await win.webContents.executeJavaScript(`window.safetynet.enroll(${JSON.stringify({server:process.env.SAFETYNET_SEMANTIC_SERVER,code:process.env.SAFETYNET_SEMANTIC_CODE})})`);
assert.equal(enrolled.ok,true,'Enrollment failed');assert.equal(enrolled.data.ready,true);
const page=win.contentView.children.find(child=>child.webContents!==win.webContents).webContents;
for(let i=0;i<100&&page.isLoading();i++)await wait(100);
const connection=JSON.parse(process.env.SAFETYNET_SEMANTIC_FIXTURES);
original=[];for(const item of await clipboard.read()){const data={};for(const type of item.types)data[type]=await item.getType(type);if(Object.keys(data).length)original.push(new ClipboardItem(data));}
async function select(text){await page.executeJavaScript(`(()=>{let node=document.getElementById('source');node.textContent=${JSON.stringify(text)};const range=document.createRange();range.selectNodeContents(node);const selection=getSelection();selection.removeAllRanges();selection.addRange(range);})()`);}
async function copy(){win.show();win.focus();page.focus();page.sendInputEvent({type:'keyDown',keyCode:'C',modifiers:['control']});page.sendInputEvent({type:'keyUp',keyCode:'C',modifiers:['control']});await wait(500);for(let i=0;i<150;i++){const state=await win.webContents.executeJavaScript('window.safetynet.state()');if(!state.data.clipboardPending)return;await wait(100);}throw Error('Native clipboard scan timed out');}
const sentinel='Public semantic test clipboard marker';
await clipboard.writeText(sentinel);await select(connection.paraphrase);await copy();
assert.ok((await clipboard.readText())===sentinel,'Semantic confidential paraphrase reached OS clipboard');
const overview=await (await fetch(`${process.env.SAFETYNET_SEMANTIC_SERVER}/api/admin/overview`,{headers:{authorization:`Bearer ${process.env.SAFETYNET_SEMANTIC_ADMIN}`}})).json();
assert.ok(overview.events.some(event=>event.kind==='clipboard.block'&&event.metadata.ruleId==='synthetic-restructuring'),'Semantic rule did not cause centrally audited block');
await select(connection.publicText);await copy();
for(let i=0;i<30&&await clipboard.readText()!==connection.publicText;i++)await wait(100);
assert.equal(await clipboard.readText(),connection.publicText,'Public text was not copied through real local semantic inference');
assert.equal(JSON.stringify(overview.events).includes(connection.paraphrase),false,'Audit contains raw clipboard text');
console.log(JSON.stringify({nativeSemanticClipboard:true,confidentialParaphraseBlocked:true,publicTextAllowed:true,centralAuditMetadataOnly:true}));
if(original.length)await clipboard.write(original);else await clipboard.clear();original=null;clearTimeout(deadline);app.quit();
}catch(error){console.error(JSON.stringify({nativeSemanticClipboard:false,error:error.message}));if(original){try{if(original.length)await clipboard.write(original);else await clipboard.clear();}catch{}}clearTimeout(deadline);app.exit(1);}});
+51
View File
@@ -0,0 +1,51 @@
// Independent localhost control plane and real Windows browser. No cloud/model downloads.
import assert from 'node:assert/strict';
import {createRequire} from 'node:module';
import {createServer} from 'node:http';
import {mkdtempSync,mkdirSync,existsSync,writeFileSync} from 'node:fs';
import {tmpdir} from 'node:os';
import {join,resolve} from 'node:path';
import {spawn} from 'node:child_process';
import {randomBytes} from 'node:crypto';
import {createApp} from '../apps/server/app.mjs';
import {openStore,digest} from '../apps/server/store.mjs';
import {inspect,verifyPolicy} from '../packages/core/policy.mjs';
const require=createRequire(import.meta.url),electron=require('electron');
const temporary=mkdtempSync(join(tmpdir(),'safetynet-semantic-browser-'));
const runtime=resolve('.runtime/windows/semantic'),python=resolve('.runtime/windows/python/python.exe');
assert.ok(existsSync(join(runtime,'models/model-manifest.json')),'Stage verified local model artifacts before running');
const fixtures={reference:'Confidential corporate restructuring will close the Lisbon office next autumn and eliminate two hundred positions before the public announcement. Leadership is negotiating a six-million-euro acquisition of a rival. These undisclosed staffing reductions and acquisition plans are restricted internal company information.',paraphrase:'Private workforce planning calls for shutting the Portugal branch after summer and cutting roughly two hundred jobs. Executives are discussing a six-million-euro purchase of a competitor; the timetable and personnel reductions remain undisclosed.',publicText:'A simple tomato pasta recipe combines ripe tomatoes, olive oil, garlic and fresh basil. Boil the pasta in salted water and serve it warm.'};
let inspector,management,sink,store,child;
const report={model:'google/embeddinggemma-2',revision:'bfcd298762cc34d0357ece5ebdd31791a3a374d8',dimensions:768,profile:'document-v1',artifactFormat:'gguf',quantization:'Q8_0',runtimeRevision:'b11461',local:true};
try{
const inspectorToken=randomBytes(32).toString('base64url'),adminToken=randomBytes(32).toString('base64url'),code=randomBytes(32).toString('base64url');
inspector=spawn(python,['apps/inspector/server.py'],{windowsHide:true,stdio:['ignore','pipe','pipe'],env:{...process.env,EMBEDDING_MODEL_DIR:join(runtime,'models'),EMBEDDING_WORKER_PATH:join(runtime,'searchi-gemma-worker.exe'),INSPECTOR_TOKEN:inspectorToken,INSPECTOR_PORT:'0',INSPECTOR_PARENT_PID:String(process.pid)}});
inspector.stderr.on('data',()=>{});
const inspectorPort=await new Promise((accept,reject)=>{let output='';const timeout=setTimeout(()=>{inspector.kill();reject(Error('Inspector startup timed out'));},40000);inspector.once('error',reject);inspector.once('exit',()=>{clearTimeout(timeout);reject(Error('Inspector exited before startup'));});inspector.stdout.on('data',chunk=>{output+=chunk;if(output.includes('\n')){clearTimeout(timeout);try{accept(JSON.parse(output.split('\n')[0]).port);}catch{reject(Error('Invalid inspector startup'));}}});});
sink=createServer((_req,res)=>{res.setHeader('Content-Type','text/html');res.end('<!doctype html><title>Local semantic enforcement fixture</title><h1>Public browser fixture</h1><pre id="source"></pre>');}).listen(0,'127.0.0.1');await new Promise(resolve=>sink.once('listening',resolve));
store=openStore(join(temporary,'management.sqlite'));
const initial=store.get('policy');initial.browser.homeUrl=`http://127.0.0.1:${sink.address().port}`;initial.browser.allowedHosts=['127.0.0.1'];initial.dlp.rules=[];store.put('policy',initial);
store.db.prepare('INSERT INTO enrollments VALUES(?,?,?)').run(digest(code),Date.now()+600000,'synthetic-semantic-user');
const config={publicUrl:'http://127.0.0.1',secure:false,adminToken,inspectorUrl:`http://127.0.0.1:${inspectorPort}`,inspectorToken};
management=createApp(store,config).listen(0,'127.0.0.1');await new Promise(resolve=>management.once('listening',resolve));config.publicUrl=`http://127.0.0.1:${management.address().port}`;
async function admin(route,body,method='POST'){const result=await fetch(config.publicUrl+route,{method,headers:{authorization:`Bearer ${adminToken}`,'content-type':'application/json'},body:JSON.stringify(body),signal:AbortSignal.timeout(90000)});assert.equal(result.status,200,`Central route ${route} failed`);return result.json();}
const teaching=await admin('/api/admin/teaching',{label:'Synthetic confidential workforce plan',filename:'synthetic-reference.txt',data:Buffer.from(fixtures.reference).toString('base64')});
await admin(`/api/admin/teaching/${teaching.id}/publish`,{expectedVersion:initial.version,approve:true});
const reference=await admin('/api/admin/semantic/reference',{description:fixtures.reference});
for(const key of ['model','revision','dimensions','profile','artifactFormat','quantization','runtimeRevision','local'])assert.equal(reference[key],report[key],`Unexpected local model ${key}`);
const policy=store.get('policy');policy.version++;policy.dlp.semantic={enabled:true,model:reference.model,revision:reference.revision,dimensions:reference.dimensions,profile:reference.profile,artifactFormat:reference.artifactFormat,quantization:reference.quantization,runtimeRevision:reference.runtimeRevision,categories:[{id:'synthetic-restructuring',label:'Synthetic restricted workforce plan',threshold:0.65,prototype:reference.vector,prototypes:reference.vectors}]};
assert.equal(inspect(Buffer.from(fixtures.paraphrase),policy).decision,'allow','Paraphrase accidentally matches a deterministic rule');
const secret=await admin('/api/admin/policy/test',{text:fixtures.paraphrase,policy}),ordinary=await admin('/api/admin/policy/test',{text:fixtures.publicText,policy});
assert.equal(secret.ruleId,'synthetic-restructuring','Semantic paraphrase did not match calibrated category');assert.equal(ordinary.decision,'allow','Unrelated public text failed semantic calibration');
await admin('/api/admin/policy',policy,'PUT');const signed=verifyPolicy(store.envelope(),store.publicKey());assert.equal(signed.dlp.semantic.revision,report.revision);assert.equal(signed.dlp.semantic.profile,report.profile);
const env={...process.env,SAFETYNET_SEMANTIC_PROFILE:join(temporary,'browser'),SAFETYNET_SEMANTIC_SERVER:config.publicUrl,SAFETYNET_SEMANTIC_CODE:code,SAFETYNET_SEMANTIC_ADMIN:adminToken,SAFETYNET_SEMANTIC_FIXTURES:JSON.stringify(fixtures)};
// Prove the browser's automatic bundled-path wiring rather than the fixture inspector environment.
delete env.EMBEDDING_MODEL_DIR;delete env.EMBEDDING_WORKER_PATH;delete env.ELECTRON_RUN_AS_NODE;
child=spawn(electron,['scripts/semantic-browser-smoke.cjs'],{windowsHide:true,stdio:'inherit',env});const timer=setTimeout(()=>child.kill(),100000);
const status=await new Promise(resolve=>{child.once('exit',code=>resolve(code??1));child.once('error',()=>resolve(1));});clearTimeout(timer);assert.equal(status,0,'Native semantic browser fixture failed');
Object.assign(report,{centralTeaching:true,signedPolicyVerified:true,deterministicParaphraseAllow:true,semanticParaphraseBlock:true,publicTextAllow:true,paraphraseSimilarity:secret.similarity?.[0]?.score,publicSimilarity:ordinary.similarity?.[0]?.score,nativeProofPassed:true});
mkdirSync('artifacts',{recursive:true});writeFileSync('artifacts/semantic-browser-proof.json',JSON.stringify(report,null,2));console.log(JSON.stringify(report));
}finally{
child?.kill();inspector?.kill();for(const server of [management,sink])if(server){server.closeAllConnections();await new Promise(resolve=>server.close(resolve));}store?.db.close();
}
+54
View File
@@ -0,0 +1,54 @@
import { createServer } from 'node:http';
import { createRequire } from 'node:module';
import { mkdtempSync,rmSync,mkdirSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join,resolve } from 'node:path';
import { spawn } from 'node:child_process';
import { randomBytes } from 'node:crypto';
import { createApp } from '../apps/server/app.mjs';
import { openStore,digest } from '../apps/server/store.mjs';
const require=createRequire(import.meta.url),electron=require('electron');
const temporary=mkdtempSync(join(tmpdir(),'safetynet-smoke-'));mkdirSync('artifacts',{recursive:true});
let posts=0,proxyRequests=0,secondaryRequests=0;
const visualLogin='<!doctype html><meta charset="utf-8"><title>Visual identity fixture</title><style>body{font-family:Arial;background:#fff;color:#202124;margin:0}form{margin:60px auto;padding:32px;border:2px solid #3267cb;border-radius:12px;width:340px;height:330px;box-sizing:content-box}h1{color:#3267cb;font-size:27px}input{display:block;margin:20px 0;padding:12px;border:1px solid #aaa;width:260px}button{background:#3267cb;color:white;padding:12px}</style><form method="post" action="/sink"><h1>SafetyNet Identity Lab</h1><h2>Sign in</h2><p>Use your laboratory account</p><input name="username" type="email" autocomplete="username"><input type="password" autocomplete="current-password"><button type="submit">Continue</button></form>';
const receiver=(req,res)=>{
res.setHeader('Access-Control-Allow-Origin','*');
if(req.url==='/count'){res.setHeader('content-type','application/json');res.end(JSON.stringify({posts,proxyRequests,secondaryRequests}));return;}
if(req.url==='/visual-login'){res.setHeader('content-type','text/html');res.end(visualLogin);return;}
if(req.url==='/download-safe'||req.url==='/download-blocked'){
res.setHeader('Content-Type','application/octet-stream');res.setHeader('Content-Disposition',`attachment; filename="${req.url==='/download-safe'?'safe.bin':'blocked.bin'}"`);
res.end(req.url==='/download-safe'?Buffer.from([0,1,2,3,255]):Buffer.from('SAFETYNET_BLOCK_TEST'));return;
}
if(req.url.startsWith('http://proxy-check.invalid/'))proxyRequests++;
if(req.method==='POST'){posts++;req.resume();res.end('received');return;}
res.setHeader('content-type','text/html');res.end('<!doctype html><title>SafetyNet enforcement fixture</title><h1>Managed browsing is active</h1><p>This controlled receiver verifies that blocked payloads never arrive.</p><input id="public-input" type="text"><input id="private-input" type="password" value="never-export-this"><a id="safe-download" href="/download-safe">Download safe sample</a><a id="blocked-download" href="/download-blocked">Download blocked sample</a>');
};
const sink=createServer(receiver).listen(0,'127.0.0.1');await new Promise(r=>sink.on('listening',r));
const secondary=createServer((req,res)=>{secondaryRequests++;res.setHeader('Access-Control-Allow-Origin','*');res.end('secondary');}).listen(0,'127.0.0.2');await new Promise(r=>secondary.on('listening',r));
const store=openStore(join(temporary,'db')),code=randomBytes(32).toString('base64url'),adminToken=randomBytes(32).toString('base64url');
const inspectorToken=randomBytes(32).toString('base64url');
const inspectorProcess=spawn(resolve('.runtime/windows/python/python.exe'),['apps/inspector/server.py'],{windowsHide:true,stdio:['ignore','pipe','pipe'],env:{...process.env,INSPECTOR_TOKEN:inspectorToken,INSPECTOR_PORT:'0',INSPECTOR_PARENT_PID:String(process.pid)}});
const inspectorPort=await new Promise((resolve,reject)=>{
let output='';const deadline=setTimeout(()=>{inspectorProcess.kill();reject(Error('Fixture inspector did not start'));},40000);
inspectorProcess.once('exit',()=>{clearTimeout(deadline);reject(Error('Fixture inspector exited before startup'));});
inspectorProcess.on('error',reject);
inspectorProcess.stdout.on('data',chunk=>{
output+=chunk;
if(output.includes('\n')){
clearTimeout(deadline);
try{resolve(JSON.parse(output.split('\n')[0]).port);}catch{reject(Error('Fixture inspector startup rejected'));}
}
});
inspectorProcess.stderr.on('data',()=>{});
});
const p=store.get('policy');p.browser.homeUrl=`http://127.0.0.1:${sink.address().port}`;p.brand={name:'Acme Secure Browser',color:'#245fbc'};p.dlp.rules=[{id:'secret-roadmap',label:'Roadmap',kind:'literal',value:'Secret Roadmap',action:'block'}];store.put('policy',p);store.db.prepare('INSERT INTO enrollments VALUES(?,?,?)').run(digest(code),Date.now()+600000,'smoke-user');
p.browser.allowDownloads=true;p.security.yara={enabled:true,rules:[{id:'test-marker',name:'Controlled malicious marker',source:'rule Block_Test { strings: $a = "SAFETYNET_BLOCK_TEST" condition: $a }'}],maxScanBytes:1048576};p.agents={enabled:true,scopes:['sessions','navigate','read','click','type','application:state','settings:get','settings:update','bookmarks:list','bookmarks:mutate','tabs:create','tabs:activate','tabs:close','tabs:group'],allowedHosts:['127.0.0.1'],allowSensitiveRead:false};store.put('policy',p);
const config={publicUrl:'http://127.0.0.1',secure:false,adminToken,inspectorUrl:`http://127.0.0.1:${inspectorPort}`,inspectorToken};const management=createApp(store,config).listen(0,'127.0.0.1');await new Promise(r=>management.on('listening',r));config.publicUrl=`http://127.0.0.1:${management.address().port}`;
const child=spawn(electron,['scripts/electron-smoke.cjs'],{stdio:'inherit',windowsHide:true,env:{...process.env,SAFETYNET_SMOKE_SERVER:config.publicUrl,SAFETYNET_SMOKE_CODE:code,SAFETYNET_SMOKE_SINK:p.browser.homeUrl,SAFETYNET_SMOKE_SECONDARY:`http://127.0.0.2:${secondary.address().port}`,SAFETYNET_SMOKE_USERDATA:join(temporary,'browser'),SAFETYNET_SMOKE_ARTIFACTS:resolve('artifacts'),SAFETYNET_SMOKE_ADMIN:adminToken}});
const timeout=setTimeout(()=>child.kill(),240000);
const exitCode=await new Promise(resolve=>{child.on('exit',code=>resolve(code??1));child.on('error',()=>resolve(1));});clearTimeout(timeout);
for(const server of [management,sink,secondary])server.closeAllConnections();
await Promise.all([new Promise(r=>management.close(r)),new Promise(r=>sink.close(r)),new Promise(r=>secondary.close(r))]);store.db.close();
inspectorProcess.kill();
// Temporary paths originate from mkdtemp under the OS temp directory.
rmSync(temporary,{recursive:true,force:true});process.exit(exitCode);
+59
View File
@@ -0,0 +1,59 @@
// Deterministic UI fixture: public invented metadata only; no production main process.
const {app,BrowserWindow,ipcMain}=require('electron');
const fs=require('node:fs'),path=require('node:path'),os=require('node:os');
const fixtureDirectory=fs.mkdtempSync(path.join(os.tmpdir(),'safetynet-ui-fixture-'));
function cleanup(){
const target=path.resolve(fixtureDirectory),parent=path.resolve(os.tmpdir());
if(path.dirname(target)===parent&&path.basename(target).startsWith('safetynet-ui-fixture-')){
try{fs.rmSync(target,{recursive:true,force:true});}catch{}
}
}
app.setPath('userData',path.join(fixtureDirectory,'profile'));
app.disableHardwareAcceleration();
app.commandLine.appendSwitch('force-device-scale-factor','1');
const watchdog=setTimeout(()=>app.exit(1),20000);
let locked=false;
const state=()=>({ready:true,enrolled:true,brand:{name:'SafetyNet'},policyVersion:1,url:'https://example.test/',message:'UI fixture · public example metadata',aiEnabled:true,agentsEnabled:true,documentScanEnabled:true,passwordManagerEnabled:true,vaultExists:true,vaultLocked:locked});
const vaultStatus=()=>({exists:true,locked,enabled:true,idleLockSeconds:120,allowSaving:true,allowAutofill:true});
ipcMain.handle('ui-fixture',(_event,method)=>{
if(method==='state')return {ok:true,data:state()};
if(method==='vaultStatus')return {ok:true,data:vaultStatus()};
if(method==='vaultList')return {ok:true,data:locked?[]:[{id:'fixture-1',origin:'https://example.test',label:'Public example account',username:'[email protected]'}]};
if(method==='vaultLock'){locked=true;return {ok:true,data:vaultStatus()};}
if(method==='vaultUnlock'){locked=false;return {ok:true,data:vaultStatus()};}
if(['toggleVault','toggleAI'].includes(method))return {ok:true,data:null};
return {ok:false,error:'This preview does not perform real browser or credential operations.'};
});
const preload=path.join(fixtureDirectory,'fixture-preload.cjs');
fs.writeFileSync(preload,`const {contextBridge,ipcRenderer}=require('electron');const api={onState:()=>()=>{}};for(const method of ['state','toggleVault','toggleAI','vaultStatus','vaultList','vaultLock','vaultUnlock','vaultCreate','vaultSave','vaultDelete','vaultFill','vaultGenerate'])api[method]=(...args)=>ipcRenderer.invoke('ui-fixture',method,...args);contextBridge.exposeInMainWorld('safetynet',api);`);
app.whenReady().then(async()=>{
let win;
try{
win=new BrowserWindow({show:false,useContentSize:true,width:1320,height:900,webPreferences:{preload,contextIsolation:true,sandbox:true,nodeIntegration:false}});
await win.loadFile(path.resolve('apps/browser/index.html'));
await win.webContents.executeJavaScript(`document.getElementById('passwords').click()`);
for(let n=0;n<40;n++){
if(await win.webContents.executeJavaScript(`document.getElementById('vault-list').textContent.includes('Public example account')`))break;
await new Promise(resolve=>setTimeout(resolve,50));
}
await win.webContents.executeJavaScript(`(()=>{const label=document.createElement('div');label.id='fixture-label';label.textContent='UI fixture preview · invented public metadata';label.style.cssText='position:fixed;left:30px;top:135px;color:#8994a3;font:12px Segoe UI';document.body.append(label);})()`);
await win.webContents.executeJavaScript(`new Promise(resolve=>requestAnimationFrame(()=>requestAnimationFrame(resolve)))`);
fs.mkdirSync(path.resolve('artifacts'),{recursive:true});
fs.writeFileSync(path.resolve('artifacts/ui-vault-preview.png'),(await win.webContents.capturePage()).toPNG());
await win.webContents.executeJavaScript(`document.getElementById('vault-lock').click()`);
for(let n=0;n<40;n++){
if(await win.webContents.executeJavaScript(`!document.getElementById('vault-access').hidden`))break;
await new Promise(resolve=>setTimeout(resolve,50));
}
fs.writeFileSync(path.resolve('artifacts/ui-vault-locked-preview.png'),(await win.webContents.capturePage()).toPNG());
const bounds=await win.webContents.executeJavaScript(`JSON.stringify({header:document.querySelector('header').getBoundingClientRect().height,vaultWidth:document.getElementById('vault').getBoundingClientRect().width,vaultTop:document.getElementById('vault').getBoundingClientRect().top,missingIcons:[...document.images].filter(i=>!i.complete||!i.naturalWidth).length,locked:document.getElementById('vault-open').hidden,masked:document.getElementById('vault-master').type==='password'})`);
fs.writeFileSync(path.resolve('artifacts/ui-vault-preview-layout.json'),bounds);
win.setContentSize(800,650);
await win.webContents.executeJavaScript(`new Promise(resolve=>requestAnimationFrame(()=>requestAnimationFrame(resolve)))`);
fs.writeFileSync(path.resolve('artifacts/ui-vault-compact-preview.png'),(await win.webContents.capturePage()).toPNG());
console.log('UI fixture captured: unlocked and locked password panels.');
win.destroy();win=null;clearTimeout(watchdog);
cleanup();app.exit(0);
}catch{win?.destroy();clearTimeout(watchdog);cleanup();app.exit(1);}
}).catch(()=>app.exit(1));
app.on('will-quit',cleanup);
+201
View File
@@ -0,0 +1,201 @@
'use strict';
if (!process.versions.electron) {
const fs = require('node:fs'), path = require('node:path'), os = require('node:os');
const { spawn } = require('node:child_process');
const owned = fs.mkdtempSync(path.join(os.tmpdir(), 'safetynet-ui-showcase-'));
const env = { ...process.env, SAFETYNET_SHOWCASE_PROFILE: owned }; delete env.ELECTRON_RUN_AS_NODE;
const child = spawn(require('electron'), [__filename], { stdio: 'inherit', windowsHide: true, env });
const deadline = setTimeout(() => child.kill(), 90_000);
const finish = code => {
clearTimeout(deadline);
const resolved = path.resolve(owned);
if (!resolved.startsWith(path.resolve(os.tmpdir()) + path.sep) || !path.basename(resolved).startsWith('safetynet-ui-showcase-')) throw Error('Unsafe showcase cleanup');
fs.rmSync(resolved, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 });
process.exit(code ?? 1);
};
child.once('error', () => finish(1)); child.once('exit', finish);
} else {
// Finite test harness for the real trusted shell. No production browser startup,
// site view, real credentials, network browsing or external application state.
const { app, BrowserWindow, ipcMain, nativeTheme } = require('electron');
const fs = require('node:fs');
const path = require('node:path');
const os = require('node:os');
const assert = require('node:assert/strict');
const { capturePNG } = require('../apps/browser/visual-capture.cjs');
app.disableHardwareAcceleration(); // Windows fixture uses the CPU compositor; production keeps its sandboxed defaults.
app.commandLine.appendSwitch('force-device-scale-factor', '1');
const root = path.resolve(__dirname, '..');
const profile = process.env.SAFETYNET_SHOWCASE_PROFILE || fs.mkdtempSync(path.join(os.tmpdir(), 'safetynet-ui-showcase-'));
if (!profile.startsWith(path.resolve(os.tmpdir()) + path.sep)) throw Error('Unsafe showcase profile');
app.setPath('userData', profile);
const output = path.join(root, 'artifacts');
fs.mkdirSync(output, { recursive: true });
const methods = ['createTab','activateTab','closeTab','groupTab','mutateBookmarks','updateSettings','authorizeSetting','state', 'windowControls', 'setChromeLayout', 'shareURL', 'enroll', 'sso', 'navigate', 'back', 'forward', 'reload', 'ai', 'inspectFile', 'agentConnection', 'toggleAI', 'toggleVault', 'vaultStatus', 'vaultCreate', 'vaultUnlock', 'vaultLock', 'vaultList', 'vaultSave', 'vaultDelete', 'vaultFill', 'vaultGenerate'];
const preload = path.join(profile, 'showcase-preload.cjs');
fs.writeFileSync(preload, `const {contextBridge,ipcRenderer}=require('electron'); const methods=${JSON.stringify(methods)}; const api={};for(const method of methods)api[method]=(...args)=>ipcRenderer.invoke('showcase:call',method,args);api.onState=callback=>{const listener=(_event,state)=>callback(state);ipcRenderer.on('showcase:state',listener);return()=>ipcRenderer.removeListener('showcase:state',listener);};contextBridge.exposeInMainWorld('safetynet',api);`);
const fixtures = [
{ title: 'Apple Documentation', url: 'https://developer.apple.com/' },
{ title: 'GitHub', url: 'https://github.com/' },
{ title: 'MDN', url: 'https://developer.mozilla.org/' },
{ title: 'Wikipedia', url: 'https://wikipedia.org/' },
{ title: 'Company Intranet', url: 'https://intranet.example.test/' },
{ title: 'Design Library', url: 'https://design.example.test/' }
];
let state = { ready: true, enrolled: true, brand: { name: 'SafetyNet' }, url: 'https://example.test', pageTitle: 'Reference Workspace', pageColor: '#8aacb4', canNavigate: true, policyVersion: 12, message: 'Public fixture · centrally managed workspace', aiEnabled: true, agentsEnabled: true, documentScanEnabled: true, passwordManagerEnabled: true, vaultLocked: false };
let nextTab=1;state.tabsRevision=0;state.tabs=[{id:'showcase-native-1',url:state.url,title:state.pageTitle,color:state.pageColor,group:'',startPage:false,canGoBack:false,canGoForward:false}];state.activeTabId=state.tabs[0].id;
function snapshot(){const tab=state.tabs.find(tab=>tab.id===state.activeTabId);state={...state,url:tab.url,pageTitle:tab.title,pageColor:tab.color,tabsRevision:state.tabsRevision+1};return JSON.parse(JSON.stringify(state));}
function publish(sender){const result=snapshot();sender.send('showcase:state',result);return result;}
state.settings={available:true,visible:true,hiddenSections:[],lockedSections:[],appearance:{mode:'system',accent:'blue',tabMode:'separate'}};
state.bookmarks={managed:[{...fixtures[4],id:'showcase-company',folder:'Company'}],personal:{revision:0,items:fixtures.filter((_,i)=>i!==4).map((item,i)=>({...item,id:`showcase-${i}`,folder:'Work'}))},allowUserAdd:true,allowUserEdit:true,allowUserDelete:true,adminReadUserBookmarks:true};
let vaultLocked = false;
const records = [], screenshots = [], consoleErrors = [];
let window, finished = false;
function cleanup() {
if (path.resolve(profile).startsWith(path.resolve(os.tmpdir()) + path.sep) && path.basename(profile).startsWith('safetynet-ui-showcase-')) {
try { fs.rmSync(profile, { recursive: true, force: true }); } catch {}
}
}
if (!process.env.SAFETYNET_SHOWCASE_PROFILE) app.on('quit', cleanup);
const watchdog = setTimeout(() => { console.error('UI showcase exceeded 80 seconds'); app.exit(1); }, 80_000);
watchdog.unref();
ipcMain.handle('showcase:call', (event, method, args) => {
if (event.sender !== window?.webContents || !methods.includes(method)) return { ok: false, error: 'Showcase operation refused' };
let data = null;
const navigation=typeof args[0]==='object'?args[0]:{url:args[0],tabId:state.activeTabId};
if(method==='navigate'&&navigation.url==='https://example.test/slow'){const id=navigation.tabId;return new Promise(resolve=>setTimeout(()=>{const tab=state.tabs.find(tab=>tab.id===id);if(tab){tab.url=navigation.url;tab.title='Delayed public fixture';tab.startPage=false;}resolve({ok:true,data:publish(event.sender)});},250));}
if (method === 'state' || ['enroll', 'sso', 'back', 'forward', 'reload'].includes(method)) data = snapshot();
else if(method==='createTab'){const tab={id:`showcase-native-${++nextTab}`,url:'',title:'New Tab',group:args[0]?.group||'',startPage:true,color:'#b8c7dd',canGoBack:false,canGoForward:false};state.tabs.push(tab);state.activeTabId=tab.id;data=publish(event.sender);}
else if(method==='activateTab'){assert.ok(state.tabs.some(tab=>tab.id===args[0]));state.activeTabId=args[0];data=publish(event.sender);}
else if(method==='closeTab'){const index=state.tabs.findIndex(tab=>tab.id===args[0]);assert.ok(index>=0);state.tabs.splice(index,1);if(!state.tabs.length){state.tabs.push({id:`showcase-native-${++nextTab}`,url:'',title:'New Tab',group:'',startPage:true,color:'#b8c7dd',canGoBack:false,canGoForward:false});}if(state.activeTabId===args[0])state.activeTabId=state.tabs[Math.min(index,state.tabs.length-1)].id;data=publish(event.sender);}
else if(method==='groupTab'){assert.ok(state.settings.visible&&!state.settings.hiddenSections.includes('library')&&!state.settings.lockedSections.includes('library'));const tab=state.tabs.find(tab=>tab.id===args[0].id);assert.ok(tab);tab.group=args[0].group;data=publish(event.sender);}
else if(method==='mutateBookmarks'){const input=args[0];if(!state.settings.visible||state.settings.hiddenSections.includes('library')||state.settings.lockedSections.includes('library')||input.expectedRevision!==state.bookmarks.personal.revision)return {ok:false,error:'Managed bookmark refused'};assert.equal(input.action,'add');state.bookmarks.personal={revision:state.bookmarks.personal.revision+1,items:[...state.bookmarks.personal.items,input.bookmark]};data=state;event.sender.send('showcase:state',state);}
else if(method==='updateSettings'){if(!state.settings.available||!state.settings.visible||state.settings.hiddenSections.includes('appearance')||state.settings.lockedSections.includes('appearance'))return{ok:false,error:'Managed setting refused'};state.settings={...state.settings,appearance:{...args[0]}};data=state.settings;}
else if(method==='authorizeSetting'){if(!state.settings.available||!state.settings.visible||state.settings.hiddenSections.includes(args[0])||state.settings.lockedSections.includes(args[0]))return{ok:false,error:'Managed setting refused'};data={allowed:true};}
else if (method === 'navigate') { const url = new URL(navigation.url); assert.equal(url.protocol, 'https:');const tab=state.tabs.find(tab=>tab.id===navigation.tabId);assert.ok(tab);tab.url=url.href;tab.title=fixtures.find(item=>item.url===url.href)?.title||'Reference Workspace';tab.startPage=false;data=publish(event.sender); }
else if (method === 'setChromeLayout') {
const layout = args[0]; assert.ok([64, 104].includes(layout.height));
for (const key of ['sidebarOpen', 'startPageOpen', 'overviewOpen', 'toolsOpen']) assert.equal(typeof layout[key], 'boolean');
records.push({ method, ...layout, nativeHidden: layout.startPageOpen || layout.overviewOpen || layout.toolsOpen }); data = { applied: true };
} else if (method === 'windowControls') { assert.ok(['minimize', 'maximize', 'close'].includes(args[0])); records.push({ method, action: args[0], nativeFlag: false }); data = { recorded: true }; }
else if (method === 'shareURL') data = { shared: true };
else if (method === 'toggleAI' || method === 'toggleVault') { records.push({ method, open: args[0] }); data = { applied: true }; }
else if (method === 'vaultStatus') data = { enabled: true, exists: true, locked: vaultLocked, allowSaving: true, allowAutofill: true, idleLockSeconds: 300 };
else if (method === 'vaultList') data = [{ id: 'public-fixture', origin: 'https://example.test', username: 'example-user', label: 'Public demonstration account' }];
else if (method === 'vaultLock') { vaultLocked = true; data = { locked: true }; }
else if (method === 'vaultCreate' || method === 'vaultUnlock') { vaultLocked = false; data = { locked: false }; }
else if (method === 'vaultGenerate') data = 'PUBLIC-DEMONSTRATION-ONLY';
else if (method === 'vaultSave' || method === 'vaultDelete' || method === 'vaultFill') data = { completed: true };
else if (method === 'ai') data = { answer: 'Public local fixture response.' };
else if (method === 'agentConnection') data = { address: 'http://127.0.0.1:0', credentialPath: 'Public showcase · no pairing credential' };
return { ok: true, data };
});
const delay = milliseconds => new Promise(resolve => setTimeout(resolve, milliseconds));
async function execute(source) { return window.webContents.executeJavaScript(source, true); }
async function reloadShell() {
const loaded = new Promise((resolve, reject) => {
const timer = setTimeout(() => reject(Error('Showcase shell reload timed out')), 5000);
window.webContents.once('did-finish-load', () => { clearTimeout(timer); resolve(); });
});
window.webContents.reload(); await loaded; await delay(100);
}
async function waitFor(source, expected) {
for (let attempt = 0; attempt < 40; attempt++) { if (await execute(source) === expected) return; await delay(70); }
assert.equal(await execute(source), expected);
}
async function click(id) { await execute(`document.getElementById(${JSON.stringify(id)}).click()`); await delay(100); }
async function appearance(theme, mode) {
await execute(`for(const [id,value] of ${JSON.stringify([['theme-mode', theme], ['tab-mode', mode]])}){const element=document.getElementById(id);element.value=value;element.dispatchEvent(new Event('change',{bubbles:true}));}`); await delay(100);
}
async function accent(value) {
await execute(`(()=>{const selector=document.getElementById('accent-mode');selector.value=${JSON.stringify(value)};selector.dispatchEvent(new Event('change',{bubbles:true}));})()`); await delay(90);
}
async function shot(name) {
console.log('Showcase capture: ' + name);
await execute('document.fonts.ready'); await delay(90);
const measurements = await execute(`(()=>{const rect=id=>{const element=document.getElementById(id),r=element.getBoundingClientRect();return{hidden:element.hidden,x:r.x,y:r.y,width:r.width,height:r.height}};const brokenImages=[...document.images].filter(image=>!image.complete||!image.naturalWidth).map(image=>image.getAttribute('src'));return{viewport:{width:innerWidth,height:innerHeight,zoom:devicePixelRatio},theme:document.documentElement.dataset.theme,effectiveTheme:document.documentElement.dataset.effectiveTheme,accent:document.documentElement.dataset.accent,tabMode:document.documentElement.dataset.tabMode,chrome:rect('chrome'),toolbar:document.querySelector('.toolbar').getBoundingClientRect().height,library:rect('library'),ai:rect('ai'),vault:rect('vault'),startPage:rect('start-page'),overview:rect('overview'),tools:rect('tools-menu'),scrollWidth:document.documentElement.scrollWidth,brokenImages,error:document.getElementById('error').textContent,passwordFieldsEmpty:[...document.querySelectorAll('input[type=password]')].every(input=>!input.value)}})()`);
assert.equal(measurements.toolbar, 64); assert.ok([64, 104].includes(measurements.chrome.height));
assert.equal(measurements.scrollWidth, measurements.viewport.width); assert.deepEqual(measurements.brokenImages, []); assert.equal(measurements.passwordFieldsEmpty, true); assert.equal(measurements.error, '');
if (!measurements.library.hidden) assert.equal(measurements.library.width, 240);
for (const panel of ['ai', 'vault']) if (!measurements[panel].hidden) assert.equal(measurements[panel].width, 360);
// This Windows host's native capturePage can return an earlier compositor frame.
// Exercise the existing trusted screenshot-only CDP fallback for finite fixtures.
const capturePage = window.webContents.capturePage;
let png;
try { window.webContents.capturePage = async () => { throw Error('Use finite showcase compositor fallback'); }; png = await capturePNG(window.webContents); }
finally { window.webContents.capturePage = capturePage; }
fs.writeFileSync(path.join(output, name + '.png'), png); screenshots.push({ name, ...measurements });
}
app.whenReady().then(async () => {
window = new BrowserWindow({ width: 1320, height: 900, useContentSize: true, frame: false, show: true, backgroundColor: '#f7f8fa', webPreferences: { preload, contextIsolation: true, sandbox: true, nodeIntegration: false, zoomFactor: 1 } });
window.webContents.setZoomFactor(1);
window.webContents.on('console-message', event => { if (event.level === 'error' || event.level >= 3) consoleErrors.push(event.message); });
window.webContents.on('will-navigate', event => event.preventDefault());
window.webContents.setWindowOpenHandler(() => ({ action: 'deny' }));
await window.loadFile(path.join(root, 'apps/browser/index.html'));
await execute(`localStorage.clear();localStorage.setItem('sbrowser.bookmarks',${JSON.stringify(JSON.stringify(fixtures))});localStorage.setItem('sbrowser.theme','"light"');localStorage.setItem('sbrowser.tab-mode','"separate"');localStorage.setItem('sbrowser.accent','{"toString":0}');`);
await reloadShell();
assert.equal(await execute(`document.documentElement.dataset.accent`), 'blue');
await appearance('auto', 'separate'); nativeTheme.themeSource = 'dark';
await waitFor(`document.documentElement.dataset.effectiveTheme`, 'dark');
nativeTheme.themeSource = 'light';
await waitFor(`document.documentElement.dataset.effectiveTheme`, 'light');
await appearance('dark', 'separate'); nativeTheme.themeSource = 'light'; await delay(90);
assert.equal(await execute(`document.body.dataset.theme`), 'dark');
await accent('teal'); await reloadShell();
assert.equal(await execute(`document.documentElement.dataset.accent`), 'teal');
assert.equal(await execute(`document.documentElement.dataset.theme`), 'dark');
assert.equal(await execute(`document.documentElement.style.getPropertyValue('--accent')`), '#007d76');
await accent('blue'); await appearance('light', 'separate');
// Real DOM interactions verify tabs, bookmarks, themes and overlay signaling.
await click('tools-toggle'); await click('bookmark');
await execute(`document.getElementById('bookmark-form').requestSubmit()`);
await waitFor(`document.getElementById('bookmark-editor').open`,false);
assert.equal(state.bookmarks.managed.length+state.bookmarks.personal.items.length,7);
assert.equal(await execute(`JSON.parse(localStorage.getItem('sbrowser.bookmarks')).length`), 6,'User bookmarks must not be mutated through renderer storage');
await click('new-tab'); await click('sidebar-toggle');
assert.equal(await execute(`document.querySelectorAll('#favorites-grid .favorite-card').length`), 7);
await shot('sbrowser-light');
await appearance('dark', 'compact'); await shot('sbrowser-dark');
await click('tab-overview'); assert.equal(await execute(`document.querySelectorAll('#overview-grid .overview-card').length`), 2); await shot('sbrowser-overview');
await click('overview-close'); await appearance('light', 'separate'); await click('tools-toggle'); await shot('sbrowser-settings');
await appearance('dark', 'separate'); await accent('violet'); await shot('sbrowser-theme-violet');
await appearance('light', 'separate'); await accent('blue');
await click('passwords'); await shot('sbrowser-vault'); await click('vault-close');
await appearance('light', 'compact'); window.setContentSize(800, 650); await delay(150); await shot('sbrowser-compact');
await click('tools-toggle'); await click('ai-toggle'); await shot('sbrowser-compact-panels'); await click('ai-close');
await execute(`document.getElementById('address').value='https://example.test/slow';document.getElementById('address-form').requestSubmit();`);
await click('new-tab'); await delay(300);
assert.equal(await execute(`document.querySelector('.browser-tab.active .tab-label').textContent`), 'New Tab');
assert.equal(await execute(`document.getElementById('address').value`), '');
assert.equal(await execute(`document.getElementById('start-page').hidden`), false);
const latestLayout=records.findLast(record=>record.method==='setChromeLayout');assert.ok(latestLayout.startPageOpen&&latestLayout.nativeHidden);
for (const overlay of ['startPageOpen', 'overviewOpen', 'toolsOpen']) assert.ok(records.some(record => record.method === 'setChromeLayout' && record[overlay] && record.nativeHidden));
// Policy updates override stale or hostile renderer preferences immediately.
state={...state,settings:{...state.settings,lockedSections:['appearance','ai','passwords','documentScan','agents'],appearance:{mode:'dark',accent:'violet',tabMode:'compact'}}};
window.webContents.send('showcase:state',state);await delay(120);
await execute(`localStorage.setItem('sbrowser.theme','"light"');localStorage.setItem('sbrowser.accent','"blue"');window.dispatchEvent(new StorageEvent('storage',{key:'sbrowser.theme'}));`);
assert.equal(await execute(`document.body.dataset.theme`),'dark');
assert.equal(await execute(`document.documentElement.dataset.accent`),'violet');
assert.equal(await execute(`['theme-mode','accent-mode','tab-mode','ai-toggle','passwords','inspect','agents'].every(id=>document.getElementById(id).disabled)`),true);
assert.equal((await execute(`window.safetynet.updateSettings({mode:'light',accent:'blue',tabMode:'separate'})`)).ok,false);
state={...state,settings:{...state.settings,lockedSections:[],hiddenSections:['appearance','ai','passwords','documentScan','agents'],visible:true}};
window.webContents.send('showcase:state',state);await delay(100);
assert.equal(await execute(`['appearance-section','ai-toggle','sidebar','passwords','inspect','agents'].every(id=>document.getElementById(id).hidden)`),true);
state={...state,settings:{...state.settings,visible:false}};window.webContents.send('showcase:state',state);await delay(100);
assert.equal(await execute(`document.getElementById('tools-toggle').hidden&&document.getElementById('tools-menu').hidden`),true);
state={...state,settings:{...state.settings,hiddenSections:['appearance']}};window.webContents.send('showcase:state',state);await delay(100);
assert.equal(await execute(`!document.getElementById('quick-ai').hidden&&!document.getElementById('quick-ai').disabled&&document.getElementById('appearance-section').hidden`),true);
await click('quick-ai');assert.equal(await execute(`document.getElementById('ai').hidden`),false);await click('ai-close');
await reloadShell();assert.equal(await execute(`document.getElementById('tools-toggle').hidden&&document.body.dataset.theme==='dark'`),true);
await execute(`document.getElementById('error').textContent=''`);
for (const control of ['window-minimize', 'window-maximize', 'window-close']) await click(control);
assert.equal(records.filter(record => record.method === 'windowControls').length, 3);
fs.writeFileSync(path.join(output, 'sbrowser-ui-layout.json'), JSON.stringify({ fixtureOnly: true, managedSettingsProof:{liveLocks:true,hiddenSections:true,globalHidden:true,localStorageCannotOverride:true,reloadPreservesPolicy:true,directUpdateRejected:true,globalHiddenPreservesApprovedFeatures:true},screenshots, records, consoleErrors }, null, 2));
assert.deepEqual(consoleErrors, []);
finished = true; clearTimeout(watchdog); console.log('UI showcase passed: eight screenshots, live system themes, persisted accents, real DOM interactions and delayed-navigation regression.');
if(window.webContents.debugger.isAttached())window.webContents.debugger.detach();
window.destroy(); app.exit(0);
}).catch(error => { clearTimeout(watchdog); console.error(error.message); if (!finished) app.exit(1); });
}
+56
View File
@@ -0,0 +1,56 @@
import {createRequire} from 'node:module';
import {spawn} from 'node:child_process';
import fs from 'node:fs/promises';
import path from 'node:path';
import os from 'node:os';
import assert from 'node:assert/strict';
const require=createRequire(import.meta.url);
const {startAgentControl}=require('../apps/browser/agent-control.cjs');
const {startInspector}=require('../apps/browser/inspection.cjs');
const root=path.resolve('dist/win-unpacked');
if(process.platform!=='win32')throw Error('Windows package verification requires Windows');
const {extractFile}=require('@electron/asar');
for(const file of ['apps/browser/policy-assignment.cjs','packages/core/policy-groups.mjs','apps/browser/tab-registry.cjs','apps/browser/agent-adapters.cjs','apps/browser/agent-control.cjs','apps/browser/password-fill.cjs','apps/browser/diagnostics.cjs','packages/core/diagnostics.mjs','packages/core/security.mjs'])assert.deepEqual(extractFile(path.join(root,'resources/app.asar'),path.normalize(file)),await fs.readFile(file),`Packaged device/session policy source is stale: ${file}`);
for(const file of ['apps/browser/main.cjs','apps/browser/preload.cjs','apps/browser/site-preload.cjs','apps/browser/clipboard-deny.cjs','apps/browser/clipboard-guard.cjs','apps/browser/clipboard-dom.cjs','apps/browser/page-clipboard-guard.cjs','apps/browser/startup-security.cjs','apps/browser/visual-capture.cjs','apps/browser/renderer.js','apps/browser/index.html','apps/browser/style.css','packages/core/clipboard.mjs']){
assert.deepEqual(extractFile(path.join(root,'resources/app.asar'),path.normalize(file)),await fs.readFile(file),`Packaged source is stale: ${file}`);
}
for(const file of ['apps/browser/inspection.cjs','apps/browser/managed-settings.cjs','apps/browser/management-channel.cjs','apps/browser/enterprise-inspection.cjs','apps/browser/icap-client.cjs','apps/browser/network-posture.cjs','apps/browser/download-gate.cjs','packages/core/enterprise.mjs','packages/core/semantic.mjs','packages/core/managed-settings.mjs','packages/core/policy-channel.cjs','packages/core/policy.mjs'])assert.ok(extractFile(path.join(root,'resources/app.asar'),path.normalize(file)).equals(await fs.readFile(file)),`Packaged source is stale: ${file}`);
for(const file of ['semantic.py','engine.py','server.py','windows_containment.py','windows_appcontainer.py','sandbox_worker.py','provision_runtime_acl.py'])assert.deepEqual(await fs.readFile(path.join(root,'resources/inspector',file)),await fs.readFile(path.join('apps/inspector',file)),`Packaged inspector is stale: ${file}`);
const temporary=await fs.mkdtemp(path.join(os.tmpdir(),'safetynet-package-'));
for(const file of ['apps/browser/bookmarks.cjs','packages/core/bookmarks.mjs'])assert.ok(extractFile(path.join(root,'resources/app.asar'),path.normalize(file)).equals(await fs.readFile(file)),`Packaged bookmark source is stale: ${file}`);
function run(executable,args,input,timeoutMs=15000){return new Promise((resolve,reject)=>{
const child=spawn(executable,args,{stdio:['pipe','pipe','pipe'],windowsHide:true,env:{...process.env,PYTHONDONTWRITEBYTECODE:'1'}});let output='',errors='';
const timer=setTimeout(()=>{child.kill();reject(Error('Package verification timed out'));},timeoutMs);
child.on('error',reject);child.stdout.on('data',data=>output+=data);child.stderr.on('data',data=>errors+=data);
child.on('close',code=>{clearTimeout(timer);resolve({code,output,errors});});child.stdin.end(input);
});}
let service;
try{
const inspectorBytecode=path.join(root,'resources/inspector/__pycache__');
const bytecodeExists=()=>fs.stat(inspectorBytecode).then(()=>true,error=>{if(error.code==='ENOENT')return false;throw error;});
assert.equal(await bytecodeExists(),false,'Package must start with no inspector bytecode cache');
const packagedInspector=startInspector(path.join(root,'resources'),true);
assert.ok(packagedInspector,'Packaged inspector runtime is missing');
try{
const verdict=await packagedInspector.inspect(Buffer.from('Public package verification text'),{dlp:{maxBytes:1048576,rules:[],semantic:{enabled:false}}});
assert.equal(verdict.decision,'allow','Packaged contained inspector failed');
assert.equal(verdict.coverage.complete,true);
}finally{packagedInspector.stop();}
const semanticPath=path.join(root,'resources/semantic');
const actual=await run(path.join(root,'resources/python/python.exe'),['-c','import sys; sys.path.insert(0,sys.argv[1]); from semantic import NativeSemanticModel; m=NativeSemanticModel(sys.argv[2],sys.argv[3]); vectors=m.text_vectors("Public information about weather forecasting."); assert len(vectors)>=1 and len(vectors[0])==768; m.close(); print("Offline packaged semantic CPU inference verified.")',path.join(root,'resources/inspector'),path.join(semanticPath,'models'),path.join(semanticPath,'searchi-gemma-worker.exe')],undefined,45000);
assert.equal(actual.code,0,'Packaged offline semantic inference failed');assert.ok(actual.output.includes('Offline packaged semantic CPU inference verified.'));
service=await startAgentControl({authorize:async()=>({allowed:true,role:'agent',scopes:['sessions:list']}),audit:async()=>{},actions:{sessions:async()=>[{id:'managed',url:'https://example.test/'}]}});
const encrypted=await run(path.join(root,'resources/python/python.exe'),[path.join(root,'resources/inspector/dpapi.py'),'protect'],JSON.stringify({address:service.address,token:service.token}));
assert.equal(encrypted.code,0,'Packaged DPAPI failed');
const connection=path.join(temporary,'connection.json'),request=path.join(temporary,'request.json');
await fs.writeFile(connection,JSON.stringify({format:'windows-dpapi-v1',protectedConnection:encrypted.output}));
await fs.writeFile(request,JSON.stringify({action:'sessions'}));
const result=await run(path.join(root,'SafetyNet.exe'),[`--agent-connection=${connection}`,`--agent-action=${request}`]);
assert.equal(result.code,0,'Packaged agent helper failed');assert.equal(JSON.parse(result.output).result[0].id,'managed');assert.equal(result.output.includes(service.token),false);
assert.equal(await bytecodeExists(),false,'Cold packaged startup must not create inspector bytecode files');
console.log('Packaged security sources, Windows-contained inspector, offline EmbeddingGemma 2 CPU inference, Windows agent helper and bundled DPAPI runtime passed.');
}finally{
await service?.close();
if(!temporary.startsWith(path.join(os.tmpdir(),'safetynet-package-')))throw Error('Unexpected temporary directory');
await fs.rm(temporary,{recursive:true,force:true});
}