@middy/http-security-headers 3.0.0-alpha.3 → 3.0.0-alpha.4
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.js +91 -128
- package/package.json +4 -4
package/index.js
CHANGED
|
@@ -1,37 +1,13 @@
|
|
|
1
|
-
import { normalizeHttpResponse } from '@middy/util'
|
|
2
|
-
|
|
3
|
-
// Code and Defaults heavily based off https://helmetjs.github.io/
|
|
4
|
-
|
|
1
|
+
import { normalizeHttpResponse } from '@middy/util';
|
|
5
2
|
const defaults = {
|
|
6
3
|
contentSecurityPolicy: {
|
|
7
|
-
// Fetch directives
|
|
8
|
-
// 'child-src': '', // fallback default-src
|
|
9
|
-
// 'connect-src': '', // fallback default-src
|
|
10
4
|
'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
5
|
'base-uri': "'none'",
|
|
27
6
|
sandbox: '',
|
|
28
|
-
// Navigation directives
|
|
29
7
|
'form-action': "'none'",
|
|
30
8
|
'frame-ancestors': "'none'",
|
|
31
9
|
'navigate-to': "'none'",
|
|
32
|
-
// Reporting directives
|
|
33
10
|
'report-to': 'csp',
|
|
34
|
-
// Other directives
|
|
35
11
|
'require-trusted-types-for': "'script'",
|
|
36
12
|
'trusted-types': "'none'",
|
|
37
13
|
'upgrade-insecure-requests': ''
|
|
@@ -59,7 +35,6 @@ const defaults = {
|
|
|
59
35
|
},
|
|
60
36
|
originAgentCluster: {},
|
|
61
37
|
permissionsPolicy: {
|
|
62
|
-
// Standard
|
|
63
38
|
accelerometer: '',
|
|
64
39
|
'ambient-light-sensor': '',
|
|
65
40
|
autoplay: '',
|
|
@@ -87,12 +62,10 @@ const defaults = {
|
|
|
87
62
|
usb: '',
|
|
88
63
|
'web-share': '',
|
|
89
64
|
'xr-spatial-tracking': '',
|
|
90
|
-
// Proposed
|
|
91
65
|
'clipboard-read': '',
|
|
92
66
|
'clipboard-write': '',
|
|
93
67
|
gamepad: '',
|
|
94
68
|
'speaker-selection': '',
|
|
95
|
-
// Experimental
|
|
96
69
|
'conversion-measurement': '',
|
|
97
70
|
'focus-without-user-activation': '',
|
|
98
71
|
hid: '',
|
|
@@ -105,7 +78,7 @@ const defaults = {
|
|
|
105
78
|
'vertical-scroll': ''
|
|
106
79
|
},
|
|
107
80
|
permittedCrossDomainPolicies: {
|
|
108
|
-
policy: 'none'
|
|
81
|
+
policy: 'none'
|
|
109
82
|
},
|
|
110
83
|
poweredBy: {
|
|
111
84
|
server: ''
|
|
@@ -129,152 +102,142 @@ const defaults = {
|
|
|
129
102
|
xssProtection: {
|
|
130
103
|
reportTo: 'xss'
|
|
131
104
|
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
const
|
|
135
|
-
const helmetHtmlOnly = {}
|
|
105
|
+
};
|
|
106
|
+
const helmet = {};
|
|
107
|
+
const helmetHtmlOnly = {};
|
|
136
108
|
|
|
137
|
-
// *** https://github.com/helmetjs/helmet/tree/main/middlewares *** //
|
|
138
|
-
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy
|
|
139
109
|
helmetHtmlOnly.contentSecurityPolicy = (headers, config) => {
|
|
140
|
-
let header = Object.keys(config)
|
|
141
|
-
|
|
142
|
-
.filter(str => str)
|
|
143
|
-
.join('; ')
|
|
110
|
+
let header = Object.keys(config).map(policy => config[policy] ? `${policy} ${config[policy]}` : '').filter(str => str).join('; ');
|
|
111
|
+
|
|
144
112
|
if (config.sandbox === '') {
|
|
145
|
-
header += '; sandbox'
|
|
113
|
+
header += '; sandbox';
|
|
146
114
|
}
|
|
115
|
+
|
|
147
116
|
if (config['upgrade-insecure-requests'] === '') {
|
|
148
|
-
header += '; upgrade-insecure-requests'
|
|
117
|
+
header += '; upgrade-insecure-requests';
|
|
149
118
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
119
|
+
|
|
120
|
+
headers['Content-Security-Policy'] = header;
|
|
121
|
+
};
|
|
122
|
+
|
|
153
123
|
helmetHtmlOnly.crossOriginEmbedderPolicy = (headers, config) => {
|
|
154
|
-
headers['Cross-Origin-Embedder-Policy'] = config.policy
|
|
155
|
-
}
|
|
124
|
+
headers['Cross-Origin-Embedder-Policy'] = config.policy;
|
|
125
|
+
};
|
|
126
|
+
|
|
156
127
|
helmetHtmlOnly.crossOriginOpenerPolicy = (headers, config) => {
|
|
157
|
-
headers['Cross-Origin-Opener-Policy'] = config.policy
|
|
158
|
-
}
|
|
159
|
-
helmetHtmlOnly.crossOriginResourcePolicy = (headers, config) => {
|
|
160
|
-
headers['Cross-Origin-Resource-Policy'] = config.policy
|
|
161
|
-
}
|
|
128
|
+
headers['Cross-Origin-Opener-Policy'] = config.policy;
|
|
129
|
+
};
|
|
162
130
|
|
|
163
|
-
|
|
164
|
-
|
|
131
|
+
helmetHtmlOnly.crossOriginResourcePolicy = (headers, config) => {
|
|
132
|
+
headers['Cross-Origin-Resource-Policy'] = config.policy;
|
|
133
|
+
};
|
|
165
134
|
|
|
166
|
-
// https://www.permissionspolicy.com/
|
|
167
135
|
helmetHtmlOnly.permissionsPolicy = (headers, config) => {
|
|
168
|
-
headers['Permissions-Policy'] = Object.keys(config)
|
|
169
|
-
|
|
170
|
-
.join(', ')
|
|
171
|
-
}
|
|
136
|
+
headers['Permissions-Policy'] = Object.keys(config).map(policy => `${policy}=${policy === '*' ? '*' : `(${config[policy]})`}`).join(', ');
|
|
137
|
+
};
|
|
172
138
|
|
|
173
139
|
helmet.originAgentCluster = (headers, config) => {
|
|
174
|
-
headers['Origin-Agent-Cluster'] = '?1'
|
|
175
|
-
}
|
|
140
|
+
headers['Origin-Agent-Cluster'] = '?1';
|
|
141
|
+
};
|
|
176
142
|
|
|
177
|
-
// https://github.com/helmetjs/referrer-policy
|
|
178
143
|
helmet.referrerPolicy = (headers, config) => {
|
|
179
|
-
headers['Referrer-Policy'] = config.policy
|
|
180
|
-
}
|
|
144
|
+
headers['Referrer-Policy'] = config.policy;
|
|
145
|
+
};
|
|
181
146
|
|
|
182
147
|
helmetHtmlOnly.reportTo = (headers, config) => {
|
|
183
|
-
headers['Report-To'] = Object.keys(config)
|
|
184
|
-
|
|
185
|
-
.filter(str => str)
|
|
186
|
-
.join(', ')
|
|
187
|
-
}
|
|
148
|
+
headers['Report-To'] = Object.keys(config).map(group => config[group] && group !== 'includeSubdomains' ? `{ "group": "default", "max_age": ${config.maxAge}, "endpoints": [ { "url": "${config[group]}" } ]${group === 'default' ? `, "include_subdomains": ${config.includeSubdomains}` : ''} }` : '').filter(str => str).join(', ');
|
|
149
|
+
};
|
|
188
150
|
|
|
189
|
-
// https://github.com/helmetjs/hsts
|
|
190
151
|
helmet.strictTransportSecurity = (headers, config) => {
|
|
191
|
-
let header = 'max-age=' + Math.round(config.maxAge)
|
|
152
|
+
let header = 'max-age=' + Math.round(config.maxAge);
|
|
153
|
+
|
|
192
154
|
if (config.includeSubDomains) {
|
|
193
|
-
header += '; includeSubDomains'
|
|
155
|
+
header += '; includeSubDomains';
|
|
194
156
|
}
|
|
157
|
+
|
|
195
158
|
if (config.preload) {
|
|
196
|
-
header += '; preload'
|
|
159
|
+
header += '; preload';
|
|
197
160
|
}
|
|
198
|
-
headers['Strict-Transport-Security'] = header
|
|
199
|
-
}
|
|
200
161
|
|
|
201
|
-
|
|
162
|
+
headers['Strict-Transport-Security'] = header;
|
|
163
|
+
};
|
|
202
164
|
|
|
203
|
-
// X-* //
|
|
204
|
-
// https://github.com/helmetjs/dont-sniff-mimetype
|
|
205
165
|
helmet.contentTypeOptions = (headers, config) => {
|
|
206
|
-
headers['X-Content-Type-Options'] = config.action
|
|
207
|
-
}
|
|
166
|
+
headers['X-Content-Type-Options'] = config.action;
|
|
167
|
+
};
|
|
208
168
|
|
|
209
|
-
// https://github.com/helmetjs/dns-Prefetch-control
|
|
210
169
|
helmet.dnsPrefetchControl = (headers, config) => {
|
|
211
|
-
headers['X-DNS-Prefetch-Control'] = config.allow ? 'on' : 'off'
|
|
212
|
-
}
|
|
170
|
+
headers['X-DNS-Prefetch-Control'] = config.allow ? 'on' : 'off';
|
|
171
|
+
};
|
|
213
172
|
|
|
214
|
-
// https://github.com/helmetjs/ienoopen
|
|
215
173
|
helmet.downloadOptions = (headers, config) => {
|
|
216
|
-
headers['X-Download-Options'] = config.action
|
|
217
|
-
}
|
|
174
|
+
headers['X-Download-Options'] = config.action;
|
|
175
|
+
};
|
|
218
176
|
|
|
219
|
-
// https://github.com/helmetjs/frameOptions
|
|
220
177
|
helmetHtmlOnly.frameOptions = (headers, config) => {
|
|
221
|
-
headers['X-Frame-Options'] = config.action.toUpperCase()
|
|
222
|
-
}
|
|
178
|
+
headers['X-Frame-Options'] = config.action.toUpperCase();
|
|
179
|
+
};
|
|
223
180
|
|
|
224
|
-
// https://github.com/helmetjs/crossdomain
|
|
225
181
|
helmet.permittedCrossDomainPolicies = (headers, config) => {
|
|
226
|
-
headers['X-Permitted-Cross-Domain-Policies'] = config.policy
|
|
227
|
-
}
|
|
182
|
+
headers['X-Permitted-Cross-Domain-Policies'] = config.policy;
|
|
183
|
+
};
|
|
228
184
|
|
|
229
|
-
// https://github.com/helmetjs/hide-powered-by
|
|
230
185
|
helmet.poweredBy = (headers, config) => {
|
|
231
186
|
if (config.server) {
|
|
232
|
-
headers['X-Powered-By'] = config.server
|
|
187
|
+
headers['X-Powered-By'] = config.server;
|
|
233
188
|
} else {
|
|
234
|
-
delete headers.Server
|
|
235
|
-
delete headers['X-Powered-By']
|
|
189
|
+
delete headers.Server;
|
|
190
|
+
delete headers['X-Powered-By'];
|
|
236
191
|
}
|
|
237
|
-
}
|
|
192
|
+
};
|
|
238
193
|
|
|
239
|
-
// https://github.com/helmetjs/x-xss-protection
|
|
240
194
|
helmetHtmlOnly.xssProtection = (headers, config) => {
|
|
241
|
-
let header = '1; mode=block'
|
|
195
|
+
let header = '1; mode=block';
|
|
196
|
+
|
|
242
197
|
if (config.reportTo) {
|
|
243
|
-
header += '; report=' + config.reportTo
|
|
198
|
+
header += '; report=' + config.reportTo;
|
|
244
199
|
}
|
|
245
|
-
headers['X-XSS-Protection'] = header
|
|
246
|
-
}
|
|
247
200
|
|
|
248
|
-
|
|
249
|
-
|
|
201
|
+
headers['X-XSS-Protection'] = header;
|
|
202
|
+
};
|
|
250
203
|
|
|
251
|
-
|
|
252
|
-
|
|
204
|
+
const httpSecurityHeadersMiddleware = (opts = {}) => {
|
|
205
|
+
const options = { ...defaults,
|
|
206
|
+
...opts
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
const httpSecurityHeadersMiddlewareAfter = async request => {
|
|
210
|
+
var _request$response$hea;
|
|
211
|
+
|
|
212
|
+
normalizeHttpResponse(request);
|
|
213
|
+
Object.keys(helmet).forEach(key => {
|
|
214
|
+
if (!options[key]) return;
|
|
215
|
+
const config = { ...defaults[key],
|
|
216
|
+
...options[key]
|
|
217
|
+
};
|
|
218
|
+
helmet[key](request.response.headers, config);
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
if ((_request$response$hea = request.response.headers['Content-Type']) !== null && _request$response$hea !== void 0 && _request$response$hea.includes('text/html')) {
|
|
222
|
+
Object.keys(helmetHtmlOnly).forEach(key => {
|
|
223
|
+
if (!options[key]) return;
|
|
224
|
+
const config = { ...defaults[key],
|
|
225
|
+
...options[key]
|
|
226
|
+
};
|
|
227
|
+
helmetHtmlOnly[key](request.response.headers, config);
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
};
|
|
253
231
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
})
|
|
232
|
+
const httpSecurityHeadersMiddlewareOnError = async request => {
|
|
233
|
+
if (request.response === undefined) return;
|
|
234
|
+
return httpSecurityHeadersMiddlewareAfter(request);
|
|
235
|
+
};
|
|
259
236
|
|
|
260
|
-
if (request.response.headers['Content-Type']?.includes('text/html')) {
|
|
261
|
-
Object.keys(helmetHtmlOnly).forEach((key) => {
|
|
262
|
-
if (!options[key]) return
|
|
263
|
-
const config = { ...defaults[key], ...options[key] }
|
|
264
|
-
helmetHtmlOnly[key](
|
|
265
|
-
request.response.headers,
|
|
266
|
-
config
|
|
267
|
-
)
|
|
268
|
-
})
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
const httpSecurityHeadersMiddlewareOnError = async (request) => {
|
|
272
|
-
if (request.response === undefined) return
|
|
273
|
-
return httpSecurityHeadersMiddlewareAfter(request)
|
|
274
|
-
}
|
|
275
237
|
return {
|
|
276
238
|
after: httpSecurityHeadersMiddlewareAfter,
|
|
277
239
|
onError: httpSecurityHeadersMiddlewareOnError
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
|
|
240
|
+
};
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
export default httpSecurityHeadersMiddleware;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@middy/http-security-headers",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.4",
|
|
4
4
|
"description": "Applies best practice security headers to responses. It's a simplified port of HelmetJS",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -50,11 +50,11 @@
|
|
|
50
50
|
"url": "https://github.com/middyjs/middy/issues"
|
|
51
51
|
},
|
|
52
52
|
"homepage": "https://github.com/middyjs/middy#readme",
|
|
53
|
-
"gitHead": "
|
|
53
|
+
"gitHead": "d4bea7f4e21f6a9bbb1f6f6908361169598b9e53",
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@middy/util": "^3.0.0-alpha.
|
|
55
|
+
"@middy/util": "^3.0.0-alpha.4"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
|
-
"@middy/core": "^3.0.0-alpha.
|
|
58
|
+
"@middy/core": "^3.0.0-alpha.4"
|
|
59
59
|
}
|
|
60
60
|
}
|