fix: harden authentication and file access security

This commit is contained in:
whyour
2026-09-05 18:19:01 +08:00
parent be2580d0e8
commit 4df52094f2
26 changed files with 1165 additions and 99 deletions
+74
View File
@@ -0,0 +1,74 @@
const assert = require('node:assert/strict');
const test = require('node:test');
const path = require('node:path');
const jwt = require('jsonwebtoken');
const load = require('../helpers/load-security-module.cjs');
const { isValidToken } = load(
path.join(__dirname, '../../back/shared/auth.ts'),
);
const { hashPassword, verifyPassword } = load(
path.join(__dirname, '../../back/shared/password.ts'),
);
const secret = 'security-test-secret';
const token = (payload = {}, options = {}) =>
jwt.sign(payload, secret, {
algorithm: 'HS384',
expiresIn: '1h',
...options,
});
const info = (value) => ({ token: value, tokens: {} });
test('valid legacy and platform sessions retain compatibility', () => {
const value = token();
for (const auth of [
info(value),
{ tokens: { desktop: value } },
{ tokens: { desktop: [{ value }] } },
]) {
assert.equal(isValidToken(auth, value, 'desktop', secret), true);
}
assert.equal(
isValidToken({ tokens: { mobile: value } }, value, 'desktop', secret),
false,
);
});
test('session membership never bypasses JWT signature, expiry, algorithm or nbf', () => {
const values = [
token({}, { expiresIn: -1 }),
token({}, { algorithm: 'HS256' }),
token({ nbf: Math.floor(Date.now() / 1000) + 60 }),
jwt.sign({}, 'wrong-secret', { algorithm: 'HS384', expiresIn: '1h' }),
jwt.sign({}, secret, { algorithm: 'HS384' }),
'not-a-token',
];
for (const value of values)
assert.equal(isValidToken(info(value), value, 'desktop', secret), false);
assert.equal(isValidToken({ tokens: {} }, token(), 'desktop', secret), false);
assert.equal(isValidToken(null, token(), 'desktop', secret), false);
assert.equal(isValidToken(info(''), '', 'desktop', secret), false);
});
test('platform token metadata can shorten but cannot extend JWT expiration', () => {
const value = token();
assert.equal(
isValidToken(
{ tokens: { desktop: [{ value, expiration: 1 }] } },
value,
'desktop',
secret,
),
false,
);
});
test('passwords are salted and legacy plaintext can migrate without changing the password', async () => {
const first = await hashPassword('owner-password');
const second = await hashPassword('owner-password');
assert.notEqual(first, second);
assert.equal(await verifyPassword('owner-password', first), true);
assert.equal(await verifyPassword('wrong-password', first), false);
assert.equal(await verifyPassword(first, first), false);
assert.equal(await verifyPassword('old-password', 'old-password'), true);
assert.equal(await verifyPassword('wrong', 'old-password'), false);
});