43 lines
2.2 KiB
JavaScript
43 lines
2.2 KiB
JavaScript
'use strict';
|
|
const test = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
const fs = require('fs');
|
|
const os = require('os');
|
|
const path = require('path');
|
|
const { SecretsStore } = require('../../src/security/secrets-store');
|
|
const { hashPassword, verifyPassword } = require('../../src/security/passwords');
|
|
const { mountedRoots, resolveAllowedPath } = require('../../src/platform/data-paths');
|
|
const { redact } = require('../../src/platform/logger');
|
|
|
|
test('secrets are encrypted at rest and passwords use scrypt', async () => {
|
|
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'porkfolio-security-'));
|
|
const store = new SecretsStore({ filePath: path.join(root, 'secrets.json'), keyFile: path.join(root, 'master.key') });
|
|
store.set('ftp.password', 'top-secret-value');
|
|
assert.equal(store.get('ftp.password'), 'top-secret-value');
|
|
assert.equal(fs.readFileSync(path.join(root, 'secrets.json'), 'utf8').includes('top-secret-value'), false);
|
|
const encoded = await hashPassword('een-lang-wachtwoord');
|
|
assert.equal(await verifyPassword('een-lang-wachtwoord', encoded), true);
|
|
assert.equal(await verifyPassword('verkeerd-wachtwoord', encoded), false);
|
|
});
|
|
|
|
test('path allowlist rejects traversal and redaction removes sensitive values', () => {
|
|
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'porkfolio-path-'));
|
|
const inside = path.join(root, 'export', 'file.bin');
|
|
assert.equal(resolveAllowedPath(inside, [root]), inside);
|
|
assert.throws(() => resolveAllowedPath(path.join(root, '..', 'outside.txt'), [root]), /buiten/);
|
|
assert.deepEqual(redact({ user: 'jens', password: 'secret', nested: { token: 'abc' } }), { user: 'jens', password: '[REDACTED]', nested: { token: '[REDACTED]' } });
|
|
});
|
|
|
|
test('mounted server roots use the same absolute representation as the allowlist', () => {
|
|
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'chimera-mounted-roots-'));
|
|
const existsSync = fs.existsSync;
|
|
fs.existsSync = value => String(value) === '/downloads' || existsSync(value);
|
|
try {
|
|
const roots = mountedRoots(root);
|
|
assert.ok(roots.includes(path.resolve('/downloads')));
|
|
assert.ok(roots.every(value => path.isAbsolute(value)));
|
|
} finally {
|
|
fs.existsSync = existsSync;
|
|
}
|
|
});
|