-
Notifications
You must be signed in to change notification settings - Fork 57
Expand file tree
/
Copy pathrequest-filters.js
More file actions
89 lines (74 loc) · 2.16 KB
/
request-filters.js
File metadata and controls
89 lines (74 loc) · 2.16 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
import net from 'net';
import { isPrivateIp } from './utils/network-utils.js';
import config from './config.js';
export const localIpFilter = (_req, headersData) => {
const hostname = headersData.targetApiServer.hostname || '';
const allowPrivateIps =
config.features?.ALLOW_PRIVATE_IPS?.isEnabled ?? false;
if (allowPrivateIps) {
return;
}
if (hostname.endsWith('.cluster.local')) {
throw Error('Local IP addresses are not allowed.');
}
if (net.isIP(hostname)) {
if (isPrivateIp(hostname)) {
throw Error('Local IP addresses are not allowed.');
}
}
};
export const pathWhitelistFilter = (req) => {
const path = req.originalUrl.replace(/^\/backend/, '');
// list comes from "/" call to API server
const whitelist = [
'/.well-known',
'/api',
'/apis',
'/healthz',
'/livez',
'/logs',
'/metrics',
'/openapi',
'/openid',
'/readyz',
'/version',
];
if (!whitelist.some((e) => path.startsWith(e))) {
throw Error(`Path ${path} is not whitelisted.`);
}
};
export const pathInvalidCharacterFilter = (req) => {
const encodedPath = req.originalUrl;
let decodedPath;
try {
decodedPath = decodeURIComponent(encodedPath);
} catch (err) {
throw Error('Path contains invalid encoding', { cause: err });
}
// Check if the decoded path still contains encoded characters (i.e., '%' symbol)
if (decodedPath.includes('%')) {
throw Error('Decoded path contains illegal % characters');
}
// Check if the decoded path contains any non-printable or control characters
// eslint-disable-next-line no-control-regex
const controlCharRegex = /[\x00-\x1F\x7F]/;
if (controlCharRegex.test(decodedPath) || decodedPath.includes('..')) {
throw Error('Path contains invalid characters');
}
};
export const invalidRequestMethodFilter = (req) => {
const path = req.originalUrl;
const method = req.method;
if (
method === 'TRACE' ||
(['OPTIONS', 'HEAD'].includes(method) && !path.includes('proxy'))
) {
throw Error(`Invalid request method`);
}
};
export const filters = [
invalidRequestMethodFilter,
localIpFilter,
pathWhitelistFilter,
pathInvalidCharacterFilter,
];