mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-06-21 14:21:46 +00:00
Backend/frontend hardening & consistency cleanups (#1113)
* refactor(auth): session token validation and password-change consistency * refactor(journey): entry field allow-list and public share-link consistency * refactor(mcp): align tool authorization with the REST permission checks * chore: input validation and sanitisation touch-ups (uploads, pdf, maps, backup, csp)
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import { HttpException } from '@nestjs/common';
|
||||
import type { Response } from 'express';
|
||||
import path from 'node:path';
|
||||
import fs from 'node:fs';
|
||||
|
||||
import { JourneyController } from '../../../src/nest/journey/journey.controller';
|
||||
import { JourneyPublicController } from '../../../src/nest/journey/journey-public.controller';
|
||||
@@ -164,4 +166,27 @@ describe('JourneyPublicController', () => {
|
||||
await new JourneyPublicController(s).legacyPhoto('tok', 'immich', 'a1', '2', 'original', {} as Response);
|
||||
expect(streamImmichAsset).toHaveBeenCalledWith({}, 5, 'a1', 'original', 5);
|
||||
});
|
||||
|
||||
it('legacy photo proxy: local provider cannot escape uploads/journey via a traversal asset id', async () => {
|
||||
// Pretend any path exists so we can inspect exactly what would be served.
|
||||
const existsSpy = vi.spyOn(fs, 'existsSync').mockReturnValue(true);
|
||||
try {
|
||||
const sendFile = vi.fn();
|
||||
const res = { set: vi.fn(), sendFile } as unknown as Response;
|
||||
const s = svc({ validateShareTokenForAsset: vi.fn().mockReturnValue({ ownerId: 5 }) } as Partial<JourneyService>);
|
||||
|
||||
// Express decodes %2F in a single path param to '/', so the handler sees this.
|
||||
await new JourneyPublicController(s).legacyPhoto('tok', 'local', '../../files/secret.pdf', '2', 'original', res);
|
||||
|
||||
expect(sendFile).toHaveBeenCalledTimes(1);
|
||||
const served = sendFile.mock.calls[0][0] as string;
|
||||
// basename() collapses the traversal: the served file stays inside
|
||||
// uploads/journey and never reaches the sibling /uploads/files dir.
|
||||
expect(path.basename(served)).toBe('secret.pdf');
|
||||
expect(served).toMatch(/[\\/]journey[\\/]secret\.pdf$/);
|
||||
expect(served).not.toMatch(/[\\/]files[\\/]/);
|
||||
} finally {
|
||||
existsSpy.mockRestore();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user