Files
qinglong/test/back/file-access-security.test.cjs
T

48 lines
1.6 KiB
JavaScript

const assert = require('node:assert/strict');
const test = require('node:test');
const fs = require('node:fs');
const os = require('node:os');
const path = require('node:path');
const load = require('../helpers/load-security-module.cjs');
const { resolveFileAccess } = load(
path.join(__dirname, '../../back/shared/fileAccess.ts'),
);
test('file access enforces directory boundaries, blacklist descendants and symlinks', (t) => {
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'ql-file-security-'));
t.after(() => fs.rmSync(tmp, { recursive: true, force: true }));
const root = path.join(tmp, 'config');
fs.mkdirSync(path.join(root, 'grpc'), { recursive: true });
fs.mkdirSync(path.join(tmp, 'config-other'));
fs.writeFileSync(path.join(root, 'normal.txt'), 'normal');
fs.writeFileSync(path.join(root, 'grpc', 'client.key'), 'test-only');
fs.symlinkSync(path.join(tmp, 'config-other'), path.join(root, 'outside'));
fs.symlinkSync(path.join(root, 'grpc'), path.join(root, 'alias'));
fs.symlinkSync(path.join(root, 'normal.txt'), path.join(root, 'safe-link'));
fs.symlinkSync(path.join(tmp, 'missing'), path.join(root, 'dangling'));
for (const input of [
'../config-other/secret',
'/etc/passwd',
'grpc/client.key',
'alias/client.key',
'outside/new.txt',
'dangling',
'auth.json',
'nested/auth.json',
'',
]) {
assert.equal(
resolveFileAccess(root, [input], ['grpc', 'auth.json']),
'',
input,
);
}
for (const input of ['normal.txt', 'safe-link', 'new-dir/new.txt']) {
assert.equal(
resolveFileAccess(root, [input], ['grpc']),
path.join(root, input),
input,
);
}
});