From 3e949688750e2d022264b1825915fbeea006e281 Mon Sep 17 00:00:00 2001 From: Simon Boyd Date: Tue, 8 Oct 2024 12:21:15 +0100 Subject: [PATCH 1/8] WIP SEC-87 --- .ncurc.json | 3 ++ Dockerfile | 2 +- package-lock.json | 37 ++++++++++++++----- package.json | 4 +- src/middleware/csrf.ts | 11 ++++++ src/middleware/session.ts | 2 +- src/views/layouts/default.njk | 1 + .../confirmCompany/confirmCompany.njk | 2 +- .../router_views/includes/csrf_token.html | 2 + .../individualPscList/individualPscList.njk | 1 + .../individual_statement.njk | 1 + src/views/router_views/psc_type/psc_type.njk | 5 ++- test/mocks/allMiddleware.mock.ts | 2 + test/mocks/csrfProtectionMiddleware.mock.ts | 10 +++++ .../confirmCompanyHandler.unit.ts | 3 ++ 15 files changed, 69 insertions(+), 17 deletions(-) create mode 100644 .ncurc.json create mode 100644 src/middleware/csrf.ts create mode 100644 src/views/router_views/includes/csrf_token.html create mode 100644 test/mocks/csrfProtectionMiddleware.mock.ts diff --git a/.ncurc.json b/.ncurc.json new file mode 100644 index 00000000..57886951 --- /dev/null +++ b/.ncurc.json @@ -0,0 +1,3 @@ +{ + "target": "minor" +} diff --git a/Dockerfile b/Dockerfile index 5579607c..b1ddb40a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,5 +17,5 @@ WORKDIR /app COPY package*.json ./ RUN npm install COPY . . -CMD [ "npm", "run", "start:watch" ] +CMD [ "npm", "run", "sntart:watch" ] # ENTRYPOINT [ "bash" ] diff --git a/package-lock.json b/package-lock.json index 6c47f0d6..dcdb06a1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,9 +13,9 @@ "@companieshouse/ch-node-utils": "^1.3.2", "@companieshouse/node-session-handler": "^5.0.1", "@companieshouse/structured-logging-node": "^2.0.1", - "@companieshouse/web-security-node": "^2.0.5", + "@companieshouse/web-security-node": "^4.3.1", "@types/supertest": "^6.0.2", - "axios": "^1.6.7", + "axios": "^1.7.5", "cookie-parser": "1.4.5", "express": "^4.19.2", "govuk_frontend_toolkit": "^9.0.1", @@ -718,9 +718,10 @@ } }, "node_modules/@companieshouse/node-session-handler": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@companieshouse/node-session-handler/-/node-session-handler-5.0.2.tgz", - "integrity": "sha512-XEhsN7p9gXk32RQHytwgkIRA8rSEfsWvtdLHSF4JJOLiuztSv6sDYx/mxZLWgAU0gCNWgrM3UW/+6KLFeTGM1Q==", + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/@companieshouse/node-session-handler/-/node-session-handler-5.1.4.tgz", + "integrity": "sha512-giKQWlnaugFcgQoHrBMN61x6GMLrwcxkPS1y0NnMpXLePynQKbkdXjUm4aoWSS4fNe95tg2YnJkU66XWjnwhKw==", + "license": "MIT", "dependencies": { "@companieshouse/structured-logging-node": "^1.0.0", "crypto": "^1.0.1", @@ -789,12 +790,28 @@ } }, "node_modules/@companieshouse/web-security-node": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@companieshouse/web-security-node/-/web-security-node-2.0.5.tgz", - "integrity": "sha512-uiCrZiavQ0Scg3T02vHRlMIZwbqb5VdLGR1R6oeU4tEMLrvMtiVV/KCrLyjdJwVphbsqybtxE5XhE/4rBdFgBQ==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@companieshouse/web-security-node/-/web-security-node-4.3.1.tgz", + "integrity": "sha512-sQhbApcY5a5K8eSHdnPDiyY5q4DiMF/j6Q3tsaHx4yJs5264JDk3aFcPr0ZhcePBB7kVnekGg1idvPdN0TZcvQ==", + "license": "MIT", "dependencies": { - "@companieshouse/node-session-handler": "~5.0.1", - "@companieshouse/structured-logging-node": "~2.0.1" + "@companieshouse/node-session-handler": "~5.1.3", + "@companieshouse/structured-logging-node": "~2.0.1", + "express-async-handler": "^1.2.0", + "uuid": "^9.0.1" + } + }, + "node_modules/@companieshouse/web-security-node/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" } }, "node_modules/@cspotcode/source-map-support": { diff --git a/package.json b/package.json index 03dc0e30..9ddfcad9 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "coverage": "jest --coverage", "test": "jest", "test:coverage": "sh ./scripts/jest_coverage.sh", - "start": "npm run build && source ./dist/config/.env && node dist/httpServer.js", + "start": "npm run build && node dist/httpServer.js", "start:watch": "nodemon", "sonarqube-base-branch": "sonar-scanner", "sonarqube-pull-request": "sonar-scanner -D sonar.pullrequest.base=main", @@ -35,7 +35,7 @@ "@companieshouse/ch-node-utils": "^1.3.2", "@companieshouse/node-session-handler": "^5.0.1", "@companieshouse/structured-logging-node": "^2.0.1", - "@companieshouse/web-security-node": "^2.0.5", + "@companieshouse/web-security-node": "^4.3.1", "@types/supertest": "^6.0.2", "axios": "^1.7.5", "cookie-parser": "1.4.5", diff --git a/src/middleware/csrf.ts b/src/middleware/csrf.ts new file mode 100644 index 00000000..63ec16a0 --- /dev/null +++ b/src/middleware/csrf.ts @@ -0,0 +1,11 @@ +import { CsrfProtectionMiddleware } from "@companieshouse/web-security-node"; +import { sessionStore } from "./session"; +import { env } from "../config"; + +export const csrfProtectionMiddleware = CsrfProtectionMiddleware({ + sessionStore, + enabled: false, + sessionCookieName: env.COOKIE_NAME +}); + +console.log(env.COOKIE_NAME); \ No newline at end of file diff --git a/src/middleware/session.ts b/src/middleware/session.ts index 52568e8e..501282ab 100644 --- a/src/middleware/session.ts +++ b/src/middleware/session.ts @@ -3,7 +3,7 @@ import Redis from "ioredis"; import { env } from "../config"; const redis = new Redis(env.CACHE_SERVER); -const sessionStore = new SessionStore(redis); +export const sessionStore = new SessionStore(redis); export const sessionMiddleware = SessionMiddleware({ cookieDomain: env.COOKIE_DOMAIN, diff --git a/src/views/layouts/default.njk b/src/views/layouts/default.njk index 6636b136..dd8b1fe6 100644 --- a/src/views/layouts/default.njk +++ b/src/views/layouts/default.njk @@ -2,6 +2,7 @@ {% import "add-lang-to-url.njk" as lang2url %} +{% from "web-security-node/components/csrf-token-input/macro.njk" import csrfTokenInput %} {% include "partials/__meta_header.njk" %} diff --git a/src/views/router_views/confirmCompany/confirmCompany.njk b/src/views/router_views/confirmCompany/confirmCompany.njk index 438cbec9..194b440b 100644 --- a/src/views/router_views/confirmCompany/confirmCompany.njk +++ b/src/views/router_views/confirmCompany/confirmCompany.njk @@ -8,7 +8,7 @@ {% block main_content %}

{{ i18n.confirm_company_main_title }}

- + {% include "includes/csrf_token.html" %} {{ govukSummaryList({ rows: [ { diff --git a/src/views/router_views/includes/csrf_token.html b/src/views/router_views/includes/csrf_token.html new file mode 100644 index 00000000..967becb1 --- /dev/null +++ b/src/views/router_views/includes/csrf_token.html @@ -0,0 +1,2 @@ +{{ csrfTokenInput({ csrfToken: csrfToken }) }} +npm \ No newline at end of file diff --git a/src/views/router_views/individualPscList/individualPscList.njk b/src/views/router_views/individualPscList/individualPscList.njk index a8aa08f6..fe2b0d91 100644 --- a/src/views/router_views/individualPscList/individualPscList.njk +++ b/src/views/router_views/individualPscList/individualPscList.njk @@ -6,6 +6,7 @@ {% block main_content %} + {% include "includes/csrf_token.html" %}
{{ govukRadios({ classes: "govuk-radios", diff --git a/src/views/router_views/individual_statement/individual_statement.njk b/src/views/router_views/individual_statement/individual_statement.njk index 36641433..c3935788 100644 --- a/src/views/router_views/individual_statement/individual_statement.njk +++ b/src/views/router_views/individual_statement/individual_statement.njk @@ -21,6 +21,7 @@ {% block main_content %} + {% include "includes/csrf_token.html" %}
{{ nameAndDateBirthText }}
diff --git a/src/views/router_views/psc_type/psc_type.njk b/src/views/router_views/psc_type/psc_type.njk index 79cb5fd9..75182c52 100644 --- a/src/views/router_views/psc_type/psc_type.njk +++ b/src/views/router_views/psc_type/psc_type.njk @@ -8,6 +8,7 @@ {% block main_content %} + {% include "includes/csrf_token.html" %} {{ govukRadios({ idPrefix: "pscType", name: "pscType", @@ -26,7 +27,7 @@ attributes:{ "data-event-id": "psc-type-radio-option" } - + }, { value: "rle", @@ -53,7 +54,7 @@ {{ govukButton({ attributes: { - id: "submit", + id: "submit", "data-event-id": "psc-type-continue-button" }, text: i18n.global_continue_button diff --git a/test/mocks/allMiddleware.mock.ts b/test/mocks/allMiddleware.mock.ts index c92f6ccf..75d2a944 100644 --- a/test/mocks/allMiddleware.mock.ts +++ b/test/mocks/allMiddleware.mock.ts @@ -1,10 +1,12 @@ import mockAuthenticationMiddleware from "./authenticationMiddleware.mock"; +import mockCsrfProtectionMiddleware from "./csrfProtectionMiddleware.mock"; import mockFetchCompanyMiddleware from "./fetchCompany.mock"; import mockFetchVerificationMiddleware from "./fetchVerification.mock"; import mockSessionMiddleware from "./sessionMiddleware.mock"; export default { mockSessionMiddleware, + mockCsrfProtectionMiddleware, mockAuthenticationMiddleware, mockFetchVerificationMiddleware, mockFetchCompanyMiddleware diff --git a/test/mocks/csrfProtectionMiddleware.mock.ts b/test/mocks/csrfProtectionMiddleware.mock.ts new file mode 100644 index 00000000..b89a28ad --- /dev/null +++ b/test/mocks/csrfProtectionMiddleware.mock.ts @@ -0,0 +1,10 @@ +import { NextFunction, Request, Response } from "express"; +import { CsrfProtectionMiddleware } from "@companieshouse/web-security-node"; + +jest.mock("@companieshouse/web-security-node"); + +const mockCsrfProtectionMiddleware = CsrfProtectionMiddleware as jest.Mock; + +mockCsrfProtectionMiddleware.mockImplementation((_opts) => (req: Request, res: Response, next: NextFunction) => next()); + +export default mockCsrfProtectionMiddleware; diff --git a/test/routers/handlers/confirm-company/confirmCompanyHandler.unit.ts b/test/routers/handlers/confirm-company/confirmCompanyHandler.unit.ts index dc522070..9d267aa6 100644 --- a/test/routers/handlers/confirm-company/confirmCompanyHandler.unit.ts +++ b/test/routers/handlers/confirm-company/confirmCompanyHandler.unit.ts @@ -4,6 +4,9 @@ import { ConfirmCompanyHandler } from "../../../../src/routers/handlers/confirm- import { COMPANY_NUMBER } from "../../../mocks/companyPsc.mock"; import { getCompanyProfile } from "../../../../src/services/companyProfileService"; import { validCompanyProfile } from "../../../mocks/companyProfile.mock"; +import mockCsrfProtectionMiddleware from "../../../mocks/csrfProtectionMiddleware.mock"; + +mockCsrfProtectionMiddleware.mockClear(); jest.mock("../../../../src/services/companyProfileService"); const mockGetCompanyProfile = getCompanyProfile as jest.Mock; From a361f0b1b9aab0721ac3a6fec9213044aba96a18 Mon Sep 17 00:00:00 2001 From: Simon Boyd Date: Wed, 9 Oct 2024 15:59:40 +0100 Subject: [PATCH 2/8] WIP SEC-87 --- Dockerfile | 2 +- package-lock.json | 134 ++++++++++++------ package.json | 2 +- src/app.ts | 7 +- src/middleware/csrf.ts | 4 +- .../csrf_token.njk} | 1 - src/views/layouts/default.njk | 2 +- .../confirmCompany/confirmCompany.njk | 2 +- .../individualPscList/individualPscList.njk | 2 +- .../individual_statement.njk | 2 +- .../personal_code/personal_code.njk | 1 + src/views/router_views/psc_type/psc_type.njk | 2 +- .../personal-code/personalCode.int.ts | 1 + 13 files changed, 104 insertions(+), 58 deletions(-) rename src/views/{router_views/includes/csrf_token.html => includes/csrf_token.njk} (94%) diff --git a/Dockerfile b/Dockerfile index b1ddb40a..5579607c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,5 +17,5 @@ WORKDIR /app COPY package*.json ./ RUN npm install COPY . . -CMD [ "npm", "run", "sntart:watch" ] +CMD [ "npm", "run", "start:watch" ] # ENTRYPOINT [ "bash" ] diff --git a/package-lock.json b/package-lock.json index dcdb06a1..5fd584b6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "@companieshouse/api-sdk-node": "^2.0.172", "@companieshouse/ch-node-utils": "^1.3.2", - "@companieshouse/node-session-handler": "^5.0.1", + "@companieshouse/node-session-handler": "^5.1.4", "@companieshouse/structured-logging-node": "^2.0.1", "@companieshouse/web-security-node": "^4.3.1", "@types/supertest": "^6.0.2", @@ -2836,9 +2836,10 @@ } }, "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "license": "MIT", "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.5", @@ -2848,7 +2849,7 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.11.0", + "qs": "6.13.0", "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" @@ -2862,6 +2863,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -2870,6 +2872,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", @@ -2884,12 +2887,14 @@ "node_modules/body-parser/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" }, "node_modules/body-parser/node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", "dependencies": { "ee-first": "1.1.1" }, @@ -3017,6 +3022,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -3457,6 +3463,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -3905,6 +3912,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", "engines": { "node": ">= 0.8", "npm": "1.2.8000 || >= 1.4.16" @@ -4082,9 +4090,10 @@ "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" }, "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -4268,7 +4277,8 @@ "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" }, "node_modules/escape-string-regexp": { "version": "4.0.0", @@ -4784,6 +4794,7 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -4849,36 +4860,37 @@ } }, "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", + "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", + "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.2", + "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.2.0", + "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", + "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", + "path-to-regexp": "0.1.10", "proxy-addr": "~2.0.7", - "qs": "6.11.0", + "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", + "send": "0.19.0", + "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", @@ -5078,12 +5090,13 @@ } }, "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "license": "MIT", "dependencies": { "debug": "2.6.9", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", @@ -5098,6 +5111,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -5105,12 +5119,14 @@ "node_modules/finalhandler/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" }, "node_modules/finalhandler/node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", "dependencies": { "ee-first": "1.1.1" }, @@ -6402,6 +6418,7 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -8258,9 +8275,13 @@ } }, "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/merge-stream": { "version": "2.0.0", @@ -9390,9 +9411,10 @@ } }, "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", + "license": "MIT" }, "node_modules/path-type": { "version": "4.0.0", @@ -9619,11 +9641,12 @@ ] }, "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -9687,6 +9710,7 @@ "version": "2.5.2", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -9701,6 +9725,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", @@ -10130,9 +10155,10 @@ } }, "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", "dependencies": { "debug": "2.6.9", "depd": "2.0.0", @@ -10156,6 +10182,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -10163,12 +10190,23 @@ "node_modules/send/node_modules/debug/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } }, "node_modules/send/node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", @@ -10183,12 +10221,14 @@ "node_modules/send/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/send/node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", "dependencies": { "ee-first": "1.1.1" }, @@ -10206,14 +10246,15 @@ } }, "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", "dependencies": { - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.18.0" + "send": "0.19.0" }, "engines": { "node": ">= 0.8.0" @@ -11304,6 +11345,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } diff --git a/package.json b/package.json index 9ddfcad9..71ef02a6 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "dependencies": { "@companieshouse/api-sdk-node": "^2.0.172", "@companieshouse/ch-node-utils": "^1.3.2", - "@companieshouse/node-session-handler": "^5.0.1", + "@companieshouse/node-session-handler": "^5.1.4", "@companieshouse/structured-logging-node": "^2.0.1", "@companieshouse/web-security-node": "^4.3.1", "@types/supertest": "^6.0.2", diff --git a/src/app.ts b/src/app.ts index 0d221959..8e4d9746 100755 --- a/src/app.ts +++ b/src/app.ts @@ -7,6 +7,8 @@ import { logger } from "./lib/logger"; import { sessionMiddleware } from "./middleware/session"; import routerDispatch from "./routerDispatch"; import { isLive } from "./middleware/serviceLive"; +import { csrfProtectionMiddleware } from "./middleware/csrf"; + const app = express(); app.use(isLive); @@ -17,7 +19,9 @@ app.set("views", [ path.join(__dirname, "../node_modules/govuk-frontend"), // This if for when using ts-node since the working directory is src path.join(__dirname, "node_modules/govuk-frontend/components"), path.join(__dirname, "../node_modules/@companieshouse/ch-node-utils/templates/"), - path.join(__dirname, "node_modules/@companieshouse/ch-node-utils/templates/") + path.join(__dirname, "node_modules/@companieshouse/ch-node-utils/templates/"), + path.join(__dirname, "../node_modules/@companieshouse/web-security-node/components"), + path.join(__dirname, "node_modules/@companieshouse/web-security-node/components") ]); const nunjucksLoaderOpts = { @@ -36,6 +40,7 @@ app.set("view engine", "njk"); // apply middleware app.use(cookieParser()); app.use(servicePathPrefix, sessionMiddleware); +app.use(csrfProtectionMiddleware); // Serve static files app.use(express.static(path.join(__dirname, "/../assets/public"))); diff --git a/src/middleware/csrf.ts b/src/middleware/csrf.ts index 63ec16a0..5c506a46 100644 --- a/src/middleware/csrf.ts +++ b/src/middleware/csrf.ts @@ -4,8 +4,6 @@ import { env } from "../config"; export const csrfProtectionMiddleware = CsrfProtectionMiddleware({ sessionStore, - enabled: false, + enabled: true, sessionCookieName: env.COOKIE_NAME }); - -console.log(env.COOKIE_NAME); \ No newline at end of file diff --git a/src/views/router_views/includes/csrf_token.html b/src/views/includes/csrf_token.njk similarity index 94% rename from src/views/router_views/includes/csrf_token.html rename to src/views/includes/csrf_token.njk index 967becb1..42e88bdf 100644 --- a/src/views/router_views/includes/csrf_token.html +++ b/src/views/includes/csrf_token.njk @@ -1,2 +1 @@ {{ csrfTokenInput({ csrfToken: csrfToken }) }} -npm \ No newline at end of file diff --git a/src/views/layouts/default.njk b/src/views/layouts/default.njk index dd8b1fe6..8fc8af53 100644 --- a/src/views/layouts/default.njk +++ b/src/views/layouts/default.njk @@ -2,7 +2,7 @@ {% import "add-lang-to-url.njk" as lang2url %} -{% from "web-security-node/components/csrf-token-input/macro.njk" import csrfTokenInput %} +{% from "csrf-token-input/macro.njk" import csrfTokenInput %} {% include "partials/__meta_header.njk" %} diff --git a/src/views/router_views/confirmCompany/confirmCompany.njk b/src/views/router_views/confirmCompany/confirmCompany.njk index 194b440b..9aa67f70 100644 --- a/src/views/router_views/confirmCompany/confirmCompany.njk +++ b/src/views/router_views/confirmCompany/confirmCompany.njk @@ -8,7 +8,7 @@ {% block main_content %}

{{ i18n.confirm_company_main_title }}

- {% include "includes/csrf_token.html" %} + {% include "includes/csrf_token.njk" %} {{ govukSummaryList({ rows: [ { diff --git a/src/views/router_views/individualPscList/individualPscList.njk b/src/views/router_views/individualPscList/individualPscList.njk index fe2b0d91..dea22ba6 100644 --- a/src/views/router_views/individualPscList/individualPscList.njk +++ b/src/views/router_views/individualPscList/individualPscList.njk @@ -6,7 +6,7 @@ {% block main_content %} - {% include "includes/csrf_token.html" %} + {% include "includes/csrf_token.njk" %}
{{ govukRadios({ classes: "govuk-radios", diff --git a/src/views/router_views/individual_statement/individual_statement.njk b/src/views/router_views/individual_statement/individual_statement.njk index c3935788..0b59991e 100644 --- a/src/views/router_views/individual_statement/individual_statement.njk +++ b/src/views/router_views/individual_statement/individual_statement.njk @@ -21,7 +21,7 @@ {% block main_content %} - {% include "includes/csrf_token.html" %} + {% include "includes/csrf_token.njk" %}
{{ nameAndDateBirthText }}
diff --git a/src/views/router_views/personal_code/personal_code.njk b/src/views/router_views/personal_code/personal_code.njk index a7115c0b..cc90934d 100644 --- a/src/views/router_views/personal_code/personal_code.njk +++ b/src/views/router_views/personal_code/personal_code.njk @@ -16,6 +16,7 @@ {% block main_content %} + {% include "includes/csrf_token.njk" %} {{ nameAndDateBirthText }} diff --git a/src/views/router_views/psc_type/psc_type.njk b/src/views/router_views/psc_type/psc_type.njk index 75182c52..881a5ae6 100644 --- a/src/views/router_views/psc_type/psc_type.njk +++ b/src/views/router_views/psc_type/psc_type.njk @@ -8,7 +8,7 @@ {% block main_content %} - {% include "includes/csrf_token.html" %} + {% include "includes/csrf_token.njk" %} {{ govukRadios({ idPrefix: "pscType", name: "pscType", diff --git a/test/routers/handlers/personal-code/personalCode.int.ts b/test/routers/handlers/personal-code/personalCode.int.ts index 9b00c39a..07382578 100644 --- a/test/routers/handlers/personal-code/personalCode.int.ts +++ b/test/routers/handlers/personal-code/personalCode.int.ts @@ -54,6 +54,7 @@ describe("personal code router/handler integration tests", () => { const uri = getUrlWithTransactionIdAndSubmissionId(uriWithQuery, TRANSACTION_ID, PSC_VERIFICATION_ID); const resp = await request(app).get(uri).expect(HttpStatusCode.Ok); + console.log(resp); const $ = cheerio.load(resp.text); From e76a822eeda9d10b02af322ae1c573e34b183f93 Mon Sep 17 00:00:00 2001 From: Moses Wejuli Date: Thu, 10 Oct 2024 15:18:19 +0100 Subject: [PATCH 3/8] fix: ensure csrf token is readable by the app on form submissions - cleans up folder paths for views in node_modules - modifies comments in app.ts to be more descriptive --- src/app.ts | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/src/app.ts b/src/app.ts index 8e4d9746..2cb30a99 100755 --- a/src/app.ts +++ b/src/app.ts @@ -9,19 +9,16 @@ import routerDispatch from "./routerDispatch"; import { isLive } from "./middleware/serviceLive"; import { csrfProtectionMiddleware } from "./middleware/csrf"; - const app = express(); + +// service availability page app.use(isLive); app.set("views", [ path.join(__dirname, "views"), - path.join(__dirname, "node_modules/govuk-frontend"), - path.join(__dirname, "../node_modules/govuk-frontend"), // This if for when using ts-node since the working directory is src - path.join(__dirname, "node_modules/govuk-frontend/components"), - path.join(__dirname, "../node_modules/@companieshouse/ch-node-utils/templates/"), - path.join(__dirname, "node_modules/@companieshouse/ch-node-utils/templates/"), - path.join(__dirname, "../node_modules/@companieshouse/web-security-node/components"), - path.join(__dirname, "node_modules/@companieshouse/web-security-node/components") + path.join(__dirname, "./../node_modules/govuk-frontend"), // This if for when using ts-node since the working directory is src + path.join(__dirname, "./../node_modules/@companieshouse/ch-node-utils/templates/"), + path.join(__dirname, "./../node_modules/@companieshouse/web-security-node/components") ]); const nunjucksLoaderOpts = { @@ -37,13 +34,21 @@ const njk = new nunjucks.Environment( njk.express(app); app.set("view engine", "njk"); -// apply middleware +// get cookie data from incoming request app.use(cookieParser()); + +// parse incoming payload into req.body +app.use(express.json()); +app.use(express.urlencoded({ extended: false })); + +// initiate session and attach to middleware app.use(servicePathPrefix, sessionMiddleware); + +// attach csrf protection to middleware app.use(csrfProtectionMiddleware); -// Serve static files -app.use(express.static(path.join(__dirname, "/../assets/public"))); +// serve static files +app.use(express.static(path.join(__dirname, "./../assets/public"))); njk.addGlobal("cdnUrlCss", process.env.CDN_URL_CSS); njk.addGlobal("cdnUrlJs", process.env.CDN_URL_JS); @@ -56,29 +61,25 @@ njk.addGlobal("PIWIK_SITE_ID", process.env.PIWIK_SITE_ID); njk.addGlobal("PIWIK_URL", process.env.PIWIK_URL); njk.addGlobal("verifyIdentityLink", process.env.VERIFY_IDENTITY_LINK); -// If app is behind a front-facing proxy, and to use the X-Forwarded-* headers to determine the connection and the IP address of the client +// if app is behind a front-facing proxy, and to use the X-Forwarded-* headers to determine the connection and the IP address of the client app.enable("trust proxy"); -// parse body into req.body -app.use(express.json()); -app.use(express.urlencoded({ extended: false })); - -// Unhandled errors +// unhandled errors app.use((err: any, req: Request, res: Response, next: NextFunction) => { logger.error(`${err.name} - appError: ${err.message} - ${err.stack}`); res.render("partials/error_500"); }); -// Channel all requests through router dispatch +// channel all requests through router dispatch routerDispatch(app); -// Unhandled exceptions +// unhandled exceptions process.on("uncaughtException", (err: any) => { logger.error(`${err.name} - uncaughtException: ${err.message} - ${err.stack}`); process.exit(1); }); -// Unhandled promise rejections +// unhandled promise rejections process.on("unhandledRejection", (err: any) => { logger.error(`${err.name} - unhandledRejection: ${err.message} - ${err.stack}`); process.exit(1); From 4f85ee5ceadf036ab218fdec422f438b2bd952c7 Mon Sep 17 00:00:00 2001 From: PhilipGlover Date: Fri, 11 Oct 2024 15:26:31 +0100 Subject: [PATCH 4/8] add CSRF Error screen from web-security-node --- src/app.ts | 2 ++ src/middleware/csrfError.ts | 22 ++++++++++++++++++++++ src/views/403.njk | 26 ++++++++++++++++++++++++++ 3 files changed, 50 insertions(+) create mode 100644 src/middleware/csrfError.ts create mode 100644 src/views/403.njk diff --git a/src/app.ts b/src/app.ts index 2cb30a99..0a02ac45 100755 --- a/src/app.ts +++ b/src/app.ts @@ -8,6 +8,7 @@ import { sessionMiddleware } from "./middleware/session"; import routerDispatch from "./routerDispatch"; import { isLive } from "./middleware/serviceLive"; import { csrfProtectionMiddleware } from "./middleware/csrf"; +import csrfErrorHandler from "./middleware/csrfError"; const app = express(); @@ -46,6 +47,7 @@ app.use(servicePathPrefix, sessionMiddleware); // attach csrf protection to middleware app.use(csrfProtectionMiddleware); +app.use(csrfErrorHandler); // serve static files app.use(express.static(path.join(__dirname, "./../assets/public"))); diff --git a/src/middleware/csrfError.ts b/src/middleware/csrfError.ts new file mode 100644 index 00000000..21140ca2 --- /dev/null +++ b/src/middleware/csrfError.ts @@ -0,0 +1,22 @@ +import { NextFunction, Request, Response } from "express"; +import { CsrfError } from "@companieshouse/web-security-node"; +import { StatusCodes } from "http-status-codes"; + +const csrfErrorTemplateName = "403"; + +const csrfErrorHandler = ( + err: CsrfError | Error, + _: Request, + res: Response, + next: NextFunction +) => { + if (!(err instanceof CsrfError)) { + return next(err); + } + + return res.status(StatusCodes.FORBIDDEN).render(csrfErrorTemplateName, { + csrfErrors: true + }); +}; + +export default csrfErrorHandler; diff --git a/src/views/403.njk b/src/views/403.njk new file mode 100644 index 00000000..3f3e75ef --- /dev/null +++ b/src/views/403.njk @@ -0,0 +1,26 @@ +{% extends "layouts/default.njk" %} +{% from "csrf-error/macro.njk" import csrfError %} + +{% set title = "Forbidden" %} + +{% if errors and errors.errorList and errors.errorList.length > 0 %} +Error: +{% endif %} +{{ title }} - {{ "Provide identity verification details for a PSC or relevant legal entity" }} + +{% block main_content %} + {% if csrfErrors %} + {{ + csrfError({}) + }} + {% else %} +
+
+

Sorry, the service can not be accessed

+ +

Email enquiries@companieshouse.gov.uk if you need more information.

+
+
+ {% endif %} + +{% endblock %} \ No newline at end of file From 8306d70d9d3663322796206085f129a45c44aedd Mon Sep 17 00:00:00 2001 From: Simon Boyd Date: Wed, 16 Oct 2024 14:42:13 +0100 Subject: [PATCH 5/8] apply CSRF on all POST routes - fix some failing tests - WIP on csrfError test (failing) --- src/app.ts | 6 -- src/routerDispatch.ts | 12 ++-- test/app.int.ts | 4 ++ test/authentication/csrfError.int.ts | 66 +++++++++++++++++++ test/routers/confirmCompany.int.ts | 4 ++ .../individualStatement.int.ts | 2 + .../personal-code/personalCode.int.ts | 4 ++ test/routers/pscType.int.ts | 4 ++ 8 files changed, 91 insertions(+), 11 deletions(-) create mode 100644 test/authentication/csrfError.int.ts diff --git a/src/app.ts b/src/app.ts index 0a02ac45..7eac4c57 100755 --- a/src/app.ts +++ b/src/app.ts @@ -7,8 +7,6 @@ import { logger } from "./lib/logger"; import { sessionMiddleware } from "./middleware/session"; import routerDispatch from "./routerDispatch"; import { isLive } from "./middleware/serviceLive"; -import { csrfProtectionMiddleware } from "./middleware/csrf"; -import csrfErrorHandler from "./middleware/csrfError"; const app = express(); @@ -45,10 +43,6 @@ app.use(express.urlencoded({ extended: false })); // initiate session and attach to middleware app.use(servicePathPrefix, sessionMiddleware); -// attach csrf protection to middleware -app.use(csrfProtectionMiddleware); -app.use(csrfErrorHandler); - // serve static files app.use(express.static(path.join(__dirname, "./../assets/public"))); diff --git a/src/routerDispatch.ts b/src/routerDispatch.ts index 4cad305e..f8ec5da7 100644 --- a/src/routerDispatch.ts +++ b/src/routerDispatch.ts @@ -3,6 +3,8 @@ import { Application, Request, Response, Router } from "express"; import { Urls, servicePathPrefix } from "./constants"; import { CompanyNumberRouter, ConfirmCompanyRouter, ConfirmRoStatementsRouter, IndividualPscListRouter, IndividualStatementRouter, NewSubmissionRouter, NotADirectorRouter, PersonalCodeRouter, PscTypeRouter, PscVerifiedRouter, RleDetailsRouter, RleDirectorRouter, RlePscListRouter, RleVerifiedRouter, StartRouter } from "./routers/utils"; import { authenticate } from "./middleware/authentication"; +import { csrfProtectionMiddleware } from "./middleware/csrf"; +import csrfErrorHandler from "./middleware/csrfError"; import { fetchVerification } from "./middleware/fetchVerification"; import { fetchCompany } from "./middleware/fetchCompany"; @@ -15,12 +17,12 @@ const routerDispatch = (app: Application) => { router.use("/", StartRouter); router.use(Urls.START, StartRouter); router.use(Urls.COMPANY_NUMBER, authenticate, CompanyNumberRouter); - router.use(Urls.CONFIRM_COMPANY, authenticate, ConfirmCompanyRouter); + router.use(Urls.CONFIRM_COMPANY, csrfProtectionMiddleware, csrfErrorHandler, authenticate, ConfirmCompanyRouter); router.use(Urls.NEW_SUBMISSION, authenticate, NewSubmissionRouter); - router.use(Urls.PSC_TYPE, authenticate, fetchVerification, PscTypeRouter); - router.use(Urls.INDIVIDUAL_PSC_LIST, authenticate, fetchVerification, fetchCompany, IndividualPscListRouter); - router.use(Urls.PERSONAL_CODE, authenticate, fetchVerification, PersonalCodeRouter); - router.use(Urls.INDIVIDUAL_STATEMENT, authenticate, fetchVerification, IndividualStatementRouter); + router.use(Urls.PSC_TYPE, csrfProtectionMiddleware, csrfErrorHandler, authenticate, fetchVerification, PscTypeRouter); + router.use(Urls.INDIVIDUAL_PSC_LIST, csrfProtectionMiddleware, csrfErrorHandler, authenticate, fetchVerification, fetchCompany, IndividualPscListRouter); + router.use(Urls.PERSONAL_CODE, csrfProtectionMiddleware, csrfErrorHandler, authenticate, fetchVerification, PersonalCodeRouter); + router.use(Urls.INDIVIDUAL_STATEMENT, csrfProtectionMiddleware, csrfErrorHandler, authenticate, fetchVerification, IndividualStatementRouter); router.use(Urls.PSC_VERIFIED, authenticate, fetchVerification, fetchCompany, PscVerifiedRouter); router.use(Urls.RLE_LIST, authenticate, RlePscListRouter); router.use(Urls.RLE_DETAILS, authenticate, RleDetailsRouter); diff --git a/test/app.int.ts b/test/app.int.ts index 54630a88..920207bb 100644 --- a/test/app.int.ts +++ b/test/app.int.ts @@ -4,6 +4,7 @@ import request from "supertest"; import app from "../src/app"; import * as config from "../src/config"; import { servicePathPrefix } from "../src/constants"; +import mockCsrfProtectionMiddleware from "./mocks/csrfProtectionMiddleware.mock"; jest.mock("ioredis"); jest.mock("../src/config", () => ({ @@ -31,6 +32,9 @@ const mockConfig = config as { env: { }}; describe("Service not live integration tests", () => { + beforeEach(() => { + mockCsrfProtectionMiddleware.mockClear(); + }); it("should render the Service not live page when SERVICE_LEVEL is false", async () => { mockConfig.env.SERVICE_LIVE = "false"; diff --git a/test/authentication/csrfError.int.ts b/test/authentication/csrfError.int.ts new file mode 100644 index 00000000..bc9a5873 --- /dev/null +++ b/test/authentication/csrfError.int.ts @@ -0,0 +1,66 @@ +import request from "supertest"; +import { HttpStatusCode } from "axios"; +import { PrefixedUrls } from ".../../../src/constants"; +import mockCsrfProtectionMiddleware from "../mocks/csrfProtectionMiddleware.mock"; +import { PscVerification } from "@companieshouse/api-sdk-node/dist/services/psc-verification-link/types"; +import Resource from "@companieshouse/api-sdk-node/dist/services/resource"; +import { createOAuthApiClient } from "../../src/services/apiClientService"; +import { COMPANY_NUMBER, INDIVIDUAL_VERIFICATION_CREATED, PSC_VERIFICATION_ID, TRANSACTION_ID } from "../mocks/pscVerification.mock"; +import app from ".../../../src/app"; +import { getUrlWithTransactionIdAndSubmissionId } from "../../src/utils/url"; + +jest.mock(".../../../src/services/companyProfileService"); +jest.mock("../../src/services/apiClientService"); + +const mockCreatePscVerification = jest.fn(); +const mockGetPscVerification = jest.fn(); +const mockCreateOAuthApiClient = createOAuthApiClient as jest.Mock; + +mockCreateOAuthApiClient.mockReturnValue({ + pscVerificationService: { + postPscVerification: mockCreatePscVerification, + getPscVerification: mockGetPscVerification + } +}); +const mockCreate: Resource = { + httpStatusCode: HttpStatusCode.Created, + resource: INDIVIDUAL_VERIFICATION_CREATED +}; +const mockGet: Resource = { + httpStatusCode: HttpStatusCode.Ok, + resource: INDIVIDUAL_VERIFICATION_CREATED +}; +mockCreatePscVerification.mockResolvedValueOnce(mockCreate); +mockGetPscVerification.mockResolvedValueOnce(mockGet); + +describe("CSRF violation handling", () => { + beforeAll(() => { + mockCsrfProtectionMiddleware.mockClear(); + }); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it.skip.each([PrefixedUrls.CONFIRM_COMPANY, + PrefixedUrls.PSC_TYPE, + PrefixedUrls.INDIVIDUAL_PSC_LIST, + PrefixedUrls.INDIVIDUAL_STATEMENT, + PrefixedUrls.PERSONAL_CODE])("Should fail missing CSRF token when posting to '%s'", async (url) => { + + const queryParams = new URLSearchParams(`companyNumber=${COMPANY_NUMBER}&lang=en`); + const uriWithQuery = `${url}?${queryParams}`; + const uri = getUrlWithTransactionIdAndSubmissionId(uriWithQuery, TRANSACTION_ID, PSC_VERIFICATION_ID); + const data = { lang: "en", companyNumber: `${COMPANY_NUMBER}` }; + + const response = await request(app) + .post(uri) + .send(data) + .set("Content-Type", "application/json") + .set("Accept", "application/json"); + + expect(response.status).toEqual(403); + expect(response.text).toContain("Sorry, the service can not be accessed"); + }); + +}); diff --git a/test/routers/confirmCompany.int.ts b/test/routers/confirmCompany.int.ts index bd920156..faab2867 100644 --- a/test/routers/confirmCompany.int.ts +++ b/test/routers/confirmCompany.int.ts @@ -14,6 +14,10 @@ mockGetCompanyProfile.mockResolvedValue(validCompanyProfile); describe("ConfirmCompany router/handler integration tests", () => { + beforeAll(() => { + // middlewareMocks.mockCsrfProtectionMiddleware.mockClear(); + }); + beforeEach(() => { middlewareMocks.mockSessionMiddleware.mockClear(); }); diff --git a/test/routers/handlers/individual-statement/individualStatement.int.ts b/test/routers/handlers/individual-statement/individualStatement.int.ts index 4e574e77..879257f6 100644 --- a/test/routers/handlers/individual-statement/individualStatement.int.ts +++ b/test/routers/handlers/individual-statement/individualStatement.int.ts @@ -4,6 +4,7 @@ import request from "supertest"; import { URLSearchParams } from "url"; import mockSessionMiddleware from "../../../mocks/sessionMiddleware.mock"; import mockAuthenticationMiddleware from "../../../mocks/authenticationMiddleware.mock"; +import mockCsrfProtectionMiddleware from "../../../mocks/csrfProtectionMiddleware.mock"; import { PrefixedUrls } from "../../../../src/constants"; import { getUrlWithTransactionIdAndSubmissionId } from "../../../../src/utils/url"; import { PSC_INDIVIDUAL } from "../../../mocks/psc.mock"; @@ -33,6 +34,7 @@ describe("individual statement view", () => { beforeEach(() => { mockSessionMiddleware.mockClear(); mockAuthenticationMiddleware.mockClear(); + mockCsrfProtectionMiddleware.mockClear(); }); afterEach(() => { diff --git a/test/routers/handlers/personal-code/personalCode.int.ts b/test/routers/handlers/personal-code/personalCode.int.ts index 07382578..eb0ec833 100644 --- a/test/routers/handlers/personal-code/personalCode.int.ts +++ b/test/routers/handlers/personal-code/personalCode.int.ts @@ -3,6 +3,7 @@ import request from "supertest"; import * as cheerio from "cheerio"; import mockSessionMiddleware from "../../../mocks/sessionMiddleware.mock"; import mockAuthenticationMiddleware from "../../../mocks/authenticationMiddleware.mock"; +import mockCsrfProtectionMiddleware from "../../../mocks/csrfProtectionMiddleware.mock"; import { PrefixedUrls } from "../../../../src/constants"; import { getUrlWithTransactionIdAndSubmissionId } from "../../../../src/utils/url"; import { PSC_INDIVIDUAL } from "../../../mocks/psc.mock"; @@ -21,6 +22,9 @@ const mockPatchPscVerification = patchPscVerification as jest.Mock; const mockGetPscIndividual = getPscIndividual as jest.Mock; describe("personal code router/handler integration tests", () => { + beforeAll(() => { + mockCsrfProtectionMiddleware.mockClear(); + }); beforeEach(() => { jest.clearAllMocks(); diff --git a/test/routers/pscType.int.ts b/test/routers/pscType.int.ts index cdad21be..fa4918fd 100644 --- a/test/routers/pscType.int.ts +++ b/test/routers/pscType.int.ts @@ -2,6 +2,7 @@ import * as cheerio from "cheerio"; import { HttpStatusCode } from "axios"; import mockAuthenticationMiddleware from "../mocks/authenticationMiddleware.mock"; import mockSessionMiddleware from "../mocks/sessionMiddleware.mock"; +import mockCsrfProtectionMiddleware from "../mocks/csrfProtectionMiddleware.mock"; import { PrefixedUrls } from "../../src/constants"; import request from "supertest"; import app from "../../src/app"; @@ -14,6 +15,9 @@ jest.mock("../../src/services/pscVerificationService"); const mockGetPscVerification = getPscVerification as jest.Mock; describe("PscType router/handler integration tests", () => { + beforeAll(() => { + mockCsrfProtectionMiddleware.mockClear(); + }); beforeEach(() => { jest.clearAllMocks(); From 965deed54d685e6f484453df759d35e095ecb2cd Mon Sep 17 00:00:00 2001 From: Simon Boyd Date: Fri, 18 Oct 2024 08:47:00 +0100 Subject: [PATCH 6/8] Move CSRF middleware to app (all routes) - move CSRF middleware to app.ts from routerDispatch.ts - fix tests affected - simplify CSRF Error page test - move 403.njk to views/error --- src/app.ts | 6 ++ src/middleware/csrfError.ts | 2 +- src/routerDispatch.ts | 12 ++-- src/views/{ => error}/403.njk | 0 test/app.int.ts | 2 +- test/authentication/csrfError.int.ts | 63 +++++-------------- .../handlers/psc-verified/pscVerified.int.ts | 2 + test/routers/newSubmission.int.ts | 2 + 8 files changed, 32 insertions(+), 57 deletions(-) rename src/views/{ => error}/403.njk (100%) diff --git a/src/app.ts b/src/app.ts index 7eac4c57..0a02ac45 100755 --- a/src/app.ts +++ b/src/app.ts @@ -7,6 +7,8 @@ import { logger } from "./lib/logger"; import { sessionMiddleware } from "./middleware/session"; import routerDispatch from "./routerDispatch"; import { isLive } from "./middleware/serviceLive"; +import { csrfProtectionMiddleware } from "./middleware/csrf"; +import csrfErrorHandler from "./middleware/csrfError"; const app = express(); @@ -43,6 +45,10 @@ app.use(express.urlencoded({ extended: false })); // initiate session and attach to middleware app.use(servicePathPrefix, sessionMiddleware); +// attach csrf protection to middleware +app.use(csrfProtectionMiddleware); +app.use(csrfErrorHandler); + // serve static files app.use(express.static(path.join(__dirname, "./../assets/public"))); diff --git a/src/middleware/csrfError.ts b/src/middleware/csrfError.ts index 21140ca2..1cc5c67d 100644 --- a/src/middleware/csrfError.ts +++ b/src/middleware/csrfError.ts @@ -2,7 +2,7 @@ import { NextFunction, Request, Response } from "express"; import { CsrfError } from "@companieshouse/web-security-node"; import { StatusCodes } from "http-status-codes"; -const csrfErrorTemplateName = "403"; +const csrfErrorTemplateName = "error/403"; const csrfErrorHandler = ( err: CsrfError | Error, diff --git a/src/routerDispatch.ts b/src/routerDispatch.ts index f8ec5da7..4cad305e 100644 --- a/src/routerDispatch.ts +++ b/src/routerDispatch.ts @@ -3,8 +3,6 @@ import { Application, Request, Response, Router } from "express"; import { Urls, servicePathPrefix } from "./constants"; import { CompanyNumberRouter, ConfirmCompanyRouter, ConfirmRoStatementsRouter, IndividualPscListRouter, IndividualStatementRouter, NewSubmissionRouter, NotADirectorRouter, PersonalCodeRouter, PscTypeRouter, PscVerifiedRouter, RleDetailsRouter, RleDirectorRouter, RlePscListRouter, RleVerifiedRouter, StartRouter } from "./routers/utils"; import { authenticate } from "./middleware/authentication"; -import { csrfProtectionMiddleware } from "./middleware/csrf"; -import csrfErrorHandler from "./middleware/csrfError"; import { fetchVerification } from "./middleware/fetchVerification"; import { fetchCompany } from "./middleware/fetchCompany"; @@ -17,12 +15,12 @@ const routerDispatch = (app: Application) => { router.use("/", StartRouter); router.use(Urls.START, StartRouter); router.use(Urls.COMPANY_NUMBER, authenticate, CompanyNumberRouter); - router.use(Urls.CONFIRM_COMPANY, csrfProtectionMiddleware, csrfErrorHandler, authenticate, ConfirmCompanyRouter); + router.use(Urls.CONFIRM_COMPANY, authenticate, ConfirmCompanyRouter); router.use(Urls.NEW_SUBMISSION, authenticate, NewSubmissionRouter); - router.use(Urls.PSC_TYPE, csrfProtectionMiddleware, csrfErrorHandler, authenticate, fetchVerification, PscTypeRouter); - router.use(Urls.INDIVIDUAL_PSC_LIST, csrfProtectionMiddleware, csrfErrorHandler, authenticate, fetchVerification, fetchCompany, IndividualPscListRouter); - router.use(Urls.PERSONAL_CODE, csrfProtectionMiddleware, csrfErrorHandler, authenticate, fetchVerification, PersonalCodeRouter); - router.use(Urls.INDIVIDUAL_STATEMENT, csrfProtectionMiddleware, csrfErrorHandler, authenticate, fetchVerification, IndividualStatementRouter); + router.use(Urls.PSC_TYPE, authenticate, fetchVerification, PscTypeRouter); + router.use(Urls.INDIVIDUAL_PSC_LIST, authenticate, fetchVerification, fetchCompany, IndividualPscListRouter); + router.use(Urls.PERSONAL_CODE, authenticate, fetchVerification, PersonalCodeRouter); + router.use(Urls.INDIVIDUAL_STATEMENT, authenticate, fetchVerification, IndividualStatementRouter); router.use(Urls.PSC_VERIFIED, authenticate, fetchVerification, fetchCompany, PscVerifiedRouter); router.use(Urls.RLE_LIST, authenticate, RlePscListRouter); router.use(Urls.RLE_DETAILS, authenticate, RleDetailsRouter); diff --git a/src/views/403.njk b/src/views/error/403.njk similarity index 100% rename from src/views/403.njk rename to src/views/error/403.njk diff --git a/test/app.int.ts b/test/app.int.ts index 920207bb..6b3e2542 100644 --- a/test/app.int.ts +++ b/test/app.int.ts @@ -1,10 +1,10 @@ import { HttpStatusCode } from "axios"; import * as cheerio from "cheerio"; import request from "supertest"; +import mockCsrfProtectionMiddleware from "./mocks/csrfProtectionMiddleware.mock"; import app from "../src/app"; import * as config from "../src/config"; import { servicePathPrefix } from "../src/constants"; -import mockCsrfProtectionMiddleware from "./mocks/csrfProtectionMiddleware.mock"; jest.mock("ioredis"); jest.mock("../src/config", () => ({ diff --git a/test/authentication/csrfError.int.ts b/test/authentication/csrfError.int.ts index bc9a5873..674cb04f 100644 --- a/test/authentication/csrfError.int.ts +++ b/test/authentication/csrfError.int.ts @@ -1,66 +1,33 @@ import request from "supertest"; +import * as cheerio from "cheerio"; import { HttpStatusCode } from "axios"; import { PrefixedUrls } from ".../../../src/constants"; -import mockCsrfProtectionMiddleware from "../mocks/csrfProtectionMiddleware.mock"; -import { PscVerification } from "@companieshouse/api-sdk-node/dist/services/psc-verification-link/types"; -import Resource from "@companieshouse/api-sdk-node/dist/services/resource"; -import { createOAuthApiClient } from "../../src/services/apiClientService"; -import { COMPANY_NUMBER, INDIVIDUAL_VERIFICATION_CREATED, PSC_VERIFICATION_ID, TRANSACTION_ID } from "../mocks/pscVerification.mock"; +import mockSessionMiddleware from "../mocks/sessionMiddleware.mock"; +import mockAuthenticationMiddleware from "../mocks/authenticationMiddleware.mock"; +import { csrfProtectionMiddleware } from "../../src/middleware/csrf"; import app from ".../../../src/app"; -import { getUrlWithTransactionIdAndSubmissionId } from "../../src/utils/url"; +import { CsrfError } from "@companieshouse/web-security-node"; -jest.mock(".../../../src/services/companyProfileService"); -jest.mock("../../src/services/apiClientService"); +jest.mock("../../src/middleware/csrf"); -const mockCreatePscVerification = jest.fn(); -const mockGetPscVerification = jest.fn(); -const mockCreateOAuthApiClient = createOAuthApiClient as jest.Mock; - -mockCreateOAuthApiClient.mockReturnValue({ - pscVerificationService: { - postPscVerification: mockCreatePscVerification, - getPscVerification: mockGetPscVerification - } -}); -const mockCreate: Resource = { - httpStatusCode: HttpStatusCode.Created, - resource: INDIVIDUAL_VERIFICATION_CREATED -}; -const mockGet: Resource = { - httpStatusCode: HttpStatusCode.Ok, - resource: INDIVIDUAL_VERIFICATION_CREATED -}; -mockCreatePscVerification.mockResolvedValueOnce(mockCreate); -mockGetPscVerification.mockResolvedValueOnce(mockGet); +const mockCsrfThrowingMiddleware = csrfProtectionMiddleware as jest.Mock; describe("CSRF violation handling", () => { - beforeAll(() => { - mockCsrfProtectionMiddleware.mockClear(); - }); beforeEach(() => { - jest.clearAllMocks(); + mockAuthenticationMiddleware.mockClear(); + mockSessionMiddleware.mockClear(); }); - it.skip.each([PrefixedUrls.CONFIRM_COMPANY, - PrefixedUrls.PSC_TYPE, - PrefixedUrls.INDIVIDUAL_PSC_LIST, - PrefixedUrls.INDIVIDUAL_STATEMENT, - PrefixedUrls.PERSONAL_CODE])("Should fail missing CSRF token when posting to '%s'", async (url) => { - - const queryParams = new URLSearchParams(`companyNumber=${COMPANY_NUMBER}&lang=en`); - const uriWithQuery = `${url}?${queryParams}`; - const uri = getUrlWithTransactionIdAndSubmissionId(uriWithQuery, TRANSACTION_ID, PSC_VERIFICATION_ID); - const data = { lang: "en", companyNumber: `${COMPANY_NUMBER}` }; + it("Should render the CSRF error page", async () => { + mockCsrfThrowingMiddleware.mockImplementation(() => { throw new CsrfError("CSRF token mismatch"); }); const response = await request(app) - .post(uri) - .send(data) - .set("Content-Type", "application/json") - .set("Accept", "application/json"); + .get(PrefixedUrls.START); + const $ = cheerio.load(response.text); - expect(response.status).toEqual(403); - expect(response.text).toContain("Sorry, the service can not be accessed"); + expect(response.status).toBe(HttpStatusCode.Forbidden); + expect($("h1.govuk-heading-l").text()).toMatch("something went wrong"); }); }); diff --git a/test/routers/handlers/psc-verified/pscVerified.int.ts b/test/routers/handlers/psc-verified/pscVerified.int.ts index 5fd9ed60..0c916389 100644 --- a/test/routers/handlers/psc-verified/pscVerified.int.ts +++ b/test/routers/handlers/psc-verified/pscVerified.int.ts @@ -2,6 +2,7 @@ import { HttpStatusCode } from "axios"; import request from "supertest"; import mockSessionMiddleware from "../../../mocks/sessionMiddleware.mock"; import mockAuthenticationMiddleware from "../../../mocks/authenticationMiddleware.mock"; +import mockCsrfProtectionMiddleware from "../../../mocks/csrfProtectionMiddleware.mock"; import app from "../../../../src/app"; import { PrefixedUrls } from "../../../../src/constants"; import { getCompanyProfile } from "../../../../src/services/companyProfileService"; @@ -42,6 +43,7 @@ describe("psc verified view tests", () => { beforeEach(() => { jest.clearAllMocks(); + mockCsrfProtectionMiddleware.mockClear(); }); afterEach(() => { diff --git a/test/routers/newSubmission.int.ts b/test/routers/newSubmission.int.ts index 9deeb0c7..f8c27fa6 100644 --- a/test/routers/newSubmission.int.ts +++ b/test/routers/newSubmission.int.ts @@ -2,6 +2,7 @@ import { HttpStatusCode } from "axios"; import request from "supertest"; import mockSessionMiddleware from "../mocks/sessionMiddleware.mock"; import mockAuthenticationMiddleware from "../mocks/authenticationMiddleware.mock"; +import mockCsrfProtectionMiddleware from "../mocks/csrfProtectionMiddleware.mock"; import app from "../../src/app"; import { PrefixedUrls } from "../../src/constants"; import { postTransaction } from "../../src/services/transactionService"; @@ -25,6 +26,7 @@ describe("NewSubmission router/handler integration tests", () => { beforeEach(() => { jest.clearAllMocks(); + mockCsrfProtectionMiddleware.mockClear(); }); afterEach(() => { From dac38cd99e1f35b3cdf2aecb1603311cdb8fd4b7 Mon Sep 17 00:00:00 2001 From: Simon Boyd Date: Fri, 18 Oct 2024 09:32:37 +0100 Subject: [PATCH 7/8] Update packages to latest minor version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - @companieshouse/ch-node-utils ^1.3.11 → ^1.3.12 - @companieshouse/web-security-node ^4.3.1 → ^4.4.0 - cookie-parser 1.4.6 → 1.4.7 - express ^4.21.0 → ^4.21.1 - govuk-frontend ^4.8.0 → ^4.9.0 - sass 1.79.4 → 1.80.2 - tslib ^2.7.0 → ^2.8.0 --- package-lock.json | 408 ++++++++++++++++++++++++++++++++++++++++++---- package.json | 14 +- 2 files changed, 385 insertions(+), 37 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6bb6f86e..e6a56ccb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,24 +10,24 @@ "license": "MIT", "dependencies": { "@companieshouse/api-sdk-node": "^2.0.209", - "@companieshouse/ch-node-utils": "^1.3.11", + "@companieshouse/ch-node-utils": "^1.3.12", "@companieshouse/node-session-handler": "^5.1.4", "@companieshouse/structured-logging-node": "^2.0.1", - "@companieshouse/web-security-node": "^4.3.1", + "@companieshouse/web-security-node": "^4.4.0", "@types/supertest": "^6.0.2", "axios": "^1.7.7", - "cookie-parser": "1.4.6", - "express": "^4.21.0", + "cookie-parser": "1.4.7", + "express": "^4.21.1", "govuk_frontend_toolkit": "^9.0.1", "govuk-elements-sass": "^3.1.3", - "govuk-frontend": "^4.8.0", + "govuk-frontend": "^4.9.0", "http-errors": "^1.8.1", "ioredis": "4.28.5", "js-yaml": "^3.14.1", "luxon": "^3.5.0", "nunjucks": "3.2.4", "sonarqube-scanner": "^3.5.0", - "tslib": "^2.7.0", + "tslib": "^2.8.0", "uuid": "8.3.2", "yargs": "17.7.2" }, @@ -67,7 +67,7 @@ "node-mocks-http": "^1.16.1", "nodemon": "^3.1.7", "nyc": "^15.1.0", - "sass": "1.79.4", + "sass": "1.80.2", "supertest": "^6.3.4", "ts-jest": "^29.2.5", "ts-node": "8.10.2", @@ -707,19 +707,53 @@ } }, "node_modules/@companieshouse/ch-node-utils": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@companieshouse/ch-node-utils/-/ch-node-utils-1.3.11.tgz", - "integrity": "sha512-rwUA9D3i1cpKwJ6lP1bw0AMSj1exqxRVA3ltOBVKUkseRSyKScHEXf/67k8Sv1HOQVr8939J0HZlLkwf47vgnA==", + "version": "1.3.12", + "resolved": "https://registry.npmjs.org/@companieshouse/ch-node-utils/-/ch-node-utils-1.3.12.tgz", + "integrity": "sha512-UhYyWd6J5x+eSuKn35Trvny683ypknJ/AR3cwqNryFdoC64dWJsVUfIA6rlobFESuM1mLHYgTcDQjAFD/kx7Zw==", "license": "MIT", "dependencies": { - "@companieshouse/node-session-handler": "^5.0.1", + "@companieshouse/node-session-handler": "^5.1.4", "express": "^4.18.3", "i18next": "^23.10.1", "i18next-fs-backend": "^2.3.1", + "ioredis": "^5.4.1", "iso-639-1": "^3.1.2", "tslib": "^2.3.0" } }, + "node_modules/@companieshouse/ch-node-utils/node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/@companieshouse/ch-node-utils/node_modules/ioredis": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.4.1.tgz", + "integrity": "sha512-2YZsvl7jopIa1gaePkeMtd9rAcSjOOjPtpcLlOeusyO+XH2SK5ZcT+UCrElPP+WVIInh2TzeI4XW9ENaSLVVHA==", + "license": "MIT", + "dependencies": { + "@ioredis/commands": "^1.1.1", + "cluster-key-slot": "^1.1.0", + "debug": "^4.3.4", + "denque": "^2.1.0", + "lodash.defaults": "^4.2.0", + "lodash.isarguments": "^3.1.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0", + "standard-as-callback": "^2.1.0" + }, + "engines": { + "node": ">=12.22.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ioredis" + } + }, "node_modules/@companieshouse/node-session-handler": { "version": "5.1.4", "resolved": "https://registry.npmjs.org/@companieshouse/node-session-handler/-/node-session-handler-5.1.4.tgz", @@ -755,9 +789,9 @@ } }, "node_modules/@companieshouse/web-security-node": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@companieshouse/web-security-node/-/web-security-node-4.3.1.tgz", - "integrity": "sha512-sQhbApcY5a5K8eSHdnPDiyY5q4DiMF/j6Q3tsaHx4yJs5264JDk3aFcPr0ZhcePBB7kVnekGg1idvPdN0TZcvQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@companieshouse/web-security-node/-/web-security-node-4.4.0.tgz", + "integrity": "sha512-JF7Oi+ljrVLhpkGgQdN4tV58IDw1Vn41wtYJxD+QkyVq5Ll+/W8RtcCR8Sdc2ugiDqd3DpxqGWyt9fhIRz4iyQ==", "license": "MIT", "dependencies": { "@companieshouse/node-session-handler": "~5.1.3", @@ -994,6 +1028,12 @@ "dev": true, "license": "BSD-3-Clause" }, + "node_modules/@ioredis/commands": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", + "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==", + "license": "MIT" + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -1557,6 +1597,292 @@ "node": ">= 8" } }, + "node_modules/@parcel/watcher": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.4.1.tgz", + "integrity": "sha512-HNjmfLQEVRZmHRET336f20H/8kOozUGwk7yajvsonjNxbj2wBTK1WsQuHkD5yYh9RxFGL2EyDHryOihOwUoKDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "detect-libc": "^1.0.3", + "is-glob": "^4.0.3", + "micromatch": "^4.0.5", + "node-addon-api": "^7.0.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.4.1", + "@parcel/watcher-darwin-arm64": "2.4.1", + "@parcel/watcher-darwin-x64": "2.4.1", + "@parcel/watcher-freebsd-x64": "2.4.1", + "@parcel/watcher-linux-arm-glibc": "2.4.1", + "@parcel/watcher-linux-arm64-glibc": "2.4.1", + "@parcel/watcher-linux-arm64-musl": "2.4.1", + "@parcel/watcher-linux-x64-glibc": "2.4.1", + "@parcel/watcher-linux-x64-musl": "2.4.1", + "@parcel/watcher-win32-arm64": "2.4.1", + "@parcel/watcher-win32-ia32": "2.4.1", + "@parcel/watcher-win32-x64": "2.4.1" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.4.1.tgz", + "integrity": "sha512-LOi/WTbbh3aTn2RYddrO8pnapixAziFl6SMxHM69r3tvdSm94JtCenaKgk1GRg5FJ5wpMCpHeW+7yqPlvZv7kg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.4.1.tgz", + "integrity": "sha512-ln41eihm5YXIY043vBrrHfn94SIBlqOWmoROhsMVTSXGh0QahKGy77tfEywQ7v3NywyxBBkGIfrWRHm0hsKtzA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.4.1.tgz", + "integrity": "sha512-yrw81BRLjjtHyDu7J61oPuSoeYWR3lDElcPGJyOvIXmor6DEo7/G2u1o7I38cwlcoBHQFULqF6nesIX3tsEXMg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.4.1.tgz", + "integrity": "sha512-TJa3Pex/gX3CWIx/Co8k+ykNdDCLx+TuZj3f3h7eOjgpdKM+Mnix37RYsYU4LHhiYJz3DK5nFCCra81p6g050w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.4.1.tgz", + "integrity": "sha512-4rVYDlsMEYfa537BRXxJ5UF4ddNwnr2/1O4MHM5PjI9cvV2qymvhwZSFgXqbS8YoTk5i/JR0L0JDs69BUn45YA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.4.1.tgz", + "integrity": "sha512-BJ7mH985OADVLpbrzCLgrJ3TOpiZggE9FMblfO65PlOCdG++xJpKUJ0Aol74ZUIYfb8WsRlUdgrZxKkz3zXWYA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.4.1.tgz", + "integrity": "sha512-p4Xb7JGq3MLgAfYhslU2SjoV9G0kI0Xry0kuxeG/41UfpjHGOhv7UoUDAz/jb1u2elbhazy4rRBL8PegPJFBhA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.4.1.tgz", + "integrity": "sha512-s9O3fByZ/2pyYDPoLM6zt92yu6P4E39a03zvO0qCHOTjxmt3GHRMLuRZEWhWLASTMSrrnVNWdVI/+pUElJBBBg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.4.1.tgz", + "integrity": "sha512-L2nZTYR1myLNST0O632g0Dx9LyMNHrn6TOt76sYxWLdff3cB22/GZX2UPtJnaqQPdCRoszoY5rcOj4oMTtp5fQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.4.1.tgz", + "integrity": "sha512-Uq2BPp5GWhrq/lcuItCHoqxjULU1QYEcyjSO5jqqOK8RNFDBQnenMMx4gAl3v8GiWa59E9+uDM7yZ6LxwUIfRg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.4.1.tgz", + "integrity": "sha512-maNRit5QQV2kgHFSYwftmPBxiuK5u4DXjbXx7q6eKjq5dsLXZ4FJiVvlcw35QXzk0KrUecJmuVFbj4uV9oYrcw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.4.1.tgz", + "integrity": "sha512-+DvS92F9ezicfswqrvIRM2njcYJbd5mb9CUgtrHCHmvn7pPPa+nMDRu1o1bYYz/l5IB2NVGNJWiH7h1E58IF2A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, "node_modules/@rtsao/scc": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", @@ -3475,21 +3801,21 @@ "dev": true }, "node_modules/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/cookie-parser": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", - "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz", + "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==", "license": "MIT", "dependencies": { - "cookie": "0.4.1", + "cookie": "0.7.2", "cookie-signature": "1.0.6" }, "engines": { @@ -3930,6 +4256,19 @@ "node": ">=0.10.0" } }, + "node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -5932,9 +6271,10 @@ "integrity": "sha512-BlJsYnC0HJomBNCiBm2oQCqgbvP7vaA06XyJ2NocpWM4vFcK/AxAC/7gAU6iCjP3LVhyobR+o2MTFFGozPIE6A==" }, "node_modules/govuk-frontend": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/govuk-frontend/-/govuk-frontend-4.8.0.tgz", - "integrity": "sha512-NOmPJxL8IYq1HSNHYKx9XY2LLTxuwb+IFASiGQO4sgJ8K7AG66SlSeqARrcetevV8zOf+i1z+MbJJ2O7//OxAw==", + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/govuk-frontend/-/govuk-frontend-4.9.0.tgz", + "integrity": "sha512-zfX+GBUKpWBeV6JwCIawEuI8VRWlskH8Ok8aNUjKOvzo3zIaNbcrv4IOwgy+oSnMoGh67Eeh+vb7+9GFxN2fNg==", + "license": "MIT", "engines": { "node": ">= 4.2.0" } @@ -8657,6 +8997,13 @@ "node": ">= 10.13" } }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "dev": true, + "license": "MIT" + }, "node_modules/node-downloader-helper": { "version": "2.1.9", "resolved": "https://registry.npmjs.org/node-downloader-helper/-/node-downloader-helper-2.1.9.tgz", @@ -10205,12 +10552,13 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/sass": { - "version": "1.79.4", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.79.4.tgz", - "integrity": "sha512-K0QDSNPXgyqO4GZq2HO5Q70TLxTH6cIT59RdoCHMivrC8rqzaTw5ab9prjz9KUN1El4FLXrBXJhik61JR4HcGg==", + "version": "1.80.2", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.80.2.tgz", + "integrity": "sha512-9wXY8cGBlUmoUoT+vwOZOFCiS+naiWVjqlreN9ar9PudXbGwlMTFwCR5K9kB4dFumJ6ib98wZyAObJKsWf1nAA==", "dev": true, "license": "MIT", "dependencies": { + "@parcel/watcher": "^2.4.1", "chokidar": "^4.0.0", "immutable": "^4.0.0", "source-map-js": ">=0.6.2 <2.0.0" @@ -11243,9 +11591,9 @@ } }, "node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz", + "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==", "license": "0BSD" }, "node_modules/type-check": { diff --git a/package.json b/package.json index 1d65a770..1d726ae2 100644 --- a/package.json +++ b/package.json @@ -32,24 +32,24 @@ "license": "MIT", "dependencies": { "@companieshouse/api-sdk-node": "^2.0.209", - "@companieshouse/ch-node-utils": "^1.3.11", + "@companieshouse/ch-node-utils": "^1.3.12", "@companieshouse/node-session-handler": "^5.1.4", "@companieshouse/structured-logging-node": "^2.0.1", - "@companieshouse/web-security-node": "^4.3.1", + "@companieshouse/web-security-node": "^4.4.0", "@types/supertest": "^6.0.2", "axios": "^1.7.7", - "cookie-parser": "1.4.6", - "express": "^4.21.0", + "cookie-parser": "1.4.7", + "express": "^4.21.1", "govuk_frontend_toolkit": "^9.0.1", "govuk-elements-sass": "^3.1.3", - "govuk-frontend": "^4.8.0", + "govuk-frontend": "^4.9.0", "http-errors": "^1.8.1", "ioredis": "4.28.5", "js-yaml": "^3.14.1", "luxon": "^3.5.0", "nunjucks": "3.2.4", "sonarqube-scanner": "^3.5.0", - "tslib": "^2.7.0", + "tslib": "^2.8.0", "uuid": "8.3.2", "yargs": "17.7.2" }, @@ -89,7 +89,7 @@ "node-mocks-http": "^1.16.1", "nodemon": "^3.1.7", "nyc": "^15.1.0", - "sass": "1.79.4", + "sass": "1.80.2", "supertest": "^6.3.4", "ts-jest": "^29.2.5", "ts-node": "8.10.2", From 75d94dc0cd570b8afb6c4bd733b43a1122851388 Mon Sep 17 00:00:00 2001 From: Simon Boyd Date: Fri, 18 Oct 2024 15:57:38 +0100 Subject: [PATCH 8/8] Remove redundant commented out code --- test/routers/confirmCompany.int.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/test/routers/confirmCompany.int.ts b/test/routers/confirmCompany.int.ts index faab2867..670f9e81 100644 --- a/test/routers/confirmCompany.int.ts +++ b/test/routers/confirmCompany.int.ts @@ -14,10 +14,6 @@ mockGetCompanyProfile.mockResolvedValue(validCompanyProfile); describe("ConfirmCompany router/handler integration tests", () => { - beforeAll(() => { - // middlewareMocks.mockCsrfProtectionMiddleware.mockClear(); - }); - beforeEach(() => { middlewareMocks.mockSessionMiddleware.mockClear(); }); @@ -33,8 +29,6 @@ describe("ConfirmCompany router/handler integration tests", () => { .expect(HttpStatusCode.Ok); }); - // FIXME: Merge tests? - it("Should display 'Confirm this is the correct company' message on the Confirm Company page", async () => { const resp = await request(app).get(PrefixedUrls.CONFIRM_COMPANY);