Harden brainstorm companion auth regressions

This commit is contained in:
Drew Ritter
2026-06-10 14:58:16 -07:00
committed by Drew Ritter
parent fe812c418f
commit a2e67bbd9b
9 changed files with 320 additions and 34 deletions

View File

@@ -35,9 +35,9 @@ async function sleep(ms) {
}
async function fetch(url) {
const authed = url + (url.includes('?') ? '&' : '?') + 'key=' + TOKEN;
return new Promise((resolve, reject) => {
http.get(authed, (res) => {
const headers = { Cookie: `brainstorm-key-${TEST_PORT}=${TOKEN}` };
http.get(url, { headers }, (res) => {
let data = '';
res.on('data', chunk => data += chunk);
res.on('end', () => resolve({
@@ -210,6 +210,28 @@ async function runTests() {
assert.strictEqual(alive.status, 200, 'server must survive a /files/ request');
});
await test('does not serve symlinks that escape content dir via /files/', async () => {
const target = path.join(STATE_DIR, 'server-info');
const link = path.join(CONTENT_DIR, 'linked-server-info.txt');
try { fs.unlinkSync(link); } catch (e) {}
fs.symlinkSync(target, link);
const res = await fetch(`http://localhost:${TEST_PORT}/files/linked-server-info.txt`);
assert.strictEqual(res.status, 404, 'symlink to state/server-info must not be served');
assert(!res.body.includes('server-started'), 'response must not include server-info body');
});
await test('does not serve hard links to files outside content dir via /files/', async () => {
const target = path.join(STATE_DIR, 'server-info');
const link = path.join(CONTENT_DIR, 'hard-linked-server-info.txt');
try { fs.unlinkSync(link); } catch (e) {}
fs.linkSync(target, link);
const res = await fetch(`http://localhost:${TEST_PORT}/files/hard-linked-server-info.txt`);
assert.strictEqual(res.status, 404, 'hard link to state/server-info must not be served');
assert(!res.body.includes('server-started'), 'response must not include server-info body');
});
await test('returns 404 for non-root paths', async () => {
const res = await fetch(`http://localhost:${TEST_PORT}/other`);
assert.strictEqual(res.status, 404);