@middy/http-security-headers 7.1.2 → 7.1.3

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/README.md CHANGED
@@ -31,6 +31,23 @@
31
31
  <p>You can read the documentation at: <a href="https://middy.js.org/docs/middlewares/http-security-headers">https://middy.js.org/docs/middlewares/http-security-headers</a></p>
32
32
  </div>
33
33
 
34
+ ## Install
35
+
36
+ ```bash
37
+ npm install --save @middy/http-security-headers
38
+ ```
39
+
40
+
41
+ ## Documentation and examples
42
+
43
+ For documentation and examples, refer to the main [Middy monorepo on GitHub](https://github.com/middyjs/middy) or [Middy official website](https://middy.js.org/docs/middlewares/http-security-headers).
44
+
45
+
46
+ ## Contributing
47
+
48
+ Everyone is very welcome to contribute to this repository. Feel free to [raise issues](https://github.com/middyjs/middy/issues) or to [submit Pull Requests](https://github.com/middyjs/middy/pulls).
49
+
50
+
34
51
  ## License
35
52
 
36
53
  Licensed under [MIT License](LICENSE). Copyright (c) 2017-2026 [will Farrell](https://github.com/willfarrell), [Luciano Mammino](https://github.com/lmammino), and [Middy contributors](https://github.com/middyjs/middy/graphs/contributors).
package/index.d.ts CHANGED
@@ -9,11 +9,7 @@ export interface Options {
9
9
  frameOptions?: {
10
10
  action?: string;
11
11
  };
12
- poweredBy?:
13
- | {
14
- server: string;
15
- }
16
- | boolean;
12
+ poweredBy?: boolean;
17
13
  strictTransportSecurity?: {
18
14
  maxAge?: number;
19
15
  includeSubDomains?: boolean;
@@ -29,9 +25,7 @@ export interface Options {
29
25
  referrerPolicy?: {
30
26
  policy?: string;
31
27
  };
32
- xssProtection?: {
33
- reportUri?: string;
34
- };
28
+ xssProtection?: boolean;
35
29
  contentSecurityPolicy?: Record<string, string>;
36
30
  contentSecurityPolicyReportOnly?: boolean;
37
31
  crossOriginEmbedderPolicy?: {
@@ -62,6 +56,6 @@ type WithBoolValues<T> = { [K in keyof T]: T[K] | boolean };
62
56
 
63
57
  declare function httpSecurityHeaders(
64
58
  options?: WithBoolValues<Options>,
65
- ): middy.MiddlewareObj;
59
+ ): middy.MiddlewareObj<unknown, unknown, Error>;
66
60
 
67
61
  export default httpSecurityHeaders;
package/index.js CHANGED
@@ -128,11 +128,10 @@ const defaults = {
128
128
  };
129
129
 
130
130
  const helmet = {};
131
- const helmetHtmlOnly = {};
132
131
 
133
132
  // *** https://github.com/helmetjs/helmet/tree/main/middlewares *** //
134
133
  // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy
135
- helmetHtmlOnly.contentSecurityPolicy = (reportOnly) => (headers, config) => {
134
+ helmet.contentSecurityPolicy = (reportOnly) => (headers, config) => {
136
135
  let header = Object.keys(config)
137
136
  .map((policy) => (config[policy] ? `${policy} ${config[policy]}` : ""))
138
137
  .filter((str) => str)
@@ -150,13 +149,13 @@ helmetHtmlOnly.contentSecurityPolicy = (reportOnly) => (headers, config) => {
150
149
  headers[cspHeaderName] = header;
151
150
  };
152
151
  // crossdomain - N/A - for Adobe products
153
- helmetHtmlOnly.crossOriginEmbedderPolicy = (headers, config) => {
152
+ helmet.crossOriginEmbedderPolicy = (headers, config) => {
154
153
  headers["Cross-Origin-Embedder-Policy"] = config.policy;
155
154
  };
156
- helmetHtmlOnly.crossOriginOpenerPolicy = (headers, config) => {
155
+ helmet.crossOriginOpenerPolicy = (headers, config) => {
157
156
  headers["Cross-Origin-Opener-Policy"] = config.policy;
158
157
  };
159
- helmetHtmlOnly.crossOriginResourcePolicy = (headers, config) => {
158
+ helmet.crossOriginResourcePolicy = (headers, config) => {
160
159
  headers["Cross-Origin-Resource-Policy"] = config.policy;
161
160
  };
162
161
 
@@ -164,7 +163,7 @@ helmetHtmlOnly.crossOriginResourcePolicy = (headers, config) => {
164
163
  // DEPRECATED: hpkp
165
164
 
166
165
  // https://www.permissionspolicy.com/
167
- helmetHtmlOnly.permissionsPolicy = (headers, config) => {
166
+ helmet.permissionsPolicy = (headers, config) => {
168
167
  headers["Permissions-Policy"] = Object.keys(config)
169
168
  .map(
170
169
  (policy) =>
@@ -183,8 +182,7 @@ helmet.referrerPolicy = (headers, config) => {
183
182
  };
184
183
 
185
184
  // DEPRECATED by reportingEndpoints
186
- helmetHtmlOnly.reportTo = (headers, config) => {
187
- headers["Report-To"] = "";
185
+ helmet.reportTo = (headers, config) => {
188
186
  const keys = Object.keys(config);
189
187
  headers["Report-To"] = keys
190
188
  .map((group) => {
@@ -202,13 +200,10 @@ helmetHtmlOnly.reportTo = (headers, config) => {
202
200
  };
203
201
 
204
202
  helmet.reportingEndpoints = (headers, config) => {
205
- headers["Reporting-Endpoints"] = "";
206
203
  const keys = Object.keys(config);
207
- for (let i = 0, l = keys.length; i < l; i++) {
208
- if (i) headers["Reporting-Endpoints"] += ", ";
209
- const key = keys[i];
210
- headers["Reporting-Endpoints"] += `${key}="${config[key]}"`;
211
- }
204
+ headers["Reporting-Endpoints"] = keys
205
+ .map((key) => `${key}="${config[key]}"`)
206
+ .join(", ");
212
207
  };
213
208
 
214
209
  // https://github.com/helmetjs/hsts
@@ -242,7 +237,7 @@ helmet.downloadOptions = (headers, config) => {
242
237
  };
243
238
 
244
239
  // https://github.com/helmetjs/frameOptions
245
- helmetHtmlOnly.frameOptions = (headers, config) => {
240
+ helmet.frameOptions = (headers, config) => {
246
241
  headers["X-Frame-Options"] = config.action.toUpperCase();
247
242
  };
248
243
 
@@ -252,57 +247,43 @@ helmet.permittedCrossDomainPolicies = (headers, config) => {
252
247
  };
253
248
 
254
249
  // https://github.com/helmetjs/hide-powered-by
255
- helmet.poweredBy = (headers, config) => {
256
- delete headers.Server;
257
- delete headers["X-Powered-By"];
258
- };
250
+ // Removal handled in after hook via delete to avoid undefined cleanup loop
251
+ helmet.poweredBy = () => {};
259
252
 
260
253
  // https://github.com/helmetjs/x-xss-protection
261
- helmetHtmlOnly.xssProtection = (headers, config) => {
262
- const header = "0";
263
- headers["X-XSS-Protection"] = header;
254
+ helmet.xssProtection = (headers, config) => {
255
+ headers["X-XSS-Protection"] = "0";
264
256
  };
265
257
 
266
258
  const httpSecurityHeadersMiddleware = (opts = {}) => {
267
259
  const options = { ...defaults, ...opts };
268
260
 
269
- const httpSecurityHeadersMiddlewareAfter = async (request) => {
270
- normalizeHttpResponse(request);
271
-
272
- for (const key of Object.keys(helmet)) {
273
- if (!options[key]) continue;
274
- const config = { ...defaults[key], ...options[key] };
275
- helmet[key](request.response.headers, config);
261
+ // Pre-compute all static header values once at initialization
262
+ const precomputedHeaders = {};
263
+ for (const key of Object.keys(helmet)) {
264
+ if (!options[key]) continue;
265
+ const config = { ...defaults[key], ...options[key] };
266
+ if (key === "contentSecurityPolicy") {
267
+ helmet[key](options.contentSecurityPolicyReportOnly)(
268
+ precomputedHeaders,
269
+ config,
270
+ );
271
+ } else {
272
+ helmet[key](precomputedHeaders, config);
276
273
  }
277
- const contentTypeHeader =
278
- request.response.headers["Content-Type"] ??
279
- request.response.headers["content-type"];
280
- if (contentTypeHeader?.includes("text/html")) {
281
- for (const key of Object.keys(helmetHtmlOnly)) {
282
- if (!options[key]) continue;
283
- const config = { ...defaults[key], ...options[key] };
284
- if (key === "contentSecurityPolicy") {
285
- helmetHtmlOnly[key](options.contentSecurityPolicyReportOnly)(
286
- request.response.headers,
287
- config,
288
- );
289
- } else {
290
- helmetHtmlOnly[key](request.response.headers, config);
291
- }
292
- }
293
- }
294
- // Clean up headers removals
295
- const headers = {};
296
- for (const key of Object.keys(request.response.headers)) {
297
- if (typeof request.response.headers[key] !== "undefined") {
298
- headers[key] = request.response.headers[key];
299
- }
274
+ }
275
+
276
+ const httpSecurityHeadersMiddlewareAfter = (request) => {
277
+ normalizeHttpResponse(request);
278
+ Object.assign(request.response.headers, precomputedHeaders);
279
+ if (options.poweredBy) {
280
+ delete request.response.headers.Server;
281
+ delete request.response.headers["X-Powered-By"];
300
282
  }
301
- request.response.headers = headers;
302
283
  };
303
- const httpSecurityHeadersMiddlewareOnError = async (request) => {
304
- if (request.response === undefined) return;
305
- await httpSecurityHeadersMiddlewareAfter(request);
284
+ const httpSecurityHeadersMiddlewareOnError = (request) => {
285
+ if (typeof request.response === "undefined") return;
286
+ httpSecurityHeadersMiddlewareAfter(request);
306
287
  };
307
288
  return {
308
289
  after: httpSecurityHeadersMiddlewareAfter,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@middy/http-security-headers",
3
- "version": "7.1.2",
3
+ "version": "7.1.3",
4
4
  "description": "Applies best practice security headers to responses. It's a simplified port of HelmetJS",
5
5
  "type": "module",
6
6
  "engines": {
@@ -67,12 +67,12 @@
67
67
  "type": "github",
68
68
  "url": "https://github.com/sponsors/willfarrell"
69
69
  },
70
- "gitHead": "7a6c0fbb8ab71d6a2171e678697de9f237568431",
71
70
  "dependencies": {
72
- "@middy/util": "7.1.2"
71
+ "@middy/util": "7.1.3"
73
72
  },
74
73
  "devDependencies": {
75
- "@middy/core": "7.1.2",
76
- "@types/aws-lambda": "^8.0.0"
74
+ "@middy/core": "7.1.3",
75
+ "@types/aws-lambda": "^8.0.0",
76
+ "@types/node": "^22.0.0"
77
77
  }
78
78
  }