-
Notifications
You must be signed in to change notification settings - Fork 934
Expand file tree
/
Copy pathopenURLMiddleware.test.ts
More file actions
145 lines (107 loc) · 4.55 KB
/
openURLMiddleware.test.ts
File metadata and controls
145 lines (107 loc) · 4.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
import http from 'http';
import open from 'open';
import {openURLMiddleware} from '../openURLMiddleware';
jest.mock('open');
describe('openURLMiddleware', () => {
let req: http.IncomingMessage & {body?: Object};
let res: jest.Mocked<http.ServerResponse>;
let next: jest.Mock;
beforeEach(() => {
req = {
method: 'POST',
body: {},
} as any;
res = {
writeHead: jest.fn(),
end: jest.fn(),
} as any;
next = jest.fn();
jest.clearAllMocks();
});
afterEach(() => {
jest.restoreAllMocks();
});
it('should sanitize URL with pipe character to prevent RCE', async () => {
const maliciousUrl = 'https://example.com/|rm -rf /';
req.body = {url: maliciousUrl};
await openURLMiddleware(req, res, next);
// Verify that open was called with a sanitized URL
expect(open).toHaveBeenCalledTimes(1);
const sanitizedUrl = (open as jest.Mock).mock.calls[0][0];
// The sanitized URL should not contain the raw pipe character that could execute shell commands
// The pipe character should be encoded (as %7C) to prevent shell command execution
expect(sanitizedUrl).not.toContain('|rm -rf /');
expect(sanitizedUrl).not.toContain('|');
// Verify the pipe character is URL-encoded (as %7C) instead of raw
expect(sanitizedUrl).toContain('%7C');
expect(sanitizedUrl).toMatch(/^https:\/\/example\.com/);
expect(res.writeHead).toHaveBeenCalledWith(200);
expect(res.end).toHaveBeenCalled();
});
it('should sanitize URL with pipe character in query string', async () => {
const maliciousUrl = 'https://example.com/path?param=value|rm -rf /';
req.body = {url: maliciousUrl};
await openURLMiddleware(req, res, next);
expect(open).toHaveBeenCalledTimes(1);
const sanitizedUrl = (open as jest.Mock).mock.calls[0][0];
// The pipe character in query string should be properly encoded (as %7C)
expect(sanitizedUrl).not.toContain('|rm -rf /');
expect(sanitizedUrl).not.toContain('|');
expect(sanitizedUrl).toContain('%7C');
expect(sanitizedUrl).toMatch(/^https:\/\/example\.com/);
expect(res.writeHead).toHaveBeenCalledWith(200);
expect(res.end).toHaveBeenCalled();
});
it('should sanitize URL with pipe character in path', async () => {
const maliciousUrl = 'https://example.com/path|rm -rf /';
req.body = {url: maliciousUrl};
await openURLMiddleware(req, res, next);
expect(open).toHaveBeenCalledTimes(1);
const sanitizedUrl = (open as jest.Mock).mock.calls[0][0];
// The pipe character in path should be properly encoded (as %7C)
expect(sanitizedUrl).not.toContain('|rm -rf /');
expect(sanitizedUrl).not.toContain('|');
expect(sanitizedUrl).toContain('%7C');
expect(sanitizedUrl).toMatch(/^https:\/\/example\.com/);
expect(res.writeHead).toHaveBeenCalledWith(200);
expect(res.end).toHaveBeenCalled();
});
it('should handle normal URLs without pipe characters', async () => {
const normalUrl = 'https://example.com/path?param=value';
req.body = {url: normalUrl};
await openURLMiddleware(req, res, next);
expect(open).toHaveBeenCalledTimes(1);
const sanitizedUrl = (open as jest.Mock).mock.calls[0][0];
expect(sanitizedUrl).toBe('https://example.com/path?param=value');
expect(res.writeHead).toHaveBeenCalledWith(200);
expect(res.end).toHaveBeenCalled();
});
it('should return 400 for missing request body', async () => {
req.body = undefined;
await openURLMiddleware(req, res, next);
expect(open).not.toHaveBeenCalled();
expect(res.writeHead).toHaveBeenCalledWith(400);
expect(res.end).toHaveBeenCalledWith('Missing request body');
});
it('should return 400 for non-string URL', async () => {
req.body = {url: 123};
await openURLMiddleware(req, res, next);
expect(open).not.toHaveBeenCalled();
expect(res.writeHead).toHaveBeenCalledWith(400);
expect(res.end).toHaveBeenCalledWith('URL must be a string');
});
it('should return 400 for invalid URL format', async () => {
req.body = {url: 'not-a-valid-url'};
await openURLMiddleware(req, res, next);
expect(open).not.toHaveBeenCalled();
expect(res.writeHead).toHaveBeenCalledWith(400);
expect(res.end).toHaveBeenCalledWith('Invalid URL format');
});
it('should return 400 for invalid URL protocol', async () => {
req.body = {url: 'file:///etc/passwd'};
await openURLMiddleware(req, res, next);
expect(open).not.toHaveBeenCalled();
expect(res.writeHead).toHaveBeenCalledWith(400);
expect(res.end).toHaveBeenCalledWith('Invalid URL protocol');
});
});