Skip to content

Commit f5e3424

Browse files
committed
fix(api): sanitize incoming user session id's
1 parent 491f680 commit f5e3424

File tree

2 files changed

+17
-9
lines changed

2 files changed

+17
-9
lines changed

api/src/unraid-api/auth/cookie.service.spec.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,17 @@ describe.concurrent('CookieService', () => {
4646
it('handles session names robustly', ({ expect }) => {
4747
const session = (name?: unknown) => service.getSessionFilePath(name as string);
4848
expect(session('foo')).toEqual('/tmp/php/sessions/sess_foo');
49+
expect(session('foo123')).toEqual('/tmp/php/sessions/sess_foo123');
50+
expect(session('/foo123*&/^\n\r\'"!;:/../~`+=@#$%(?) \t/~/.profile')).toEqual('/tmp/php/sessions/sess_foo123profile');
4951
expect(session('')).toEqual('/tmp/php/sessions/sess_');
50-
expect(session(null)).toEqual('/tmp/php/sessions/sess_null');
51-
expect(session(undefined)).toEqual('/tmp/php/sessions/sess_undefined');
52-
expect(session(1)).toEqual('/tmp/php/sessions/sess_1');
53-
expect(session(1.0)).toEqual('/tmp/php/sessions/sess_1');
54-
expect(session(1.1)).toEqual('/tmp/php/sessions/sess_1.1');
55-
expect(session({})).toEqual('/tmp/php/sessions/sess_[object Object]');
56-
expect(session(['foo', 'bar'])).toEqual('/tmp/php/sessions/sess_foo,bar');
57-
expect(session('foo/bar')).toEqual('/tmp/php/sessions/sess_foo/bar');
52+
expect(session(null)).toEqual('/tmp/php/sessions/sess_');
53+
expect(session(undefined)).toEqual('/tmp/php/sessions/sess_');
54+
expect(session(1)).toEqual('/tmp/php/sessions/sess_');
55+
expect(session(1.0)).toEqual('/tmp/php/sessions/sess_');
56+
expect(session(1.1)).toEqual('/tmp/php/sessions/sess_');
57+
expect(session({})).toEqual('/tmp/php/sessions/sess_');
58+
expect(session(['foo', 'bar'])).toEqual('/tmp/php/sessions/sess_');
59+
expect(session('foo/bar')).toEqual('/tmp/php/sessions/sess_foobar');
5860
});
5961

6062
it('can read an existing session & reject a non-existent one', async ({ expect }) => {

api/src/unraid-api/auth/cookie.service.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,12 @@ export class CookieService {
8383
* @returns the full path to the session file on disk.
8484
*/
8585
public getSessionFilePath(sessionId: string): string {
86-
return join(this.opts.sessionDir, `sess_${sessionId}`);
86+
if (typeof sessionId !== 'string') {
87+
return join(this.opts.sessionDir, `sess_`);
88+
}
89+
// sanitize incoming session id to prevent e.g. directory traversal attacks
90+
// only allow alpha-numeric characters
91+
const sanitizedSessionId = sessionId.replace(/[^a-zA-Z0-9]/g, '');
92+
return join(this.opts.sessionDir, `sess_${sanitizedSessionId}`);
8793
}
8894
}

0 commit comments

Comments
 (0)