helmet-core 1.0.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.mjs ADDED
@@ -0,0 +1,586 @@
1
+ const dashify = str => str.replace(/[A-Z]/g, capitalLetter => "-" + capitalLetter.toLowerCase())
2
+ const errify = err => (err instanceof Error ? err : new Error(String(err)))
3
+ const isString = value => typeof value === "string"
4
+ const throwErrorIfExists = err => {
5
+ if (err) throw err
6
+ }
7
+
8
+ const dangerouslyDisableDefaultSrc = Symbol("dangerouslyDisableDefaultSrc")
9
+ const SHOULD_BE_QUOTED = new Set(["none", "self", "strict-dynamic", "report-sample", "inline-speculation-rules", "unsafe-inline", "unsafe-eval", "unsafe-hashes", "wasm-unsafe-eval"])
10
+ const getDefaultDirectives = () => ({
11
+ "default-src": ["'self'"],
12
+ "base-uri": ["'self'"],
13
+ "font-src": ["'self'", "https:", "data:"],
14
+ "form-action": ["'self'"],
15
+ "frame-ancestors": ["'self'"],
16
+ "img-src": ["'self'", "data:"],
17
+ "object-src": ["'none'"],
18
+ "script-src": ["'self'"],
19
+ "script-src-attr": ["'none'"],
20
+ "style-src": ["'self'", "https:", "'unsafe-inline'"],
21
+ "upgrade-insecure-requests": []
22
+ })
23
+ const parseDirectiveName = rawDirectiveName => {
24
+ if (rawDirectiveName.length === 0 || !/^[a-z](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?$/.test(rawDirectiveName)) {
25
+ throw new Error(`Content-Security-Policy received an invalid directive name ${JSON.stringify(rawDirectiveName)}`)
26
+ }
27
+ return dashify(rawDirectiveName)
28
+ }
29
+ const getDirectiveValueValidationError = (directiveName, directiveValue) => (/;|,/.test(directiveValue) ? new Error(`Content-Security-Policy received an invalid directive value for ${JSON.stringify(directiveName)}`) : null)
30
+ const getDirectiveValueEntryValidationError = (directiveName, directiveValueEntry) => (SHOULD_BE_QUOTED.has(directiveValueEntry) || directiveValueEntry.startsWith("nonce-") || directiveValueEntry.startsWith("sha256-") || directiveValueEntry.startsWith("sha384-") || directiveValueEntry.startsWith("sha512-") ? new Error(`Content-Security-Policy received an invalid directive value for ${JSON.stringify(directiveName)}. ${JSON.stringify(directiveValueEntry)} should be quoted`) : null)
31
+ const stringifyDirectiveValue = directiveValue => {
32
+ if (Array.isArray(directiveValue)) {
33
+ return directiveValue.every(isString) ? directiveValue.join(" ") : null
34
+ }
35
+ if (directiveValue instanceof Set) {
36
+ return stringifyDirectiveValue(Array.from(directiveValue))
37
+ }
38
+ return null
39
+ }
40
+ const parseDirectives = ({useDefaults = true, directives: rawDirectives = {}}) => {
41
+ const result = new Map(useDefaults ? Object.entries(getDefaultDirectives()) : [])
42
+ let hasDisabledDefaultSrc = false
43
+ const directiveNamesSeen = new Set()
44
+ for (const rawDirectiveName in rawDirectives) {
45
+ if (!Object.hasOwn(rawDirectives, rawDirectiveName)) {
46
+ continue
47
+ }
48
+ const directiveName = parseDirectiveName(rawDirectiveName)
49
+ if (directiveNamesSeen.has(directiveName)) {
50
+ throw new Error(`Content-Security-Policy received a duplicate directive ${JSON.stringify(directiveName)}`)
51
+ }
52
+ directiveNamesSeen.add(directiveName)
53
+ const rawDirectiveValue = rawDirectives[rawDirectiveName]
54
+ let directiveValue
55
+ if (rawDirectiveValue === null) {
56
+ if (directiveName === "default-src") {
57
+ throw new Error("Content-Security-Policy needs a default-src but it was set to `null`. If you really want to disable it, set it to `contentSecurityPolicy.dangerouslyDisableDefaultSrc`.")
58
+ }
59
+ result.delete(directiveName)
60
+ continue
61
+ } else if (typeof rawDirectiveValue === "string") {
62
+ directiveValue = [rawDirectiveValue]
63
+ } else if (rawDirectiveValue === dangerouslyDisableDefaultSrc) {
64
+ if (directiveName === "default-src") {
65
+ hasDisabledDefaultSrc = true
66
+ result.delete(directiveName)
67
+ continue
68
+ } else {
69
+ throw new Error(`Content-Security-Policy: tried to disable ${JSON.stringify(directiveName)} as if it were default-src; simply omit the key`)
70
+ }
71
+ } else if (rawDirectiveValue) {
72
+ directiveValue = rawDirectiveValue
73
+ } else {
74
+ throw new Error(`Content-Security-Policy received an invalid directive value for ${JSON.stringify(directiveName)}`)
75
+ }
76
+ for (const element of directiveValue) {
77
+ if (typeof element !== "string") continue
78
+ throwErrorIfExists(getDirectiveValueValidationError(directiveName, element) ?? getDirectiveValueEntryValidationError(directiveName, element))
79
+ }
80
+ result.set(directiveName, directiveValue)
81
+ }
82
+ if (!result.size) {
83
+ throw new Error("Content-Security-Policy has no directives. Either set some or disable the header")
84
+ }
85
+ if (!result.has("default-src") && !hasDisabledDefaultSrc) {
86
+ throw new Error("Content-Security-Policy needs a default-src but none was provided. If you really want to disable it, set it to `contentSecurityPolicy.dangerouslyDisableDefaultSrc`.")
87
+ }
88
+ let stringResult = ""
89
+ let shouldUseStringResult = true
90
+ for (const [directiveName, directiveValue] of result) {
91
+ const directiveValueString = stringifyDirectiveValue(directiveValue)
92
+ if (directiveValueString === null) {
93
+ shouldUseStringResult = false
94
+ break
95
+ } else {
96
+ if (stringResult) stringResult += ";"
97
+ stringResult += directiveValueString ? `${directiveName} ${directiveValueString}` : directiveName
98
+ }
99
+ }
100
+ return shouldUseStringResult ? stringResult : result
101
+ }
102
+ function getHeaderValue(req, res, normalizedDirectives) {
103
+ const result = []
104
+ for (const [directiveName, rawDirectiveValue] of normalizedDirectives) {
105
+ let directiveValue = ""
106
+ for (const element of rawDirectiveValue) {
107
+ if (typeof element === "function") {
108
+ let newElement
109
+ try {
110
+ newElement = element(req, res)
111
+ } catch (err) {
112
+ return errify(err)
113
+ }
114
+ const err = getDirectiveValueEntryValidationError(directiveName, newElement)
115
+ if (err) return err
116
+ directiveValue += " " + newElement
117
+ } else {
118
+ directiveValue += " " + element
119
+ }
120
+ }
121
+ if (directiveValue) {
122
+ const err = getDirectiveValueValidationError(directiveName, directiveValue)
123
+ if (err) return err
124
+ result.push(`${directiveName}${directiveValue}`)
125
+ } else {
126
+ result.push(directiveName)
127
+ }
128
+ }
129
+ return result.join(";")
130
+ }
131
+ const contentSecurityPolicy = function contentSecurityPolicy(options = {}) {
132
+ const headerName = options.reportOnly ? "Content-Security-Policy-Report-Only" : "Content-Security-Policy"
133
+ const parsedDirectives = parseDirectives(options)
134
+ // A special case for performance.
135
+ if (typeof parsedDirectives === "string") {
136
+ return function contentSecurityPolicyMiddleware(_req, res, next) {
137
+ res.setHeader(headerName, parsedDirectives)
138
+ next()
139
+ }
140
+ }
141
+ return function contentSecurityPolicyMiddleware(req, res, next) {
142
+ const result = getHeaderValue(req, res, parsedDirectives)
143
+ if (result instanceof Error) {
144
+ next(result)
145
+ } else {
146
+ res.setHeader(headerName, result)
147
+ next()
148
+ }
149
+ }
150
+ }
151
+ contentSecurityPolicy.getDefaultDirectives = getDefaultDirectives
152
+ contentSecurityPolicy.dangerouslyDisableDefaultSrc = dangerouslyDisableDefaultSrc
153
+
154
+ const ALLOWED_POLICIES$2 = new Set(["require-corp", "credentialless", "unsafe-none"])
155
+ function getHeaderValueFromOptions$6({policy = "require-corp"}) {
156
+ if (ALLOWED_POLICIES$2.has(policy)) {
157
+ return policy
158
+ } else {
159
+ throw new Error(`Cross-Origin-Embedder-Policy does not support the ${JSON.stringify(policy)} policy`)
160
+ }
161
+ }
162
+ function crossOriginEmbedderPolicy(options = {}) {
163
+ const headerValue = getHeaderValueFromOptions$6(options)
164
+ return function crossOriginEmbedderPolicyMiddleware(_req, res, next) {
165
+ res.setHeader("Cross-Origin-Embedder-Policy", headerValue)
166
+ next()
167
+ }
168
+ }
169
+
170
+ const ALLOWED_POLICIES$1 = new Set(["same-origin", "same-origin-allow-popups", "noopener-allow-popups", "unsafe-none"])
171
+ function getHeaderValueFromOptions$5({policy = "same-origin"}) {
172
+ if (ALLOWED_POLICIES$1.has(policy)) {
173
+ return policy
174
+ } else {
175
+ throw new Error(`Cross-Origin-Opener-Policy does not support the ${JSON.stringify(policy)} policy`)
176
+ }
177
+ }
178
+ function crossOriginOpenerPolicy(options = {}) {
179
+ const headerValue = getHeaderValueFromOptions$5(options)
180
+ return function crossOriginOpenerPolicyMiddleware(_req, res, next) {
181
+ res.setHeader("Cross-Origin-Opener-Policy", headerValue)
182
+ next()
183
+ }
184
+ }
185
+
186
+ const ALLOWED_POLICIES = new Set(["same-origin", "same-site", "cross-origin"])
187
+ function getHeaderValueFromOptions$4({policy = "same-origin"}) {
188
+ if (ALLOWED_POLICIES.has(policy)) {
189
+ return policy
190
+ } else {
191
+ throw new Error(`Cross-Origin-Resource-Policy does not support the ${JSON.stringify(policy)} policy`)
192
+ }
193
+ }
194
+ function crossOriginResourcePolicy(options = {}) {
195
+ const headerValue = getHeaderValueFromOptions$4(options)
196
+ return function crossOriginResourcePolicyMiddleware(_req, res, next) {
197
+ res.setHeader("Cross-Origin-Resource-Policy", headerValue)
198
+ next()
199
+ }
200
+ }
201
+
202
+ function originAgentCluster() {
203
+ return function originAgentClusterMiddleware(_req, res, next) {
204
+ res.setHeader("Origin-Agent-Cluster", "?1")
205
+ next()
206
+ }
207
+ }
208
+
209
+ const ALLOWED_TOKENS = new Set(["no-referrer", "no-referrer-when-downgrade", "same-origin", "origin", "strict-origin", "origin-when-cross-origin", "strict-origin-when-cross-origin", "unsafe-url", ""])
210
+ function getHeaderValueFromOptions$3({policy = ["no-referrer"]}) {
211
+ const tokens = typeof policy === "string" ? [policy] : policy
212
+ if (tokens.length === 0) {
213
+ throw new Error("Referrer-Policy received no policy tokens")
214
+ }
215
+ const tokensSeen = new Set()
216
+ tokens.forEach(token => {
217
+ if (!ALLOWED_TOKENS.has(token)) {
218
+ throw new Error(`Referrer-Policy received an unexpected policy token ${JSON.stringify(token)}`)
219
+ } else if (tokensSeen.has(token)) {
220
+ throw new Error(`Referrer-Policy received a duplicate policy token ${JSON.stringify(token)}`)
221
+ }
222
+ tokensSeen.add(token)
223
+ })
224
+ return tokens.join(",")
225
+ }
226
+ function referrerPolicy(options = {}) {
227
+ const headerValue = getHeaderValueFromOptions$3(options)
228
+ return function referrerPolicyMiddleware(_req, res, next) {
229
+ res.setHeader("Referrer-Policy", headerValue)
230
+ next()
231
+ }
232
+ }
233
+
234
+ const DEFAULT_MAX_AGE = 365 * 24 * 60 * 60
235
+ function parseMaxAge(value = DEFAULT_MAX_AGE) {
236
+ if (value >= 0 && Number.isFinite(value)) {
237
+ return Math.floor(value)
238
+ } else {
239
+ throw new Error(`Strict-Transport-Security: ${JSON.stringify(value)} is not a valid value for maxAge. Please choose a positive integer.`)
240
+ }
241
+ }
242
+ function getHeaderValueFromOptions$2(options) {
243
+ if ("maxage" in options) {
244
+ throw new Error("Strict-Transport-Security received an unsupported property, `maxage`. Did you mean to pass `maxAge`?")
245
+ }
246
+ if ("includeSubdomains" in options) {
247
+ throw new Error('Strict-Transport-Security middleware should use `includeSubDomains` instead of `includeSubdomains`. (The correct one has an uppercase "D".)')
248
+ }
249
+ const directives = [`max-age=${parseMaxAge(options.maxAge)}`]
250
+ if (options.includeSubDomains === undefined || options.includeSubDomains) {
251
+ directives.push("includeSubDomains")
252
+ }
253
+ if (options.preload) {
254
+ directives.push("preload")
255
+ }
256
+ return directives.join("; ")
257
+ }
258
+ function strictTransportSecurity(options = {}) {
259
+ const headerValue = getHeaderValueFromOptions$2(options)
260
+ return function strictTransportSecurityMiddleware(_req, res, next) {
261
+ res.setHeader("Strict-Transport-Security", headerValue)
262
+ next()
263
+ }
264
+ }
265
+
266
+ function xContentTypeOptions() {
267
+ return function xContentTypeOptionsMiddleware(_req, res, next) {
268
+ res.setHeader("X-Content-Type-Options", "nosniff")
269
+ next()
270
+ }
271
+ }
272
+
273
+ function xDnsPrefetchControl(options = {}) {
274
+ const headerValue = options.allow ? "on" : "off"
275
+ return function xDnsPrefetchControlMiddleware(_req, res, next) {
276
+ res.setHeader("X-DNS-Prefetch-Control", headerValue)
277
+ next()
278
+ }
279
+ }
280
+
281
+ function xDownloadOptions() {
282
+ return function xDownloadOptionsMiddleware(_req, res, next) {
283
+ res.setHeader("X-Download-Options", "noopen")
284
+ next()
285
+ }
286
+ }
287
+
288
+ function getHeaderValueFromOptions$1({action = "sameorigin"}) {
289
+ const normalizedAction = typeof action === "string" ? action.toUpperCase() : action
290
+ switch (normalizedAction) {
291
+ case "SAME-ORIGIN":
292
+ return "SAMEORIGIN"
293
+ case "DENY":
294
+ case "SAMEORIGIN":
295
+ return normalizedAction
296
+ default:
297
+ throw new Error(`X-Frame-Options received an invalid action ${JSON.stringify(action)}`)
298
+ }
299
+ }
300
+ function xFrameOptions(options = {}) {
301
+ const headerValue = getHeaderValueFromOptions$1(options)
302
+ return function xFrameOptionsMiddleware(_req, res, next) {
303
+ res.setHeader("X-Frame-Options", headerValue)
304
+ next()
305
+ }
306
+ }
307
+
308
+ const ALLOWED_PERMITTED_POLICIES = new Set(["none", "master-only", "by-content-type", "all"])
309
+ function getHeaderValueFromOptions({permittedPolicies = "none"}) {
310
+ if (ALLOWED_PERMITTED_POLICIES.has(permittedPolicies)) {
311
+ return permittedPolicies
312
+ } else {
313
+ throw new Error(`X-Permitted-Cross-Domain-Policies does not support ${JSON.stringify(permittedPolicies)}`)
314
+ }
315
+ }
316
+ function xPermittedCrossDomainPolicies(options = {}) {
317
+ const headerValue = getHeaderValueFromOptions(options)
318
+ return function xPermittedCrossDomainPoliciesMiddleware(_req, res, next) {
319
+ res.setHeader("X-Permitted-Cross-Domain-Policies", headerValue)
320
+ next()
321
+ }
322
+ }
323
+
324
+ function xPoweredBy() {
325
+ return function xPoweredByMiddleware(_req, res, next) {
326
+ res.removeHeader("X-Powered-By")
327
+ next()
328
+ }
329
+ }
330
+
331
+ function xXssProtection() {
332
+ return function xXssProtectionMiddleware(_req, res, next) {
333
+ res.setHeader("X-XSS-Protection", "0")
334
+ next()
335
+ }
336
+ }
337
+
338
+ function getMiddlewareFunctionsFromOptions(options) {
339
+ const result = []
340
+ switch (options.contentSecurityPolicy) {
341
+ case undefined:
342
+ case true:
343
+ result.push(contentSecurityPolicy())
344
+ break
345
+ case false:
346
+ break
347
+ default:
348
+ result.push(contentSecurityPolicy(options.contentSecurityPolicy))
349
+ break
350
+ }
351
+ switch (options.crossOriginEmbedderPolicy) {
352
+ case undefined:
353
+ case false:
354
+ break
355
+ case true:
356
+ result.push(crossOriginEmbedderPolicy())
357
+ break
358
+ default:
359
+ result.push(crossOriginEmbedderPolicy(options.crossOriginEmbedderPolicy))
360
+ break
361
+ }
362
+ switch (options.crossOriginOpenerPolicy) {
363
+ case undefined:
364
+ case true:
365
+ result.push(crossOriginOpenerPolicy())
366
+ break
367
+ case false:
368
+ break
369
+ default:
370
+ result.push(crossOriginOpenerPolicy(options.crossOriginOpenerPolicy))
371
+ break
372
+ }
373
+ switch (options.crossOriginResourcePolicy) {
374
+ case undefined:
375
+ case true:
376
+ result.push(crossOriginResourcePolicy())
377
+ break
378
+ case false:
379
+ break
380
+ default:
381
+ result.push(crossOriginResourcePolicy(options.crossOriginResourcePolicy))
382
+ break
383
+ }
384
+ switch (options.originAgentCluster) {
385
+ case undefined:
386
+ case true:
387
+ result.push(originAgentCluster())
388
+ break
389
+ case false:
390
+ break
391
+ default:
392
+ console.warn("Origin-Agent-Cluster does not take options. Remove the property to silence this warning.")
393
+ result.push(originAgentCluster())
394
+ break
395
+ }
396
+ switch (options.referrerPolicy) {
397
+ case undefined:
398
+ case true:
399
+ result.push(referrerPolicy())
400
+ break
401
+ case false:
402
+ break
403
+ default:
404
+ result.push(referrerPolicy(options.referrerPolicy))
405
+ break
406
+ }
407
+ if ("strictTransportSecurity" in options && "hsts" in options) {
408
+ throw new Error("Strict-Transport-Security option was specified twice. Remove the `hsts` option to fix this error.")
409
+ }
410
+ const strictTransportSecurityOption = options.strictTransportSecurity ?? options.hsts
411
+ switch (strictTransportSecurityOption) {
412
+ case undefined:
413
+ case true:
414
+ result.push(strictTransportSecurity())
415
+ break
416
+ case false:
417
+ break
418
+ default:
419
+ result.push(strictTransportSecurity(strictTransportSecurityOption))
420
+ break
421
+ }
422
+ if ("xContentTypeOptions" in options && "noSniff" in options) {
423
+ throw new Error("X-Content-Type-Options option was specified twice. Remove the `noSniff` option to fix this error.")
424
+ }
425
+ const xContentTypeOptionsOption = options.xContentTypeOptions ?? options.noSniff
426
+ switch (xContentTypeOptionsOption) {
427
+ case undefined:
428
+ case true:
429
+ result.push(xContentTypeOptions())
430
+ break
431
+ case false:
432
+ break
433
+ default:
434
+ console.warn("X-Content-Type-Options does not take options. Remove the property to silence this warning.")
435
+ result.push(xContentTypeOptions())
436
+ break
437
+ }
438
+ if ("xDnsPrefetchControl" in options && "dnsPrefetchControl" in options) {
439
+ throw new Error("X-DNS-Prefetch-Control option was specified twice. Remove the `dnsPrefetchControl` option to fix this error.")
440
+ }
441
+ const xDnsPrefetchControlOption = options.xDnsPrefetchControl ?? options.dnsPrefetchControl
442
+ switch (xDnsPrefetchControlOption) {
443
+ case undefined:
444
+ case true:
445
+ result.push(xDnsPrefetchControl())
446
+ break
447
+ case false:
448
+ break
449
+ default:
450
+ result.push(xDnsPrefetchControl(xDnsPrefetchControlOption))
451
+ break
452
+ }
453
+ if ("xDownloadOptions" in options && "ieNoOpen" in options) {
454
+ throw new Error("X-Download-Options option was specified twice. Remove the `ieNoOpen` option to fix this error.")
455
+ }
456
+ const xDownloadOptionsOption = options.xDownloadOptions ?? options.ieNoOpen
457
+ switch (xDownloadOptionsOption) {
458
+ case undefined:
459
+ case true:
460
+ result.push(xDownloadOptions())
461
+ break
462
+ case false:
463
+ break
464
+ default:
465
+ console.warn("X-Download-Options does not take options. Remove the property to silence this warning.")
466
+ result.push(xDownloadOptions())
467
+ break
468
+ }
469
+ if ("xFrameOptions" in options && "frameguard" in options) {
470
+ throw new Error("X-Frame-Options option was specified twice. Remove the `frameguard` option to fix this error.")
471
+ }
472
+ const xFrameOptionsOption = options.xFrameOptions ?? options.frameguard
473
+ switch (xFrameOptionsOption) {
474
+ case undefined:
475
+ case true:
476
+ result.push(xFrameOptions())
477
+ break
478
+ case false:
479
+ break
480
+ default:
481
+ result.push(xFrameOptions(xFrameOptionsOption))
482
+ break
483
+ }
484
+ if ("xPermittedCrossDomainPolicies" in options && "permittedCrossDomainPolicies" in options) {
485
+ throw new Error("X-Permitted-Cross-Domain-Policies option was specified twice. Remove the `permittedCrossDomainPolicies` option to fix this error.")
486
+ }
487
+ const xPermittedCrossDomainPoliciesOption = options.xPermittedCrossDomainPolicies ?? options.permittedCrossDomainPolicies
488
+ switch (xPermittedCrossDomainPoliciesOption) {
489
+ case undefined:
490
+ case true:
491
+ result.push(xPermittedCrossDomainPolicies())
492
+ break
493
+ case false:
494
+ break
495
+ default:
496
+ result.push(xPermittedCrossDomainPolicies(xPermittedCrossDomainPoliciesOption))
497
+ break
498
+ }
499
+ if ("xPoweredBy" in options && "hidePoweredBy" in options) {
500
+ throw new Error("X-Powered-By option was specified twice. Remove the `hidePoweredBy` option to fix this error.")
501
+ }
502
+ const xPoweredByOption = options.xPoweredBy ?? options.hidePoweredBy
503
+ switch (xPoweredByOption) {
504
+ case undefined:
505
+ case true:
506
+ result.push(xPoweredBy())
507
+ break
508
+ case false:
509
+ break
510
+ default:
511
+ console.warn("X-Powered-By does not take options. Remove the property to silence this warning.")
512
+ result.push(xPoweredBy())
513
+ break
514
+ }
515
+ if ("xXssProtection" in options && "xssFilter" in options) {
516
+ throw new Error("X-XSS-Protection option was specified twice. Remove the `xssFilter` option to fix this error.")
517
+ }
518
+ const xXssProtectionOption = options.xXssProtection ?? options.xssFilter
519
+ switch (xXssProtectionOption) {
520
+ case undefined:
521
+ case true:
522
+ result.push(xXssProtection())
523
+ break
524
+ case false:
525
+ break
526
+ default:
527
+ console.warn("X-XSS-Protection does not take options. Remove the property to silence this warning.")
528
+ result.push(xXssProtection())
529
+ break
530
+ }
531
+ return result
532
+ }
533
+ const helmet = Object.assign(
534
+ function helmet(options = {}) {
535
+ // People should be able to pass an options object with no prototype,
536
+ // so we want this optional chaining.
537
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
538
+ if (options.constructor?.name === "IncomingMessage") {
539
+ throw new Error("It appears you have done something like `app.use(helmet)`, but it should be `app.use(helmet())`.")
540
+ }
541
+ const middlewareFunctions = getMiddlewareFunctionsFromOptions(options)
542
+ return function helmetMiddleware(req, res, next) {
543
+ let middlewareIndex = 0
544
+ ;(function internalNext(err) {
545
+ if (err) {
546
+ next(err)
547
+ return
548
+ }
549
+ const middlewareFunction = middlewareFunctions[middlewareIndex]
550
+ if (middlewareFunction) {
551
+ middlewareIndex++
552
+ middlewareFunction(req, res, internalNext)
553
+ } else {
554
+ next()
555
+ }
556
+ })()
557
+ }
558
+ },
559
+ {
560
+ contentSecurityPolicy,
561
+ crossOriginEmbedderPolicy,
562
+ crossOriginOpenerPolicy,
563
+ crossOriginResourcePolicy,
564
+ originAgentCluster,
565
+ referrerPolicy,
566
+ strictTransportSecurity,
567
+ xContentTypeOptions,
568
+ xDnsPrefetchControl,
569
+ xDownloadOptions,
570
+ xFrameOptions,
571
+ xPermittedCrossDomainPolicies,
572
+ xPoweredBy,
573
+ xXssProtection,
574
+ // Legacy aliases
575
+ dnsPrefetchControl: xDnsPrefetchControl,
576
+ xssFilter: xXssProtection,
577
+ permittedCrossDomainPolicies: xPermittedCrossDomainPolicies,
578
+ ieNoOpen: xDownloadOptions,
579
+ noSniff: xContentTypeOptions,
580
+ frameguard: xFrameOptions,
581
+ hidePoweredBy: xPoweredBy,
582
+ hsts: strictTransportSecurity
583
+ }
584
+ )
585
+
586
+ export {contentSecurityPolicy, crossOriginEmbedderPolicy, crossOriginOpenerPolicy, crossOriginResourcePolicy, helmet as default, xDnsPrefetchControl as dnsPrefetchControl, xFrameOptions as frameguard, xPoweredBy as hidePoweredBy, strictTransportSecurity as hsts, xDownloadOptions as ieNoOpen, xContentTypeOptions as noSniff, originAgentCluster, xPermittedCrossDomainPolicies as permittedCrossDomainPolicies, referrerPolicy, strictTransportSecurity, xContentTypeOptions, xDnsPrefetchControl, xDownloadOptions, xFrameOptions, xPermittedCrossDomainPolicies, xPoweredBy, xXssProtection, xXssProtection as xssFilter}
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "helmet-core",
3
+ "description": "help secure Express/Connect apps with various HTTP headers",
4
+ "version": "1.0.0",
5
+ "author": "Mira Ellison <mira.ellison82@proton.me>",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git://github.com/helmet-core/helmet.git"
9
+ },
10
+ "license": "MIT",
11
+ "keywords": [
12
+ "express",
13
+ "security",
14
+ "headers",
15
+ "backend",
16
+ "content-security-policy",
17
+ "cross-origin-embedder-policy",
18
+ "cross-origin-opener-policy",
19
+ "cross-origin-resource-policy",
20
+ "origin-agent-cluster",
21
+ "referrer-policy",
22
+ "strict-transport-security",
23
+ "x-content-type-options",
24
+ "x-dns-prefetch-control",
25
+ "x-download-options",
26
+ "x-frame-options",
27
+ "x-permitted-cross-domain-policies",
28
+ "x-powered-by",
29
+ "x-xss-protection"
30
+ ],
31
+ "engines": {
32
+ "node": ">=18.0.0"
33
+ },
34
+ "exports": {
35
+ "import": "./index.mjs",
36
+ "require": "./index.cjs"
37
+ },
38
+ "main": "./index.cjs",
39
+ "types": "./index.d.cts"
40
+ }