Files
safetynet/tests/request-transfer-facts.test.mjs
T

53 lines
3.5 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import {readFileSync} from 'node:fs';
import facts from '../packages/core/request-transfer-facts.cjs';
import transfers from '../packages/core/file-transfer.cjs';
for(const [name,body] of [
['form password',Buffer.from('username=alice&password=short-secret')],
['JSON token',Buffer.from('{"token":"short-secret"}')],
['binary credential envelope',Buffer.concat([Buffer.from('89504e470d0a1a0a','hex'),Buffer.from('password=short-secret')])],
['multipart secret',Buffer.from('--boundary\r\nContent-Disposition: form-data; name="password"\r\n\r\nshort-secret\r\n--boundary--')]
])test(`request audit excludes reversible fingerprint for ${name}`,()=>{
const transfer=transfers.inspectFileTransfer(body,{},'upload');
const result=facts.requestFactsForTransfer(transfer);
assert.deepEqual(Object.keys(result).sort(),['bytes','detectedType']);
assert.equal(result.bytes,body.length);
assert.equal(JSON.stringify(result).includes(transfer.sha256),false);
assert.equal(JSON.stringify(result).includes('short-secret'),false);
assert.throws(()=>facts.requestTransferFacts({...result,sha256:transfer.sha256}));
});
test('request facts reject arbitrary content, unknown types and invalid sizes',()=>{
for(const value of [{bytes:-1,detectedType:'text'},{bytes:1,detectedType:'password'},{bytes:1,detectedType:'text',content:'secret'}])assert.throws(()=>facts.requestTransferFacts(value));
});
test('privileged request gate routes upload audit through request facts without modifying file inspection',()=>{
const source=readFileSync(new URL('../apps/browser/main.cjs',import.meta.url),'utf8');
assert.match(source,/requestFactsForTransfer\(transfer\)/);
assert.match(source,/audit\('upload\.authorized',null,new URL\(details\.url\)\.hostname,undefined,requestFacts\)/);
assert.match(source,/audit\('upload\.block',transfer\.ruleId,new URL\(details\.url\)\.hostname,undefined,requestFacts\)/);
// Supplementary wiring check; actual receiver fixtures verify that ordinary
// secrets and confidential residual fields still cannot leave the browser.
assert.match(source,/scanBytes=claim\?claim\.residual:requestBytes/);
assert.match(source,/core\.inspect\(scanBytes,policy\)/);
assert.equal(source.includes('sha256:transfer.sha256'),false);
});
test('offline legacy upload queue is scrubbed before replay without changing delivery identity or downloads',()=>{
const download={eventId:'download-id',kind:'download.released',file:{bytes:9,detectedType:'text',sha256:'b'.repeat(64)}};
const legacy={eventId:'upload-id',kind:'upload.authorized',host:'example.test',policyVersion:7,file:{bytes:9,detectedType:'text',sha256:'a'.repeat(64)}};
const migrated=facts.migrateQueuedRequestFacts([legacy,download]);
assert.deepEqual(migrated[0],{eventId:'upload-id',kind:'upload.authorized',host:'example.test',policyVersion:7,request:{bytes:9,detectedType:'text'}});
assert.equal(migrated[1],download);
assert.equal(legacy.file.sha256,'a'.repeat(64));
assert.deepEqual(facts.migrateQueuedRequestFacts(migrated),migrated);
const invalid=facts.migrateQueuedRequestFacts([{kind:'upload.block',eventId:'blocked-id',file:{bytes:-1,detectedType:'secret',sha256:'secret'}}]);
assert.deepEqual(invalid,[{kind:'upload.block',eventId:'blocked-id'}]);
assert.throws(()=>facts.migrateQueuedRequestFacts({}));
const source=readFileSync(new URL('../apps/browser/main.cjs',import.meta.url),'utf8');
assert.match(source,/migrateQueuedRequestFacts\(JSON.parse\(safeStorage.decryptString\(fs.readFileSync\(queuePath\)\)\)\);persistAudit\(\)/);
});