DodoTransfer/tests/unit/store-containment.test.js
2026-11-05 10:28:10 +09:00

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 });
}
});