fix: 공개 API와 토너먼트의 사용자·장수 권한 경계를 강화한다

This commit is contained in:
2026-10-10 01:56:31 +09:00
parent 5771701007
commit 4e668b9fb6
31 changed files with 889 additions and 238 deletions
+51
View File
@@ -0,0 +1,51 @@
import { describe, expect, it } from 'vitest';
import { createApiOriginGuard, resolveApiAllowedOrigins } from '../src/http/apiOrigin.js';
describe('public API origin policy', () => {
it('derives exact origins from application URLs and explicit extra origins', async () => {
const origins = resolveApiAllowedOrigins('http://localhost:5173,https://sam.hided.net', [
'https://sam.hided.net/gateway/',
'https://sam.hided.net/che/',
]);
expect(origins).toEqual(['https://sam.hided.net', 'http://localhost:5173']);
const guard = createApiOriginGuard(origins);
await expect(guard({ headers: {} })).resolves.toBeUndefined();
for (const origin of origins) await expect(guard({ headers: { origin } })).resolves.toBeUndefined();
for (const origin of [
'https://untrusted.example',
'https://sam.hided.net.untrusted.example',
'http://sam.hided.net',
'https://sam.hided.net:8443',
'null',
'',
'https://sam.hided.net,https://untrusted.example',
'x'.repeat(2049),
['https://sam.hided.net', 'https://untrusted.example'],
]) {
await expect(guard({ headers: { origin } })).rejects.toMatchObject({ statusCode: 403 });
}
});
it.each([
'*',
'null',
'https://user:password@example.com',
'file:///tmp/example',
'https://x.test/path',
'https://x.test?query',
'https://x.test#fragment',
'https://x.test,',
])('rejects unsafe configuration %s', (value) => {
expect(() => resolveApiAllowedOrigins(value, [])).toThrow();
});
it('bounds configuration and fails closed when no public origin is configured', async () => {
expect(() =>
resolveApiAllowedOrigins(Array.from({ length: 33 }, (_, i) => `https://${i}.test`).join(','), [])
).toThrow();
expect(() => resolveApiAllowedOrigins('https://' + 'a'.repeat(2048) + '.test', [])).toThrow();
await expect(
createApiOriginGuard([])({ headers: { origin: 'https://untrusted.example' } })
).rejects.toMatchObject({ statusCode: 403 });
});
});