@middy/http-security-headers 6.1.5 → 6.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.ts +56 -56
- package/index.js +257 -255
- package/package.json +71 -74
package/index.d.ts
CHANGED
|
@@ -1,62 +1,62 @@
|
|
|
1
|
-
import middy from
|
|
1
|
+
import type middy from "@middy/core";
|
|
2
2
|
|
|
3
3
|
interface Options {
|
|
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
|
-
|
|
4
|
+
dnsPrefetchControl?: {
|
|
5
|
+
allow?: boolean;
|
|
6
|
+
};
|
|
7
|
+
frameOptions?: {
|
|
8
|
+
action?: string;
|
|
9
|
+
};
|
|
10
|
+
poweredBy?: {
|
|
11
|
+
server: string;
|
|
12
|
+
};
|
|
13
|
+
strictTransportSecurity?: {
|
|
14
|
+
maxAge?: number;
|
|
15
|
+
includeSubDomains?: boolean;
|
|
16
|
+
preload?: boolean;
|
|
17
|
+
};
|
|
18
|
+
downloadOptions?: {
|
|
19
|
+
action?: string;
|
|
20
|
+
};
|
|
21
|
+
contentTypeOptions?: {
|
|
22
|
+
action?: string;
|
|
23
|
+
};
|
|
24
|
+
originAgentCluster?: boolean;
|
|
25
|
+
referrerPolicy?: {
|
|
26
|
+
policy?: string;
|
|
27
|
+
};
|
|
28
|
+
xssProtection?: {
|
|
29
|
+
reportUri?: string;
|
|
30
|
+
};
|
|
31
|
+
contentSecurityPolicy?: Record<string, string>;
|
|
32
|
+
contentSecurityPolicyReportOnly?: boolean;
|
|
33
|
+
crossOriginEmbedderPolicy?: {
|
|
34
|
+
policy?: string;
|
|
35
|
+
};
|
|
36
|
+
crossOriginOpenerPolicy?: {
|
|
37
|
+
policy?: string;
|
|
38
|
+
};
|
|
39
|
+
crossOriginResourcePolicy?: {
|
|
40
|
+
policy?: string;
|
|
41
|
+
};
|
|
42
|
+
permissionsPolicy?: Record<string, string>;
|
|
43
|
+
permittedCrossDomainPolicies?: {
|
|
44
|
+
policy?: string;
|
|
45
|
+
};
|
|
46
|
+
reportTo?: {
|
|
47
|
+
maxAge?: number;
|
|
48
|
+
default?: string;
|
|
49
|
+
includeSubdomains?: boolean;
|
|
50
|
+
csp?: string;
|
|
51
|
+
staple?: string;
|
|
52
|
+
xss?: string;
|
|
53
|
+
};
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
type WithBoolValues<T> = { [K in keyof T]: T[K] | boolean }
|
|
56
|
+
type WithBoolValues<T> = { [K in keyof T]: T[K] | boolean };
|
|
57
57
|
|
|
58
|
-
declare function httpSecurityHeaders
|
|
59
|
-
|
|
60
|
-
): middy.MiddlewareObj
|
|
58
|
+
declare function httpSecurityHeaders(
|
|
59
|
+
options?: WithBoolValues<Options>,
|
|
60
|
+
): middy.MiddlewareObj;
|
|
61
61
|
|
|
62
|
-
export default httpSecurityHeaders
|
|
62
|
+
export default httpSecurityHeaders;
|
package/index.js
CHANGED
|
@@ -1,316 +1,318 @@
|
|
|
1
|
-
import { normalizeHttpResponse } from
|
|
1
|
+
import { normalizeHttpResponse } from "@middy/util";
|
|
2
2
|
|
|
3
3
|
// Code and Defaults heavily based off https://helmetjs.github.io/
|
|
4
4
|
|
|
5
5
|
const defaults = {
|
|
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
|
-
}
|
|
6
|
+
contentSecurityPolicy: {
|
|
7
|
+
// Fetch directives
|
|
8
|
+
// 'child-src': '', // fallback default-src
|
|
9
|
+
// 'connect-src': '', // fallback default-src
|
|
10
|
+
"default-src": "'none'",
|
|
11
|
+
// 'font-src':'', // fallback default-src
|
|
12
|
+
// 'frame-src':'', // fallback child-src > default-src
|
|
13
|
+
// 'img-src':'', // fallback default-src
|
|
14
|
+
// 'manifest-src':'', // fallback default-src
|
|
15
|
+
// 'media-src':'', // fallback default-src
|
|
16
|
+
// 'object-src':'', // fallback default-src
|
|
17
|
+
// 'prefetch-src':'', // fallback default-src
|
|
18
|
+
// 'script-src':'', // fallback default-src
|
|
19
|
+
// 'script-src-elem':'', // fallback script-src > default-src
|
|
20
|
+
// 'script-src-attr':'', // fallback script-src > default-src
|
|
21
|
+
// 'style-src':'', // fallback default-src
|
|
22
|
+
// 'style-src-elem':'', // fallback style-src > default-src
|
|
23
|
+
// 'style-src-attr':'', // fallback style-src > default-src
|
|
24
|
+
// 'worker-src':'', // fallback child-src > script-src > default-src
|
|
25
|
+
// Document directives
|
|
26
|
+
"base-uri": "'none'",
|
|
27
|
+
sandbox: "",
|
|
28
|
+
// Navigation directives
|
|
29
|
+
"form-action": "'none'",
|
|
30
|
+
"frame-ancestors": "'none'",
|
|
31
|
+
"navigate-to": "'none'",
|
|
32
|
+
// Reporting directives
|
|
33
|
+
"report-to": "csp",
|
|
34
|
+
// Other directives
|
|
35
|
+
"require-trusted-types-for": "'script'",
|
|
36
|
+
"trusted-types": "'none'",
|
|
37
|
+
"upgrade-insecure-requests": "",
|
|
38
|
+
},
|
|
39
|
+
contentSecurityPolicyReportOnly: false,
|
|
40
|
+
contentTypeOptions: {
|
|
41
|
+
action: "nosniff",
|
|
42
|
+
},
|
|
43
|
+
crossOriginEmbedderPolicy: {
|
|
44
|
+
policy: "require-corp",
|
|
45
|
+
},
|
|
46
|
+
crossOriginOpenerPolicy: {
|
|
47
|
+
policy: "same-origin",
|
|
48
|
+
},
|
|
49
|
+
crossOriginResourcePolicy: {
|
|
50
|
+
policy: "same-origin",
|
|
51
|
+
},
|
|
52
|
+
dnsPrefetchControl: {
|
|
53
|
+
allow: false,
|
|
54
|
+
},
|
|
55
|
+
downloadOptions: {
|
|
56
|
+
action: "noopen",
|
|
57
|
+
},
|
|
58
|
+
frameOptions: {
|
|
59
|
+
action: "deny",
|
|
60
|
+
},
|
|
61
|
+
originAgentCluster: {},
|
|
62
|
+
permissionsPolicy: {
|
|
63
|
+
// Standard
|
|
64
|
+
accelerometer: "",
|
|
65
|
+
"ambient-light-sensor": "",
|
|
66
|
+
autoplay: "",
|
|
67
|
+
battery: "",
|
|
68
|
+
camera: "",
|
|
69
|
+
"cross-origin-isolated": "",
|
|
70
|
+
"display-capture": "",
|
|
71
|
+
"document-domain": "",
|
|
72
|
+
"encrypted-media": "",
|
|
73
|
+
"execution-while-not-rendered": "",
|
|
74
|
+
"execution-while-out-of-viewport": "",
|
|
75
|
+
fullscreen: "",
|
|
76
|
+
geolocation: "",
|
|
77
|
+
gyroscope: "",
|
|
78
|
+
"keyboard-map": "",
|
|
79
|
+
magnetometer: "",
|
|
80
|
+
microphone: "",
|
|
81
|
+
midi: "",
|
|
82
|
+
"navigation-override": "",
|
|
83
|
+
payment: "",
|
|
84
|
+
"picture-in-picture": "",
|
|
85
|
+
"publickey-credentials-get": "",
|
|
86
|
+
"screen-wake-lock": "",
|
|
87
|
+
"sync-xhr": "",
|
|
88
|
+
usb: "",
|
|
89
|
+
"web-share": "",
|
|
90
|
+
"xr-spatial-tracking": "",
|
|
91
|
+
// Proposed
|
|
92
|
+
"clipboard-read": "",
|
|
93
|
+
"clipboard-write": "",
|
|
94
|
+
gamepad: "",
|
|
95
|
+
"speaker-selection": "",
|
|
96
|
+
// Experimental
|
|
97
|
+
"conversion-measurement": "",
|
|
98
|
+
"focus-without-user-activation": "",
|
|
99
|
+
hid: "",
|
|
100
|
+
"idle-detection": "",
|
|
101
|
+
"interest-cohort": "",
|
|
102
|
+
serial: "",
|
|
103
|
+
"sync-script": "",
|
|
104
|
+
"trust-token-redemption": "",
|
|
105
|
+
"window-placement": "",
|
|
106
|
+
"vertical-scroll": "",
|
|
107
|
+
},
|
|
108
|
+
permittedCrossDomainPolicies: {
|
|
109
|
+
policy: "none", // none, master-only, by-content-type, by-ftp-filename, all
|
|
110
|
+
},
|
|
111
|
+
poweredBy: {
|
|
112
|
+
server: "",
|
|
113
|
+
},
|
|
114
|
+
referrerPolicy: {
|
|
115
|
+
policy: "no-referrer",
|
|
116
|
+
},
|
|
117
|
+
reportingEndpoints: {},
|
|
118
|
+
reportTo: {
|
|
119
|
+
maxAge: 365 * 24 * 60 * 60,
|
|
120
|
+
// default: '',
|
|
121
|
+
includeSubdomains: true,
|
|
122
|
+
// csp: '',
|
|
123
|
+
// permissions: '',
|
|
124
|
+
// staple: '',
|
|
125
|
+
// xss: ''
|
|
126
|
+
},
|
|
127
|
+
strictTransportSecurity: {
|
|
128
|
+
maxAge: 180 * 24 * 60 * 60,
|
|
129
|
+
includeSubDomains: true,
|
|
130
|
+
preload: true,
|
|
131
|
+
},
|
|
132
|
+
xssProtection: {
|
|
133
|
+
reportTo: "xss",
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
136
|
|
|
137
|
-
const helmet = {}
|
|
138
|
-
const helmetHtmlOnly = {}
|
|
137
|
+
const helmet = {};
|
|
138
|
+
const helmetHtmlOnly = {};
|
|
139
139
|
|
|
140
140
|
// *** https://github.com/helmetjs/helmet/tree/main/middlewares *** //
|
|
141
141
|
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy
|
|
142
142
|
helmetHtmlOnly.contentSecurityPolicy = (reportOnly) => (headers, config) => {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
143
|
+
let header = Object.keys(config)
|
|
144
|
+
.map((policy) => (config[policy] ? `${policy} ${config[policy]}` : ""))
|
|
145
|
+
.filter((str) => str)
|
|
146
|
+
.join("; ");
|
|
147
|
+
if (config.sandbox === "") {
|
|
148
|
+
header += "; sandbox";
|
|
149
|
+
}
|
|
150
|
+
if (config["upgrade-insecure-requests"] === "") {
|
|
151
|
+
header += "; upgrade-insecure-requests";
|
|
152
|
+
}
|
|
153
153
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
}
|
|
154
|
+
const cspHeaderName = reportOnly
|
|
155
|
+
? "Content-Security-Policy-Report-Only"
|
|
156
|
+
: "Content-Security-Policy";
|
|
157
|
+
headers[cspHeaderName] = header;
|
|
158
|
+
};
|
|
159
159
|
// crossdomain - N/A - for Adobe products
|
|
160
160
|
helmetHtmlOnly.crossOriginEmbedderPolicy = (headers, config) => {
|
|
161
|
-
|
|
162
|
-
}
|
|
161
|
+
headers["Cross-Origin-Embedder-Policy"] = config.policy;
|
|
162
|
+
};
|
|
163
163
|
helmetHtmlOnly.crossOriginOpenerPolicy = (headers, config) => {
|
|
164
|
-
|
|
165
|
-
}
|
|
164
|
+
headers["Cross-Origin-Opener-Policy"] = config.policy;
|
|
165
|
+
};
|
|
166
166
|
helmetHtmlOnly.crossOriginResourcePolicy = (headers, config) => {
|
|
167
|
-
|
|
168
|
-
}
|
|
167
|
+
headers["Cross-Origin-Resource-Policy"] = config.policy;
|
|
168
|
+
};
|
|
169
169
|
|
|
170
170
|
// DEPRECATED: expectCt
|
|
171
171
|
// DEPRECATED: hpkp
|
|
172
172
|
|
|
173
173
|
// https://www.permissionspolicy.com/
|
|
174
174
|
helmetHtmlOnly.permissionsPolicy = (headers, config) => {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
}
|
|
175
|
+
headers["Permissions-Policy"] = Object.keys(config)
|
|
176
|
+
.map(
|
|
177
|
+
(policy) =>
|
|
178
|
+
`${policy}=${config[policy] === "*" ? "*" : `(${config[policy]})`}`,
|
|
179
|
+
)
|
|
180
|
+
.join(", ");
|
|
181
|
+
};
|
|
182
182
|
|
|
183
183
|
helmet.originAgentCluster = (headers, config) => {
|
|
184
|
-
|
|
185
|
-
}
|
|
184
|
+
headers["Origin-Agent-Cluster"] = "?1";
|
|
185
|
+
};
|
|
186
186
|
|
|
187
187
|
// https://github.com/helmetjs/referrer-policy
|
|
188
188
|
helmet.referrerPolicy = (headers, config) => {
|
|
189
|
-
|
|
190
|
-
}
|
|
189
|
+
headers["Referrer-Policy"] = config.policy;
|
|
190
|
+
};
|
|
191
191
|
|
|
192
192
|
// DEPRECATED by reportingEndpoints
|
|
193
193
|
helmetHtmlOnly.reportTo = (headers, config) => {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
194
|
+
headers["Report-To"] = "";
|
|
195
|
+
const keys = Object.keys(config);
|
|
196
|
+
headers["Report-To"] = keys
|
|
197
|
+
.map((group) => {
|
|
198
|
+
if (group === "includeSubdomains" || group === "maxAge") return "";
|
|
199
|
+
const includeSubdomains =
|
|
200
|
+
group === "default"
|
|
201
|
+
? `, "include_subdomains": ${config.includeSubdomains}`
|
|
202
|
+
: "";
|
|
203
|
+
return config[group] && group !== "includeSubdomains"
|
|
204
|
+
? `{ "group": "default", "max_age": ${config.maxAge}, "endpoints": [ { "url": "${config[group]}" } ]${includeSubdomains} }`
|
|
205
|
+
: "";
|
|
206
|
+
})
|
|
207
|
+
.filter((str) => str)
|
|
208
|
+
.join(", ");
|
|
209
|
+
};
|
|
208
210
|
|
|
209
211
|
helmet.reportingEndpoints = (headers, config) => {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
}
|
|
212
|
+
headers["Reporting-Endpoints"] = "";
|
|
213
|
+
const keys = Object.keys(config);
|
|
214
|
+
for (let i = 0, l = keys.length; i < l; i++) {
|
|
215
|
+
if (i) headers["Reporting-Endpoints"] += ", ";
|
|
216
|
+
const key = keys[i];
|
|
217
|
+
headers["Reporting-Endpoints"] += `${key}="${config[key]}"`;
|
|
218
|
+
}
|
|
219
|
+
};
|
|
218
220
|
|
|
219
221
|
// https://github.com/helmetjs/hsts
|
|
220
222
|
helmet.strictTransportSecurity = (headers, config) => {
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
}
|
|
223
|
+
let header = `max-age=${Math.round(config.maxAge)}`;
|
|
224
|
+
if (config.includeSubDomains) {
|
|
225
|
+
header += "; includeSubDomains";
|
|
226
|
+
}
|
|
227
|
+
if (config.preload) {
|
|
228
|
+
header += "; preload";
|
|
229
|
+
}
|
|
230
|
+
headers["Strict-Transport-Security"] = header;
|
|
231
|
+
};
|
|
230
232
|
|
|
231
233
|
// noCache - N/A - separate middleware
|
|
232
234
|
|
|
233
235
|
// X-* //
|
|
234
236
|
// https://github.com/helmetjs/dont-sniff-mimetype
|
|
235
237
|
helmet.contentTypeOptions = (headers, config) => {
|
|
236
|
-
|
|
237
|
-
}
|
|
238
|
+
headers["X-Content-Type-Options"] = config.action;
|
|
239
|
+
};
|
|
238
240
|
|
|
239
241
|
// https://github.com/helmetjs/dns-Prefetch-control
|
|
240
242
|
helmet.dnsPrefetchControl = (headers, config) => {
|
|
241
|
-
|
|
242
|
-
}
|
|
243
|
+
headers["X-DNS-Prefetch-Control"] = config.allow ? "on" : "off";
|
|
244
|
+
};
|
|
243
245
|
|
|
244
246
|
// https://github.com/helmetjs/ienoopen
|
|
245
247
|
helmet.downloadOptions = (headers, config) => {
|
|
246
|
-
|
|
247
|
-
}
|
|
248
|
+
headers["X-Download-Options"] = config.action;
|
|
249
|
+
};
|
|
248
250
|
|
|
249
251
|
// https://github.com/helmetjs/frameOptions
|
|
250
252
|
helmetHtmlOnly.frameOptions = (headers, config) => {
|
|
251
|
-
|
|
252
|
-
}
|
|
253
|
+
headers["X-Frame-Options"] = config.action.toUpperCase();
|
|
254
|
+
};
|
|
253
255
|
|
|
254
256
|
// https://github.com/helmetjs/crossdomain
|
|
255
257
|
helmet.permittedCrossDomainPolicies = (headers, config) => {
|
|
256
|
-
|
|
257
|
-
}
|
|
258
|
+
headers["X-Permitted-Cross-Domain-Policies"] = config.policy;
|
|
259
|
+
};
|
|
258
260
|
|
|
259
261
|
// https://github.com/helmetjs/hide-powered-by
|
|
260
262
|
helmet.poweredBy = (headers, config) => {
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
}
|
|
263
|
+
if (config.server) {
|
|
264
|
+
headers["X-Powered-By"] = config.server;
|
|
265
|
+
} else {
|
|
266
|
+
headers.Server = undefined;
|
|
267
|
+
headers["X-Powered-By"] = undefined;
|
|
268
|
+
}
|
|
269
|
+
};
|
|
268
270
|
|
|
269
271
|
// https://github.com/helmetjs/x-xss-protection
|
|
270
272
|
helmetHtmlOnly.xssProtection = (headers, config) => {
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
}
|
|
273
|
+
let header = "1; mode=block";
|
|
274
|
+
if (config.reportTo) {
|
|
275
|
+
header += `; report=${config.reportTo}`;
|
|
276
|
+
}
|
|
277
|
+
headers["X-XSS-Protection"] = header;
|
|
278
|
+
};
|
|
277
279
|
|
|
278
280
|
const httpSecurityHeadersMiddleware = (opts = {}) => {
|
|
279
|
-
|
|
281
|
+
const options = { ...defaults, ...opts };
|
|
280
282
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
+
const httpSecurityHeadersMiddlewareAfter = async (request) => {
|
|
284
|
+
normalizeHttpResponse(request);
|
|
283
285
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
}
|
|
316
|
-
export default httpSecurityHeadersMiddleware
|
|
286
|
+
for (const key of Object.keys(helmet)) {
|
|
287
|
+
if (!options[key]) continue;
|
|
288
|
+
const config = { ...defaults[key], ...options[key] };
|
|
289
|
+
helmet[key](request.response.headers, config);
|
|
290
|
+
}
|
|
291
|
+
const contentTypeHeader =
|
|
292
|
+
request.response.headers["Content-Type"] ??
|
|
293
|
+
request.response.headers["content-type"];
|
|
294
|
+
if (contentTypeHeader?.includes("text/html")) {
|
|
295
|
+
for (const key of Object.keys(helmetHtmlOnly)) {
|
|
296
|
+
if (!options[key]) continue;
|
|
297
|
+
const config = { ...defaults[key], ...options[key] };
|
|
298
|
+
if (key === "contentSecurityPolicy") {
|
|
299
|
+
helmetHtmlOnly[key](options.contentSecurityPolicyReportOnly)(
|
|
300
|
+
request.response.headers,
|
|
301
|
+
config,
|
|
302
|
+
);
|
|
303
|
+
} else {
|
|
304
|
+
helmetHtmlOnly[key](request.response.headers, config);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
};
|
|
309
|
+
const httpSecurityHeadersMiddlewareOnError = async (request) => {
|
|
310
|
+
if (request.response === undefined) return;
|
|
311
|
+
await httpSecurityHeadersMiddlewareAfter(request);
|
|
312
|
+
};
|
|
313
|
+
return {
|
|
314
|
+
after: httpSecurityHeadersMiddlewareAfter,
|
|
315
|
+
onError: httpSecurityHeadersMiddlewareOnError,
|
|
316
|
+
};
|
|
317
|
+
};
|
|
318
|
+
export default httpSecurityHeadersMiddleware;
|
package/package.json
CHANGED
|
@@ -1,76 +1,73 @@
|
|
|
1
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
|
-
"devDependencies": {
|
|
74
|
-
"@middy/core": "6.1.5"
|
|
75
|
-
}
|
|
2
|
+
"name": "@middy/http-security-headers",
|
|
3
|
+
"version": "6.2.0",
|
|
4
|
+
"description": "Applies best practice security headers to responses. It's a simplified port of HelmetJS",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": ">=20"
|
|
8
|
+
},
|
|
9
|
+
"engineStrict": true,
|
|
10
|
+
"publishConfig": {
|
|
11
|
+
"access": "public"
|
|
12
|
+
},
|
|
13
|
+
"module": "./index.js",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"import": {
|
|
17
|
+
"types": "./index.d.ts",
|
|
18
|
+
"default": "./index.js"
|
|
19
|
+
},
|
|
20
|
+
"require": {
|
|
21
|
+
"default": "./index.js"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"types": "index.d.ts",
|
|
26
|
+
"files": ["index.js", "index.d.ts"],
|
|
27
|
+
"scripts": {
|
|
28
|
+
"test": "npm run test:unit && npm run test:fuzz",
|
|
29
|
+
"test:unit": "node --test",
|
|
30
|
+
"test:fuzz": "node --test index.fuzz.js",
|
|
31
|
+
"test:perf": "node --test index.perf.js"
|
|
32
|
+
},
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"keywords": [
|
|
35
|
+
"Lambda",
|
|
36
|
+
"Middleware",
|
|
37
|
+
"Serverless",
|
|
38
|
+
"Framework",
|
|
39
|
+
"AWS",
|
|
40
|
+
"AWS Lambda",
|
|
41
|
+
"Middy",
|
|
42
|
+
"HTTP",
|
|
43
|
+
"API",
|
|
44
|
+
"Header",
|
|
45
|
+
"Headers",
|
|
46
|
+
"Helmet",
|
|
47
|
+
"Security"
|
|
48
|
+
],
|
|
49
|
+
"author": {
|
|
50
|
+
"name": "Middy contributors",
|
|
51
|
+
"url": "https://github.com/middyjs/middy/graphs/contributors"
|
|
52
|
+
},
|
|
53
|
+
"repository": {
|
|
54
|
+
"type": "git",
|
|
55
|
+
"url": "git+https://github.com/middyjs/middy.git",
|
|
56
|
+
"directory": "packages/http-security-headers"
|
|
57
|
+
},
|
|
58
|
+
"bugs": {
|
|
59
|
+
"url": "https://github.com/middyjs/middy/issues"
|
|
60
|
+
},
|
|
61
|
+
"homepage": "https://middy.js.org",
|
|
62
|
+
"funding": {
|
|
63
|
+
"type": "github",
|
|
64
|
+
"url": "https://github.com/sponsors/willfarrell"
|
|
65
|
+
},
|
|
66
|
+
"gitHead": "7a6c0fbb8ab71d6a2171e678697de9f237568431",
|
|
67
|
+
"dependencies": {
|
|
68
|
+
"@middy/util": "6.2.0"
|
|
69
|
+
},
|
|
70
|
+
"devDependencies": {
|
|
71
|
+
"@middy/core": "6.2.0"
|
|
72
|
+
}
|
|
76
73
|
}
|