Files

44 lines
4.9 KiB
JavaScript
Raw Permalink Normal View History

// Explicit native installer dispatch proof; does not claim NSIS execution or
// an elevated-to-different-standard-user Program Files installation proof.
import test from 'node:test';
import assert from 'node:assert/strict';
import {readFile,mkdir,readdir,copyFile,mkdtemp,rm,writeFile} from 'node:fs/promises';
import {spawn} from 'node:child_process';
import path from 'node:path';
async function run(executable,args){
const child=spawn(executable,args,{windowsHide:true,stdio:['ignore','pipe','pipe']});let output='',bytes=0;
for(const stream of [child.stdout,child.stderr])stream.on('data',chunk=>{bytes+=chunk.length;if(bytes>4096)child.kill();else output+=chunk.toString();});
const timer=setTimeout(()=>child.kill(),60000);
try{return await new Promise((resolve,reject)=>{child.once('error',reject);child.once('exit',(code,signal)=>resolve({code,signal,output}));});}finally{clearTimeout(timer);}
}
test('actual fixed installer hook dispatch provisions copied runtime then verifies deterministic native package SID',{
skip:process.platform!=='win32'||process.env.SAFETYNET_NATIVE_INSTALLER_ACL!=='1',timeout:90000
},async()=>{
const repository=path.resolve('.'),artifacts=path.join(repository,'artifacts');
await mkdir(artifacts,{recursive:true});const root=await mkdtemp(path.join(artifacts,'installer ACL native-'));
const resources=path.join(root,'resources'),python=path.join(resources,'python'),inspector=path.join(resources,'inspector');
const proof={startedAt:new Date().toISOString(),outcome:'running',nsisPluginExecuted:false,crossUserProgramFilesProven:false};
try{
await Promise.all([mkdir(python,{recursive:true}),mkdir(inspector,{recursive:true}),mkdir(path.join(resources,'semantic'),{recursive:true})]);
for(const item of await readdir(path.join(repository,'.runtime/windows/python'),{withFileTypes:true}))if(item.isFile())await copyFile(path.join(repository,'.runtime/windows/python',item.name),path.join(python,item.name));
for(const name of ['provision_runtime_acl.py','windows_appcontainer.py','windows_containment.py'])await copyFile(path.join(repository,'apps/inspector',name),path.join(inspector,name));
await writeFile(path.join(resources,'semantic/public-marker.txt'),'Synthetic installer ACL role marker');
const hook=await readFile(path.join(repository,'scripts/install/windows-security.nsh'),'utf8');
const command=/nsExec::ExecToStack \/TIMEOUT=245000 '(.*)'/.exec(hook)?.[1];assert.ok(command);
const match=/^"\$INSTDIR\\resources\\python\\python.exe" -I -B "\$INSTDIR\\resources\\inspector\\provision_runtime_acl.py" --provision$/.exec(command);assert.ok(match,'Installer command must use the exact copied private interpreter and helper');
const executable=path.join(python,'python.exe'),helper=path.join(inspector,'provision_runtime_acl.py');
const provision=await run(executable,['-I','-B',helper,'--provision']);assert.equal(provision.code,0,provision.output);assert.equal(provision.signal,null);
const verified=JSON.parse(provision.output.trim());assert.equal(verified.verified,true);assert.equal(verified.rootCount,3);proof.profile=verified.profile;
const readonly=await run(executable,['-I','-B',helper]);assert.equal(readonly.code,0,readonly.output);assert.equal(JSON.parse(readonly.output).profile,verified.profile);
const script=`import sys,ctypes,json\nfrom pathlib import Path\nsys.path.insert(0,sys.argv[1])\nfrom windows_appcontainer import AppContainer,_api\nfrom ctypes import wintypes as W\ncontainer=AppContainer([sys.argv[1],sys.argv[2],sys.argv[3]])\nk,u,a=_api(); sid=ctypes.c_void_p(); assert u.DeriveAppContainerSidFromAppContainerName(container.name,ctypes.byref(sid))==0\ntext=W.LPWSTR(); assert a.ConvertSidToStringSidW(sid,ctypes.byref(text)); derived=text.value; k.LocalFree(text); a.FreeSid(sid)\nassert derived==container.sid_string\nprint(json.dumps({'matches':True,'profile':container.name,'packageAuthority':derived.startswith('S-1-15-2-')}))\n`;
const sid=await run(executable,['-I','-B','-c',script,inspector,python,path.join(resources,'semantic')]);assert.equal(sid.code,0,sid.output);
const identity=JSON.parse(sid.output);assert.equal(identity.matches,true);assert.equal(identity.packageAuthority,true);assert.equal(identity.profile,verified.profile);
proof.deterministicNativePackageSid=true;proof.provisionExit=0;proof.readOnlyVerifyExit=0;
const invalid=await run(executable,['-I','-B',helper,'--provision','--root',repository]);assert.notEqual(invalid.code,0);proof.callerChosenRootRejected=true;
proof.outcome='passed';
}catch(error){proof.outcome='failed';proof.errorType=error.name;throw error;}
finally{
await writeFile(path.join(artifacts,'installer-acl-native-proof-'+proof.startedAt.replaceAll(':','-')+'.json'),JSON.stringify(proof,null,2)+'\n');
const absolute=path.resolve(root);assert.equal(path.dirname(absolute),artifacts);assert.ok(path.basename(absolute).startsWith('installer ACL native-'));await rm(absolute,{recursive:true,force:true});
}
});