Add policy-bound credential submission and native DLP audit proofs
This commit is contained in:
1 parent
b991ee9da6
commit
c8b6ff9cdd
45 files changed
+777
-98
No files matched your search
@@ -2,15 +2,15 @@ import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import vm from 'node:vm';
|
||||
import {createRequire} from 'node:module';
|
||||
const require=createRequire(import.meta.url),{fillScript}=require('../apps/browser/password-fill.cjs');
|
||||
const require=createRequire(import.meta.url),{fillScript,prepareFillScript}=require('../apps/browser/password-fill.cjs');
|
||||
const credential={origin:'https://work.example',username:'employee',password:'fixture-only-generated-password'};
|
||||
function fixture({url='https://work.example/login',action='https://work.example/signin',method='post',target='',visible=true,frame=false,multiple=false,override,focused=true,visibility='visible'}={}){
|
||||
class Input{constructor(type){this.type=type;this.name=type==='password'?'password':'username';this.autocomplete='';this.disabled=false;this.readOnly=false;}set value(value){this.stored=value;}get value(){return this.stored;}closest(){return null;}getClientRects(){return visible?[{}]:[];}dispatchEvent(){}}
|
||||
const user=new Input('text'),password=new Input('password');
|
||||
const form={action,method,target,querySelectorAll:()=>[user,password]};user.form=form;password.form=form;
|
||||
const form={action,method,target,enctype:'application/x-www-form-urlencoded',querySelectorAll:()=>[user,password]};user.form=form;password.form=form;
|
||||
form.elements=override?[user,password,{getAttribute:name=>override[name]??null}]:[user,password];
|
||||
const window={isSecureContext:true};window.top=frame?{}:window;
|
||||
return {user,password,context:vm.createContext({window,location:{href:url,origin:new URL(url).origin},document:{hasFocus:()=>focused,visibilityState:visibility,querySelectorAll:()=>multiple?[password,new Input('password')]:[password]},getComputedStyle:()=>({display:'block',visibility:'visible',opacity:'1'}),HTMLInputElement:Input,Event:class{},URL})};
|
||||
return {user,password,context:vm.createContext({window,location:{href:url,origin:new URL(url).origin},document:{hasFocus:()=>focused,visibilityState:visibility,querySelectorAll:()=>multiple?[password,new Input('password')]:[password]},getComputedStyle:element=>({display:'block',visibility:'visible',opacity:element._opacity??'1'}),HTMLInputElement:Input,Event:class{},URL})};
|
||||
}
|
||||
test('explicit fill sets exact-origin visible login fields without submitting',()=>{
|
||||
const f=fixture();assert.equal(vm.runInContext(fillScript('https://work.example/login',credential),f.context).completed,true);assert.equal(f.user.stored,credential.username);assert.equal(f.password.stored,credential.password);
|
||||
@@ -28,3 +28,10 @@ test('expired policy cannot inject a password',()=>{assert.throws(()=>fillScript
|
||||
test('queued fill cannot write into a hidden or blurred target document',()=>{
|
||||
for(const options of [{focused:false},{visibility:'hidden'}]){const f=fixture(options);assert.throws(()=>vm.runInContext(fillScript('https://work.example/login',credential),f.context),/foreground/);assert.equal(f.user.stored,undefined);assert.equal(f.password.stored,undefined);}
|
||||
});
|
||||
|
||||
const approved=[{id:'company-login',actionUrl:'https://work.example/signin',usernameField:'username',passwordField:'password'}];
|
||||
test('transparent ancestors and section-prefixed new-password fields cannot receive saved login secrets',()=>{for(const mutate of [f=>f.password.parentElement={_opacity:'0'},f=>f.password.autocomplete='section-login NEW-PASSWORD',f=>f.password.closest=()=>({disabled:true})]){const f=fixture();mutate(f);assert.throws(()=>vm.runInContext(fillScript('https://work.example/login',credential),f.context));assert.equal(f.password.stored,undefined);}});
|
||||
test('controlled fill reports only an approved form ID without submitting or returning secrets',()=>{const f=fixture(),result=vm.runInContext(prepareFillScript('https://work.example/login',credential,approved),f.context);assert.deepEqual(JSON.parse(JSON.stringify(result)),{completed:true,formId:'company-login'});assert.equal(f.password.stored,credential.password);assert.equal(JSON.stringify(result).includes(credential.password),false);});
|
||||
test('controlled fill rejects changed action, encoding, duplicated fields and submit overrides before writing',()=>{
|
||||
for(const mutate of [f=>f.password.form.action='https://work.example/other',f=>f.password.form.enctype='multipart/form-data',f=>f.password.form.elements.push({name:'password'}),f=>f.password.form.elements.push({getAttribute:n=>n==='formaction'?'https://work.example/other':null}),f=>f.password.form.elements.push({getAttribute:n=>n==='formenctype'?'text/plain':null})]){const f=fixture();mutate(f);assert.throws(()=>vm.runInContext(prepareFillScript('https://work.example/login',credential,approved),f.context));assert.equal(f.password.stored,undefined);}
|
||||
});
|
||||
Reference in new issue
Block a user