Files
stack/packages/webui/tests/tester-socket.test.mjs
jason.woltje 7247d80c7a row 196: human boundary on peer credentials, interpreter receipt and the Console tester socket (#1694)
Candidate 527b9a1e6 (gander/row196-r6-prd19, base f48725cfc), the 39 manifest paths of CANDIDATE.sha256 537d30aef70b6cd1 at ec1e7fad8. Duckworth approved round 1 outside B1/B2 (rev 2973, comment 30145) and round 2 merge-scoped (rev 2986, comment 30156). Gate gander-0066 on grant sage-2145: 2334 pass, 0 fail, 1 skip; mutants 38/38 killed. BUILD-LOG lines and Duckworth's C1 DEFERRED entry follow as a doc-only append.
2026-10-21 15:55:39 -05:00

49 lines
3.1 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import { mkdtempSync,lstatSync,readdirSync,chmodSync,symlinkSync,mkdirSync,rmSync } from 'node:fs';
import { join } from 'node:path';
import { tmpdir } from 'node:os';
import { startTesterSocket, testerSocketPath } from '../src/tester-socket.mjs';
import { testerRequest } from '../../cli/src/tester-http.mjs';
async function refused(options, pattern) {
const result=await startTesterSocket(options).catch(e=>e);
if(!(result instanceof Error)) await new Promise(r=>result.close(r));
assert.ok(result instanceof Error,'unsafe tester bind must refuse');assert.match(result.message,pattern);
}
test('private tester HTTP serves on 0600 socket in 0700 parent and fixed origin',async t=>{
const root=mkdtempSync(join(tmpdir(),'g196-w-'));t.after(()=>rmSync(root,{recursive:true,force:true}));
const web=await startTesterSocket({dataRoot:root,board:'http://127.0.0.1:9'});t.after(()=>new Promise(r=>web.close(r)));
assert.equal(web.address(),testerSocketPath(root));
assert.equal(lstatSync(join(root,'console')).mode&0o777,0o700);
assert.equal(lstatSync(web.address()).mode&0o777,0o600);
assert.equal((await testerRequest({dataRoot:root,path:'/healthz'})).status,200);
for(const headers of [{host:'elsewhere.invalid'},{authorization:'Bearer fixture'},{cookie:'__Host-mosaic_session=fixture'},{origin:'http://elsewhere.invalid'}])
assert.equal((await testerRequest({dataRoot:root,path:'/api/config',headers})).status,403);
assert.equal((await testerRequest({dataRoot:root,path:'/auth/login'})).status,404);
assert.equal((await testerRequest({dataRoot:root,path:'/api/settings',method:'POST',body:{}})).status,403);
await refused({dataRoot:root},/tester-socket-exists/);
});
test('private tester refuses symlink, unsafe parent and long path without repairs',async t=>{
const root=mkdtempSync(join(tmpdir(),'g196-w-'));t.after(()=>rmSync(root,{recursive:true,force:true}));
mkdirSync(join(root,'console'),{mode:0o755});
await refused({dataRoot:root},/tester-socket-unsafe/);
chmodSync(join(root,'console'),0o700);rmSync(join(root,'console'),{recursive:true});
symlinkSync(root,join(root,'console'));
await refused({dataRoot:root},/tester-socket-unsafe/);
await refused({dataRoot:'/tmp/'+ 'a'.repeat(108)},/tester-socket-path/);
});
test('tester cleanup must leave a replacement inode untouched',async t=>{
const { createServer }=await import('node:http');
const { writeFileSync,existsSync }=await import('node:fs');
const { bindTesterSocket }=await import('../src/tester-socket.mjs');
const root=mkdtempSync(join(tmpdir(),'g196-clean-'));t.after(()=>rmSync(root,{recursive:true,force:true}));
const path=testerSocketPath(root);
const server=await bindTesterSocket(createServer(),path);
assert.deepEqual(readdirSync(join(root,'console')),['tester.sock'],'temporary name is absent after bind');
rmSync(path);writeFileSync(path,'replacement',{mode:0o600});
await new Promise(r=>server.close(r));
assert.equal(existsSync(path),true,'closing the listener must not unlink a replacement inode');
assert.deepEqual(readdirSync(join(root,'console')),['tester.sock'],'temporary name is absent after close');
});