first commit
This commit is contained in:
commit
ff482ebe23
251 files changed
+19126
No files matched your search
@@ -0,0 +1,46 @@
|
||||
// Isolated native proof fixture; never loaded by the application.
|
||||
const {app,BrowserWindow,ipcMain,clipboard,ClipboardItem}=require('electron');
|
||||
const fs=require('node:fs'),path=require('node:path'),os=require('node:os'),http=require('node:http');
|
||||
const {attachPageClipboardGuard,disposePageClipboardGuard}=require('../apps/browser/page-clipboard-guard.cjs');
|
||||
const profile=fs.mkdtempSync(path.join(os.tmpdir(),'safetynet-frame-proof-profile-'));
|
||||
app.setPath('userData',profile);app.setPath('sessionData',profile);
|
||||
app.enableSandbox();app.disableHardwareAcceleration();
|
||||
const temporary=path.join(os.tmpdir(),`safetynet-frame-proof-${process.pid}.cjs`),records=[];
|
||||
const control=process.env.SAFETYNET_CLIP_PROOF_CONTROL==='1';
|
||||
const hooks=control?'':fs.readFileSync(path.resolve('apps/browser/site-preload.cjs'),'utf8');
|
||||
fs.writeFileSync(temporary,hooks+`\nlet fsDenied=false;try{require('node:fs');}catch{fsDenied=true;}require('electron').ipcRenderer.send('frame-proof',{main:process.isMainFrame,sandboxed:process.sandboxed,contextIsolated:process.contextIsolated,fsDenied,url:location.href});`);
|
||||
ipcMain.on('managed:visual-policy',event=>{event.returnValue={enabled:false};});
|
||||
ipcMain.on('frame-proof',(event,value)=>records.push({...value,processId:event.senderFrame.processId}));
|
||||
const timeout=setTimeout(()=>app.exit(1),15000);
|
||||
app.whenReady().then(async()=>{let win,server,original;try{
|
||||
original=[];for(const item of await clipboard.read()){const data={};for(const type of item.types)data[type]=await item.getType(type);original.push(new ClipboardItem(data));}await clipboard.writeText('frame-proof-sentinel');
|
||||
server=http.createServer((req,res)=>{res.setHeader('content-type','text/html');res.end(req.url==='/child'?'<textarea id="a">frame-proof-secret</textarea>':`<h1>Frame proof</h1><iframe id="child" srcdoc="<p>Frame text</p>"></iframe><iframe id="cross" src="http://localhost:${server.address().port}/child"></iframe>`);});await new Promise(resolve=>server.listen(0,'127.0.0.1',resolve));
|
||||
win=new BrowserWindow({show:true,webPreferences:{sandbox:true,contextIsolation:true,nodeIntegration:false,nodeIntegrationInSubFrames:true,preload:temporary}});await win.loadURL('about:blank');
|
||||
if(control){win.webContents.debugger.attach('1.3');await win.webContents.debugger.sendCommand('Page.enable',{});await win.webContents.debugger.sendCommand('Page.addScriptToEvaluateOnNewDocument',{source:'void 0;'});}
|
||||
else await attachPageClipboardGuard(win.webContents,()=>{throw Error('Proof guard detached');});
|
||||
await win.loadURL(`http://127.0.0.1:${server.address().port}/`);win.focus();win.webContents.focus();await new Promise(resolve=>setTimeout(resolve,300));
|
||||
win.show();win.focus();win.webContents.focus();await new Promise(resolve=>setTimeout(resolve,500));
|
||||
const srcdoc=await win.webContents.executeJavaScript(`(()=>{const frame=document.getElementById('child'),d=frame.contentDocument;d.body.innerHTML='<textarea id="a">frame-proof-secret</textarea>';const a=d.getElementById('a');a.focus();a.select();return {copied:d.execCommand('copy'),node:typeof frame.contentWindow.require,process:typeof frame.contentWindow.process,bridge:typeof frame.contentWindow.safetynet};})()`,true);
|
||||
const srcdocFrame=win.webContents.mainFrame.frames.find(frame=>frame.url==='about:srcdoc');
|
||||
const srcdocActivated=await srcdocFrame.executeJavaScript(`(()=>{const a=document.getElementById('a');a.focus();a.select();return {copied:document.execCommand('copy')};})()`,true);
|
||||
await new Promise(resolve=>setTimeout(resolve,300));
|
||||
const srcdocSafe=await clipboard.readText()==='frame-proof-sentinel';
|
||||
await clipboard.writeText('frame-proof-sentinel');
|
||||
const blank=await win.webContents.executeJavaScript(`(()=>{const frame=document.createElement('iframe');document.body.append(frame);const d=frame.contentDocument;d.body.innerHTML='<textarea id="a">frame-proof-secret</textarea>';const a=d.getElementById('a');a.focus();a.select();return {copied:d.execCommand('copy'),node:typeof frame.contentWindow.require,process:typeof frame.contentWindow.process};})()`,true);
|
||||
const blankFrame=win.webContents.mainFrame.frames.at(-1);
|
||||
const blankActivated=await blankFrame.executeJavaScript(`(()=>{const a=document.getElementById('a');a.focus();a.select();return {copied:document.execCommand('copy'),node:typeof require,process:typeof process};})()`,true);
|
||||
await new Promise(resolve=>setTimeout(resolve,300));
|
||||
const blankSafe=await clipboard.readText()==='frame-proof-sentinel';await new Promise(resolve=>setTimeout(resolve,100));
|
||||
await clipboard.writeText('frame-proof-sentinel');
|
||||
const crossFrame=win.webContents.mainFrame.frames.find(frame=>frame.url.includes('localhost'));
|
||||
win.show();win.focus();win.webContents.focus();await new Promise(resolve=>setTimeout(resolve,500));
|
||||
const cross=await crossFrame.executeJavaScript(`(()=>{const a=document.getElementById('a');a.focus();a.select();return {copied:document.execCommand('copy'),node:typeof require,process:typeof process,bridge:typeof safetynet};})()`,true);
|
||||
await new Promise(resolve=>setTimeout(resolve,300));
|
||||
const crossSafe=await clipboard.readText()==='frame-proof-sentinel';
|
||||
const mainProcess=records.find(r=>r.main)?.processId,crossProcess=records.find(r=>r.url.includes('localhost'))?.processId;
|
||||
const oopif=Number.isInteger(mainProcess)&&Number.isInteger(crossProcess)&&crossProcess!==mainProcess;
|
||||
console.log(JSON.stringify({control,records,srcdoc,srcdocActivated,srcdocSafe,blank,blankActivated,blankSafe,cross,crossSafe,oopif}));
|
||||
const protectedExpected=srcdocSafe&&blankSafe&&crossSafe;
|
||||
const controlExpected=srcdocActivated.copied===true&&blankActivated.copied===true&&cross.copied===true&&!srcdocSafe&&!blankSafe&&!crossSafe;
|
||||
if(original.length)await clipboard.write(original);else await clipboard.clear();if(!control)disposePageClipboardGuard(win.webContents);win.destroy();server.close();clearTimeout(timeout);fs.unlinkSync(temporary);app.exit((control?controlExpected:protectedExpected)&&oopif&&records.every(r=>r.sandboxed&&r.contextIsolated&&r.fsDenied)?0:1);
|
||||
}catch(error){console.log(JSON.stringify({fixtureError:error.name,message:error.message}));if(original?.length)await clipboard.write(original).catch(()=>{});if(win&&!control)disposePageClipboardGuard(win.webContents);win?.destroy();server?.close();clearTimeout(timeout);try{fs.unlinkSync(temporary);}catch{}app.exit(1);}});
|
||||
Reference in new issue
Block a user