71 lines
2.2 KiB
JavaScript
71 lines
2.2 KiB
JavaScript
'use strict';
|
|
|
|
const { test } = require('node:test');
|
|
const assert = require('node:assert');
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const os = require('os');
|
|
|
|
const Store = require('../../lib/store');
|
|
|
|
const SAMPLE_UUID = '00000000-0000-4000-8000-000000000001';
|
|
|
|
test('getFilename rejects prefix false-positive (startsWith bypass)', () => {
|
|
const jailParent = fs.mkdtempSync(path.join(os.tmpdir(), 'psi-jail-'));
|
|
try {
|
|
const base = path.join(jailParent, 'conf');
|
|
fs.mkdirSync(base, { recursive: true });
|
|
fs.writeFileSync(path.join(jailParent, 'config.production.js'), 'x');
|
|
const store = new Store(base);
|
|
assert.throws(() => store.getFilename('..++config.production.js'), /jail/);
|
|
} finally {
|
|
fs.rmSync(jailParent, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test('getFilename rejects traversal via multiple ++ segments', () => {
|
|
const base = fs.mkdtempSync(path.join(os.tmpdir(), 'psi-store-'));
|
|
try {
|
|
const store = new Store(base);
|
|
assert.throws(() => store.getFilename('legit++..++..++outside'), /jail/);
|
|
} finally {
|
|
fs.rmSync(base, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test('getFilename rejects NUL in fid', () => {
|
|
const base = fs.mkdtempSync(path.join(os.tmpdir(), 'psi-store-'));
|
|
try {
|
|
const store = new Store(base);
|
|
assert.throws(
|
|
() => store.getFilename(`legit++${SAMPLE_UUID}\0/../../../etc/passwd`),
|
|
/jail/
|
|
);
|
|
} finally {
|
|
fs.rmSync(base, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test('getFilename rejects resolved path equal to jail root (rel empty)', () => {
|
|
const base = fs.mkdtempSync(path.join(os.tmpdir(), 'psi-store-'));
|
|
try {
|
|
const store = new Store(base);
|
|
assert.throws(() => store.getFilename('bucket++..'), /jail/);
|
|
} finally {
|
|
fs.rmSync(base, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test('getFilename accepts valid sid++uuid path under jail', () => {
|
|
const base = fs.mkdtempSync(path.join(os.tmpdir(), 'psi-store-'));
|
|
try {
|
|
const store = new Store(base);
|
|
const fid = `mybucket++${SAMPLE_UUID}`;
|
|
const got = store.getFilename(fid);
|
|
const expected = path.join(base, 'mybucket', SAMPLE_UUID);
|
|
assert.strictEqual(got, expected);
|
|
} finally {
|
|
fs.rmSync(base, { recursive: true, force: true });
|
|
}
|
|
});
|