@govuk-pay/pay-js-commons 7.0.21 → 7.0.26

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
@@ -32,7 +32,7 @@ Validators:
32
32
  - [isNaxsiSafe](#naxsi)
33
33
 
34
34
  #### Required
35
- This requires a value from a given input
35
+ This requires a value from a given input:
36
36
 
37
37
  ```html
38
38
  <form data-validate>
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+
3
+ var _require = require('express-rate-limit'),
4
+ rateLimit = _require.rateLimit;
5
+ var hasSubstr = function hasSubstr(lookUpStrings, targetString) {
6
+ return lookUpStrings.some(function (str) {
7
+ return targetString.toLowerCase().includes(str.toLowerCase());
8
+ });
9
+ };
10
+ var rateLimitMiddleware = rateLimit({
11
+ windowMs: 5 * 60 * 1000,
12
+ // 5 minutes
13
+ limit: 10,
14
+ // Limit each IP to 10 requests per window
15
+ standardHeaders: 'draft-7',
16
+ // draft-6: `RateLimit-*` headers; draft-7: combined `RateLimit` header
17
+ legacyHeaders: false // Disable the `X-RateLimit-*` headers.
18
+ });
19
+ var requestParseMiddleware = function requestParseMiddleware(maxPayloadBytes, express) {
20
+ return function (req, res, next) {
21
+ if (req.is('application/json') || req.is('application/reports+json') || req.is('application/csp-report')) {
22
+ express.json({
23
+ type: ['application/json', 'application/reports+json', 'application/csp-report'],
24
+ limit: maxPayloadBytes // limit body payload to maxPayloadBytes, validated prior to parsing
25
+ })(req, res, next);
26
+ } else {
27
+ return res.status(400).end();
28
+ }
29
+ };
30
+ };
31
+ var detectErrorsMiddleware = function detectErrorsMiddleware(logger) {
32
+ return function (err, req, res, next) {
33
+ if (err) {
34
+ if (err.type === 'entity.too.large') logger.info('CSP violation request payload exceeds maximum size');
35
+ if (err.type === 'entity.parse.failed') logger.info('CSP violation request payload did not match expected content type');
36
+ return res.status(400).end();
37
+ }
38
+ next();
39
+ };
40
+ };
41
+ var captureEventMiddleware = function captureEventMiddleware(ignoredStrings, logger, sentry) {
42
+ return function (req, res) {
43
+ var reports = undefined;
44
+ if (Array.isArray(req.body) && req.body.length > 0) {
45
+ reports = req.body.filter(function (report) {
46
+ return report.type === 'csp-violation';
47
+ }); // new style reporting-api, can be batched into multiple reports
48
+ } else if (req.body['csp-report'] !== undefined) {
49
+ reports = [{
50
+ body: req.body['csp-report']
51
+ }]; // old style report-uri
52
+ }
53
+ var userAgent = req.headers['user-agent'];
54
+ if (reports !== undefined) {
55
+ reports.forEach(function (report) {
56
+ var _body$blockedUri, _body$violatedDirect;
57
+ var body = report.body;
58
+ var blockedUri = (_body$blockedUri = body['blocked-uri']) !== null && _body$blockedUri !== void 0 ? _body$blockedUri : body['blockedURL'];
59
+ var violatedDirective = (_body$violatedDirect = body['violated-directive']) !== null && _body$violatedDirect !== void 0 ? _body$violatedDirect : body['effectiveDirective']; // https://www.w3.org/TR/CSP3/#dom-securitypolicyviolationevent-violateddirective
60
+ if (violatedDirective === undefined || blockedUri === undefined) {
61
+ logger.info('CSP violation report is invalid');
62
+ return res.status(400).end();
63
+ } else {
64
+ if (hasSubstr(ignoredStrings, blockedUri)) return res.status(204).end();
65
+ sentry.captureEvent({
66
+ message: "Blocked ".concat(violatedDirective, " from ").concat(blockedUri),
67
+ level: 'warning',
68
+ extra: {
69
+ cspReport: body,
70
+ userAgent: userAgent
71
+ }
72
+ });
73
+ }
74
+ });
75
+ } else {
76
+ logger.info('CSP violation report missing');
77
+ return res.status(400).end();
78
+ }
79
+ return res.status(204).end();
80
+ };
81
+ };
82
+ module.exports = {
83
+ rateLimitMiddleware: rateLimitMiddleware,
84
+ captureEventMiddleware: captureEventMiddleware,
85
+ requestParseMiddleware: requestParseMiddleware,
86
+ detectErrorsMiddleware: detectErrorsMiddleware
87
+ };
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "@govuk-pay/pay-js-commons",
3
- "version": "7.0.21",
3
+ "version": "7.0.26",
4
4
  "description": "Reusable js scripts for GOV.UK Pay Node.js projects",
5
5
  "engines": {
6
- "node": "^22.17.1"
6
+ "node": "^22.17.1",
7
+ "npm": "^11.6.0"
7
8
  },
8
9
  "main": "lib/index.js",
9
10
  "files": [
@@ -120,6 +121,7 @@
120
121
  "chai": "^4.2.0",
121
122
  "eslint-plugin-import": "^2.18.0",
122
123
  "eslint-plugin-promise": "^6.0.0",
124
+ "express": "^5.1.0",
123
125
  "jest": "^29.4.3",
124
126
  "jest-environment-jsdom": "^29.4.3",
125
127
  "js-cookie": "^3.0.0",
@@ -136,6 +138,7 @@
136
138
  "nock": "^13.5.1",
137
139
  "sinon": "^15.0.0",
138
140
  "standard": "^17.0.0",
141
+ "supertest": "^7.1.4",
139
142
  "uglify-js": "^3.6.0",
140
143
  "watchify": "^4.0.0",
141
144
  "xo": "^0.54.0"
@@ -146,6 +149,7 @@
146
149
  "dependencies": {
147
150
  "axios": "^1.6.5",
148
151
  "csrf": "^3.1.0",
152
+ "express-rate-limit": "^8.1.0",
149
153
  "lodash": "4.17.21",
150
154
  "moment-timezone": "0.5.43",
151
155
  "rfc822-validate": "1.0.0",