From 80cee0fed3f61239d504743bd1252756c55adb35 Mon Sep 17 00:00:00 2001 From: Matt Bevilacqua Date: Mon, 23 Sep 2024 15:12:15 -0400 Subject: [PATCH 1/7] Fix accessibility review bugs --- .../components/GoalForm/ResourceRepeater.js | 17 +++++++---- .../Pages/components/Objective.js | 4 +-- .../pages/ActivityReport/__tests__/index.js | 5 ++-- src/goalServices/getGoalsForReport.ts | 1 - src/models/goal.js | 2 ++ src/models/hooks/goal.js | 30 +++++++++++++++++-- 6 files changed, 45 insertions(+), 14 deletions(-) diff --git a/frontend/src/components/GoalForm/ResourceRepeater.js b/frontend/src/components/GoalForm/ResourceRepeater.js index fc5756728f..42d41d8a67 100644 --- a/frontend/src/components/GoalForm/ResourceRepeater.js +++ b/frontend/src/components/GoalForm/ResourceRepeater.js @@ -3,7 +3,11 @@ import { isValidResourceUrl } from '@ttahub/common'; import PropTypes from 'prop-types'; import { v4 as uuidv4 } from 'uuid'; import { - FormGroup, Label, Button, Fieldset, + FormGroup, + Label, + Button, + Fieldset, + ErrorMessage, } from '@trussworks/react-uswds'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faTrash } from '@fortawesome/free-solid-svg-icons'; @@ -22,7 +26,7 @@ export default function ResourceRepeater({ isLoading, }) { const addResource = () => { - if ((error.props.children) || resources.some((r) => !r.value)) { + if ((error) || resources.some((r) => !r.value)) { return; } const newResources = [...resources, { key: uuidv4(), value: '' }]; @@ -45,7 +49,7 @@ export default function ResourceRepeater({ return ( <> - +
@@ -58,7 +62,9 @@ export default function ResourceRepeater({ Enter one resource per field. To enter more resources, select “Add new resource”
- {error.props.children ? error : null} + + {error} +
{ resources.map((r, i) => (
@@ -103,13 +109,14 @@ ResourceRepeater.propTypes = { value: PropTypes.string, })).isRequired, setResources: PropTypes.func.isRequired, - error: PropTypes.node.isRequired, + error: PropTypes.string, validateResources: PropTypes.func.isRequired, isLoading: PropTypes.bool, toolTipText: PropTypes.string, }; ResourceRepeater.defaultProps = { + error: '', isLoading: false, toolTipText: 'Copy & paste web address of TTA resource used for this objective. Usually an ECLKC page.', }; diff --git a/frontend/src/pages/ActivityReport/Pages/components/Objective.js b/frontend/src/pages/ActivityReport/Pages/components/Objective.js index a58e6f4448..ec1b4caa70 100644 --- a/frontend/src/pages/ActivityReport/Pages/components/Objective.js +++ b/frontend/src/pages/ActivityReport/Pages/components/Objective.js @@ -388,9 +388,7 @@ export default function Objective({ resources={resourcesForRepeater} isOnReport={isOnReport || false} setResources={onChangeResources} - error={errors.resources - ? ERROR_FORMAT(errors.resources.message) - : NO_ERROR} + error={errors.resources ? errors.resources.message : ''} validateResources={onBlurResources} inputName={objectiveResourcesInputName} userCanEdit diff --git a/frontend/src/pages/ActivityReport/__tests__/index.js b/frontend/src/pages/ActivityReport/__tests__/index.js index f255c7fdce..eaa37a48f5 100644 --- a/frontend/src/pages/ActivityReport/__tests__/index.js +++ b/frontend/src/pages/ActivityReport/__tests__/index.js @@ -1173,9 +1173,8 @@ describe('ActivityReport', () => { userEvent.click(saveGoal); }); - const errors = document.querySelectorAll('.usa-error-message'); - expect(errors.length).toBe(1); - // they'll be one at least (objective suspend reason modal error sits in the dom at all times) + const errors = document.querySelectorAll('.usa-error-message:not(:empty)'); + expect(errors.length).toBe(0); await waitFor(() => { expect(fetchMock.called('/api/activity-reports/1', { method: 'PUT' })).toBe(true); diff --git a/src/goalServices/getGoalsForReport.ts b/src/goalServices/getGoalsForReport.ts index f6528d8b24..fe49459543 100644 --- a/src/goalServices/getGoalsForReport.ts +++ b/src/goalServices/getGoalsForReport.ts @@ -69,7 +69,6 @@ export default async function getGoalsForReport(reportId: number) { LEFT JOIN "ActivityReportGoalFieldResponses" argfr ON gtfp.id = argfr."goalTemplateFieldPromptId" AND argfr."activityReportGoalId" = "activityReportGoals".id - WHERE "goalTemplate".id = gtfp."goalTemplateId" GROUP BY 1=1 )`), 'prompts'], ], diff --git a/src/models/goal.js b/src/models/goal.js index 71ada9f158..322bae8575 100644 --- a/src/models/goal.js +++ b/src/models/goal.js @@ -7,6 +7,7 @@ const { afterCreate, afterUpdate, afterDestroy, + beforeCreate, } = require('./hooks/goal'); const { GOAL_CREATED_VIA, CREATION_METHOD } = require('../constants'); @@ -152,6 +153,7 @@ export default (sequelize, DataTypes) => { hooks: { beforeValidate: async (instance, options) => beforeValidate(sequelize, instance, options), beforeUpdate: async (instance, options) => beforeUpdate(sequelize, instance, options), + beforeCreate: async (instance, options) => beforeCreate(sequelize, instance, options), afterCreate: async (instance, options) => afterCreate(sequelize, instance, options), afterUpdate: async (instance, options) => afterUpdate(sequelize, instance, options), afterDestroy: async (instance, options) => afterDestroy(sequelize, instance, options), diff --git a/src/models/hooks/goal.js b/src/models/hooks/goal.js index 440bdc9c70..5396ba3c46 100644 --- a/src/models/hooks/goal.js +++ b/src/models/hooks/goal.js @@ -1,5 +1,10 @@ const { Op } = require('sequelize'); -const { GOAL_STATUS, GOAL_COLLABORATORS, OBJECTIVE_STATUS } = require('../../constants'); +const { + GOAL_STATUS, + GOAL_COLLABORATORS, + OBJECTIVE_STATUS, + CREATION_METHOD, +} = require('../../constants'); const { currentUserPopulateCollaboratorForType, } = require('../helpers/genericCollaborator'); @@ -28,7 +33,22 @@ const findOrCreateGoalTemplate = async (sequelize, transaction, regionId, name, }, transaction, }); - return { id: goalTemplate[0].id, name }; + return { id: goalTemplate[0].id, name, creationMethod: goalTemplate[0].creationMethod }; +}; + +const checkForCuratedGoal = async (sequelize, instance) => { + const curatedTemplate = await sequelize.models.GoalTemplate.findOne({ + where: { + hash: sequelize.fn('md5', sequelize.fn('NULLIF', sequelize.fn('TRIM', instance.name), '')), + creationMethod: CREATION_METHOD.CURATED, + regionId: null, + }, + attributes: ['id'], + }); + + if (curatedTemplate) { + instance.set('goalTemplateId', curatedTemplate.id); + } }; const autoPopulateOnAR = (_sequelize, instance, options) => { @@ -299,6 +319,10 @@ const beforeValidate = async (sequelize, instance, options) => { preventNameChangeWhenOnApprovedAR(sequelize, instance, options); }; +const beforeCreate = async (sequelize, instance, options) => { + await checkForCuratedGoal(sequelize, instance, options); +}; + const beforeUpdate = async (sequelize, instance, options) => { preventNameChangeWhenOnApprovedAR(sequelize, instance, options); await preventCloseIfObjectivesOpen(sequelize, instance, options); @@ -329,10 +353,12 @@ export { autoPopulateOnApprovedAR, preventNameChangeWhenOnApprovedAR, preventCloseIfObjectivesOpen, + checkForCuratedGoal, propagateName, beforeValidate, beforeUpdate, afterCreate, afterUpdate, + beforeCreate, afterDestroy, }; From 4e697a0d41ee22425ddbcea9219093a5a31b92f4 Mon Sep 17 00:00:00 2001 From: Matt Bevilacqua Date: Mon, 23 Sep 2024 15:17:30 -0400 Subject: [PATCH 2/7] Add additional check before creating curated goal --- src/models/hooks/goal.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/models/hooks/goal.js b/src/models/hooks/goal.js index 5396ba3c46..c82524d66f 100644 --- a/src/models/hooks/goal.js +++ b/src/models/hooks/goal.js @@ -37,6 +37,9 @@ const findOrCreateGoalTemplate = async (sequelize, transaction, regionId, name, }; const checkForCuratedGoal = async (sequelize, instance) => { + // we don't want to be setting goalTemplateId if it's already set + if (instance.goalTemplateId) return; + const curatedTemplate = await sequelize.models.GoalTemplate.findOne({ where: { hash: sequelize.fn('md5', sequelize.fn('NULLIF', sequelize.fn('TRIM', instance.name), '')), From e5a6e5fb869fdf326ae6b4793c737e91745e33c6 Mon Sep 17 00:00:00 2001 From: Matt Bevilacqua Date: Mon, 23 Sep 2024 15:22:05 -0400 Subject: [PATCH 3/7] Add test --- src/models/hooks/goal.test.js | 49 +++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/src/models/hooks/goal.test.js b/src/models/hooks/goal.test.js index 0c3e02bec2..9195dccf86 100644 --- a/src/models/hooks/goal.test.js +++ b/src/models/hooks/goal.test.js @@ -3,6 +3,7 @@ const { processForEmbeddedResources, findOrCreateGoalTemplate, preventCloseIfObjectivesOpen, + beforeCreate, } = require('./goal'); const { GOAL_STATUS, OBJECTIVE_STATUS } = require('../../constants'); const { createRecipient, createGrant, createGoal } = require('../../testUtils'); @@ -18,6 +19,54 @@ const { jest.mock('../../services/resource'); describe('goal hooks', () => { + describe('beforeCreate', () => { + it('does nothing if instance already has goalTemplateId', async () => { + const instanceSet = jest.fn(); + const instance = { + goalTemplateId: 1, + set: instanceSet, + }; + await expect(beforeCreate({}, instance)).resolves.not.toThrow(); + expect(instanceSet).not.toHaveBeenCalled(); + }); + + it('does nothing if sequelize cannot find a curated template', async () => { + const instanceSet = jest.fn(); + const instance = { + goalTemplateId: null, + set: instanceSet, + }; + const sequelize = { + fn: jest.fn(), + models: { + GoalTemplate: { + findOne: jest.fn().mockResolvedValue(null), + }, + }, + }; + await expect(beforeCreate(sequelize, instance)).resolves.not.toThrow(); + expect(instanceSet).not.toHaveBeenCalled(); + }); + + it('sets goalTemplateId if a curated template is found', async () => { + const instanceSet = jest.fn(); + const instance = { + goalTemplateId: null, + set: instanceSet, + }; + const sequelize = { + fn: jest.fn(), + models: { + GoalTemplate: { + findOne: jest.fn().mockResolvedValue({ id: 1 }), + }, + }, + }; + await expect(beforeCreate(sequelize, instance)).resolves.not.toThrow(); + expect(instanceSet).toHaveBeenCalledWith('goalTemplateId', 1); + }); + }); + describe('preventCloseIfObjectivesOpen', () => { it('does nothing if instance.changed is not an array', async () => { const instance = { From c8bd1b414f33c019605bf9fd5721b338937cb13a Mon Sep 17 00:00:00 2001 From: Matt Bevilacqua Date: Tue, 24 Sep 2024 12:32:35 -0400 Subject: [PATCH 4/7] Update known issues --- frontend/yarn-audit-known-issues | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/yarn-audit-known-issues b/frontend/yarn-audit-known-issues index 697c6815af..afca62462a 100644 --- a/frontend/yarn-audit-known-issues +++ b/frontend/yarn-audit-known-issues @@ -3,3 +3,4 @@ {"type":"auditAdvisory","data":{"resolution":{"id":1097682,"path":"react-scripts>jest>jest-cli>@jest/core>jest-config>jest-runner>jest-environment-jsdom>jsdom>tough-cookie","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"4.0.0","paths":["react-scripts>jest>@jest/core>jest-config>jest-environment-jsdom>jsdom>tough-cookie","react-scripts>jest>jest-cli>@jest/core>jest-config>jest-environment-jsdom>jsdom>tough-cookie","react-scripts>jest>jest-cli>@jest/core>jest-config>jest-runner>jest-environment-jsdom>jsdom>tough-cookie"]}],"found_by":null,"deleted":null,"references":"- https://nvd.nist.gov/vuln/detail/CVE-2023-26136\n- https://github.com/salesforce/tough-cookie/issues/282\n- https://github.com/salesforce/tough-cookie/commit/12d474791bb856004e858fdb1c47b7608d09cf6e\n- https://github.com/salesforce/tough-cookie/releases/tag/v4.1.3\n- https://security.snyk.io/vuln/SNYK-JS-TOUGHCOOKIE-5672873\n- https://lists.debian.org/debian-lts-announce/2023/07/msg00010.html\n- https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/3HUE6ZR5SL73KHL7XUPAOEL6SB7HUDT2\n- https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/6PVVPNSAGSDS63HQ74PJ7MZ3MU5IYNVZ\n- https://security.netapp.com/advisory/ntap-20240621-0006\n- https://github.com/advisories/GHSA-72xf-g2v4-qvf3","created":"2023-07-01T06:30:16.000Z","id":1097682,"npm_advisory_id":null,"overview":"Versions of the package tough-cookie before 4.1.3 are vulnerable to Prototype Pollution due to improper handling of Cookies when using CookieJar in `rejectPublicSuffixes=false` mode. This issue arises from the manner in which the objects are initialized.","reported_by":null,"title":"tough-cookie Prototype Pollution vulnerability","metadata":null,"cves":["CVE-2023-26136"],"access":"public","severity":"moderate","module_name":"tough-cookie","vulnerable_versions":"<4.1.3","github_advisory_id":"GHSA-72xf-g2v4-qvf3","recommendation":"Upgrade to version 4.1.3 or later","patched_versions":">=4.1.3","updated":"2024-06-21T21:33:53.000Z","cvss":{"score":6.5,"vectorString":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N"},"cwe":["CWE-1321"],"url":"https://github.com/advisories/GHSA-72xf-g2v4-qvf3"}}} {"type":"auditAdvisory","data":{"resolution":{"id":1099525,"path":"react-scripts>webpack-dev-server>express>serve-static>send","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"0.18.0","paths":["react-scripts>webpack-dev-server>express>serve-static>send"]}],"found_by":null,"deleted":null,"references":"- https://github.com/pillarjs/send/security/advisories/GHSA-m6fv-jmcg-4jfg\n- https://nvd.nist.gov/vuln/detail/CVE-2024-43799\n- https://github.com/pillarjs/send/commit/ae4f2989491b392ae2ef3b0015a019770ae65d35\n- https://github.com/advisories/GHSA-m6fv-jmcg-4jfg","created":"2024-09-10T19:42:41.000Z","id":1099525,"npm_advisory_id":null,"overview":"### Impact\n\npassing untrusted user input - even after sanitizing it - to `SendStream.redirect()` may execute untrusted code\n\n### Patches\n\nthis issue is patched in send 0.19.0\n\n### Workarounds\n\nusers are encouraged to upgrade to the patched version of express, but otherwise can workaround this issue by making sure any untrusted inputs are safe, ideally by validating them against an explicit allowlist\n\n### Details\n\nsuccessful exploitation of this vector requires the following:\n\n1. The attacker MUST control the input to response.redirect()\n1. express MUST NOT redirect before the template appears\n1. the browser MUST NOT complete redirection before:\n1. the user MUST click on the link in the template\n","reported_by":null,"title":"send vulnerable to template injection that can lead to XSS","metadata":null,"cves":["CVE-2024-43799"],"access":"public","severity":"moderate","module_name":"send","vulnerable_versions":"<0.19.0","github_advisory_id":"GHSA-m6fv-jmcg-4jfg","recommendation":"Upgrade to version 0.19.0 or later","patched_versions":">=0.19.0","updated":"2024-09-10T19:42:42.000Z","cvss":{"score":5,"vectorString":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:L"},"cwe":["CWE-79"],"url":"https://github.com/advisories/GHSA-m6fv-jmcg-4jfg"}}} {"type":"auditAdvisory","data":{"resolution":{"id":1099597,"path":"react-admin>ra-ui-materialui>dompurify","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"2.4.4","paths":["react-admin>ra-ui-materialui>dompurify"]}],"found_by":null,"deleted":null,"references":"- https://github.com/cure53/DOMPurify/security/advisories/GHSA-mmhx-hmjr-r674\n- https://github.com/cure53/DOMPurify/commit/1e520262bf4c66b5efda49e2316d6d1246ca7b21\n- https://github.com/cure53/DOMPurify/commit/26e1d69ca7f769f5c558619d644d90dd8bf26ebc\n- https://nvd.nist.gov/vuln/detail/CVE-2024-45801\n- https://github.com/advisories/GHSA-mmhx-hmjr-r674","created":"2024-09-16T20:34:26.000Z","id":1099597,"npm_advisory_id":null,"overview":"It has been discovered that malicious HTML using special nesting techniques can bypass the depth checking added to DOMPurify in recent releases. It was also possible to use Prototype Pollution to weaken the depth check.\n\nThis renders dompurify unable to avoid XSS attack.\n\nFixed by https://github.com/cure53/DOMPurify/commit/1e520262bf4c66b5efda49e2316d6d1246ca7b21 (3.x branch) and https://github.com/cure53/DOMPurify/commit/26e1d69ca7f769f5c558619d644d90dd8bf26ebc (2.x branch).","reported_by":null,"title":"DOMPurify allows tampering by prototype pollution","metadata":null,"cves":["CVE-2024-45801"],"access":"public","severity":"high","module_name":"dompurify","vulnerable_versions":"<2.5.4","github_advisory_id":"GHSA-mmhx-hmjr-r674","recommendation":"Upgrade to version 2.5.4 or later","patched_versions":">=2.5.4","updated":"2024-09-16T22:37:33.000Z","cvss":{"score":7,"vectorString":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:H/A:L"},"cwe":["CWE-1321","CWE-1333"],"url":"https://github.com/advisories/GHSA-mmhx-hmjr-r674"}}} +{"type":"auditAdvisory","data":{"resolution":{"id":1099718,"path":"react-scripts>workbox-webpack-plugin>workbox-build>rollup","dev":false,"optional":false,"bundled":false},"advisory":{"findings":[{"version":"2.79.1","paths":["react-scripts>workbox-webpack-plugin>workbox-build>rollup"]}],"found_by":null,"deleted":null,"references":"- https://github.com/rollup/rollup/security/advisories/GHSA-gcx4-mw62-g8wm\n- https://nvd.nist.gov/vuln/detail/CVE-2024-47068\n- https://github.com/rollup/rollup/commit/2ef77c00ec2635d42697cff2c0567ccc8db34fb4\n- https://github.com/rollup/rollup/commit/e2552c9e955e0a61f70f508200ee9f752f85a541\n- https://github.com/rollup/rollup/blob/b86ffd776cfa906573d36c3f019316d02445d9ef/src/ast/nodes/MetaProperty.ts#L157-L162\n- https://github.com/rollup/rollup/blob/b86ffd776cfa906573d36c3f019316d02445d9ef/src/ast/nodes/MetaProperty.ts#L180-L185\n- https://github.com/advisories/GHSA-gcx4-mw62-g8wm","created":"2024-09-23T22:11:02.000Z","id":1099718,"npm_advisory_id":null,"overview":"### Summary\n\nA DOM Clobbering vulnerability was discovered in rollup when bundling scripts that use `import.meta.url` or with plugins that emit and reference asset files from code in `cjs`/`umd`/`iife` format. The DOM Clobbering gadget can lead to cross-site scripting (XSS) in web pages where scriptless attacker-controlled HTML elements (e.g., an `img` tag with an unsanitized `name` attribute) are present.\n\nIt's worth noting that similar issues in other popular bundlers like Webpack ([CVE-2024-43788](https://github.com/webpack/webpack/security/advisories/GHSA-4vvj-4cpr-p986)) have been reported, which might serve as a good reference.\n\n### Details\n\n#### Backgrounds\n\nDOM Clobbering is a type of code-reuse attack where the attacker first embeds a piece of non-script, seemingly benign HTML markups in the webpage (e.g. through a post or comment) and leverages the gadgets (pieces of js code) living in the existing javascript code to transform it into executable code. More for information about DOM Clobbering, here are some references:\n\n[1] https://scnps.co/papers/sp23_domclob.pdf\n[2] https://research.securitum.com/xss-in-amp4email-dom-clobbering/\n\n#### Gadget found in `rollup`\n\nA DOM Clobbering vulnerability in `rollup` bundled scripts was identified, particularly when the scripts uses `import.meta` and set output in format of `cjs`/`umd`/`iife`. In such cases, `rollup` replaces meta property with the URL retrieved from `document.currentScript`.\n\nhttps://github.com/rollup/rollup/blob/b86ffd776cfa906573d36c3f019316d02445d9ef/src/ast/nodes/MetaProperty.ts#L157-L162\n\nhttps://github.com/rollup/rollup/blob/b86ffd776cfa906573d36c3f019316d02445d9ef/src/ast/nodes/MetaProperty.ts#L180-L185\n\nHowever, this implementation is vulnerable to a DOM Clobbering attack. The `document.currentScript` lookup can be shadowed by an attacker via the browser's named DOM tree element access mechanism. This manipulation allows an attacker to replace the intended script element with a malicious HTML element. When this happens, the `src` attribute of the attacker-controlled element (e.g., an `img` tag ) is used as the URL for importing scripts, potentially leading to the dynamic loading of scripts from an attacker-controlled server.\n\n### PoC\n\nConsidering a website that contains the following `main.js` script, the devloper decides to use the `rollup` to bundle up the program: `rollup main.js --format cjs --file bundle.js`.\n\n```\nvar s = document.createElement('script')\ns.src = import.meta.url + 'extra.js'\ndocument.head.append(s)\n```\n\nThe output `bundle.js` is shown in the following code snippet.\n\n```\n'use strict';\n\nvar _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;\nvar s = document.createElement('script');\ns.src = (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && False && _documentCurrentScript.src || new URL('bundle.js', document.baseURI).href)) + 'extra.js';\ndocument.head.append(s);\n```\n\nAdding the `rollup` bundled script, `bundle.js`, as part of the web page source code, the page could load the `extra.js` file from the attacker's domain, `attacker.controlled.server` due to the introduced gadget during bundling. The attacker only needs to insert an `img` tag with the name attribute set to `currentScript`. This can be done through a website's feature that allows users to embed certain script-less HTML (e.g., markdown renderers, web email clients, forums) or via an HTML injection vulnerability in third-party JavaScript loaded on the page.\n\n```\n\n\n\n rollup Example\n \n \n \n\n\n\n\n\n```\n\n### Impact\n\nThis vulnerability can result in cross-site scripting (XSS) attacks on websites that include rollup-bundled files (configured with an output format of `cjs`, `iife`, or `umd` and use `import.meta`) and allow users to inject certain scriptless HTML tags without properly sanitizing the `name` or `id` attributes.\n\n### Patch\n\nPatching the following two functions with type checking would be effective mitigations against DOM Clobbering attack.\n\n```\nconst getRelativeUrlFromDocument = (relativePath: string, umd = false) =>\n\tgetResolveUrl(\n\t\t`'${escapeId(relativePath)}', ${\n\t\t\tumd ? `typeof document === 'undefined' ? location.href : ` : ''\n\t\t}document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT' && document.currentScript.src || document.baseURI`\n\t);\n```\n\n```\nconst getUrlFromDocument = (chunkId: string, umd = false) =>\n\t`${\n\t\tumd ? `typeof document === 'undefined' ? location.href : ` : ''\n\t}(${DOCUMENT_CURRENT_SCRIPT} && ${DOCUMENT_CURRENT_SCRIPT}.tagName.toUpperCase() === 'SCRIPT' &&${DOCUMENT_CURRENT_SCRIPT}.src || new URL('${escapeId(\n\t\tchunkId\n\t)}', document.baseURI).href)`;\n```\n","reported_by":null,"title":"DOM Clobbering Gadget found in rollup bundled scripts that leads to XSS","metadata":null,"cves":["CVE-2024-47068"],"access":"public","severity":"high","module_name":"rollup","vulnerable_versions":"<3.29.5","github_advisory_id":"GHSA-gcx4-mw62-g8wm","recommendation":"Upgrade to version 3.29.5 or later","patched_versions":">=3.29.5","updated":"2024-09-23T22:11:05.000Z","cvss":{"score":6.4,"vectorString":"CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:L/A:H"},"cwe":["CWE-79"],"url":"https://github.com/advisories/GHSA-gcx4-mw62-g8wm"}}} From 48c7cbabd2f1b4e3afa039db7e7d4ba3b76d21f1 Mon Sep 17 00:00:00 2001 From: Matt Bevilacqua Date: Tue, 24 Sep 2024 12:40:14 -0400 Subject: [PATCH 5/7] revert sql change, bad --- src/goalServices/getGoalsForReport.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/goalServices/getGoalsForReport.ts b/src/goalServices/getGoalsForReport.ts index fe49459543..f6528d8b24 100644 --- a/src/goalServices/getGoalsForReport.ts +++ b/src/goalServices/getGoalsForReport.ts @@ -69,6 +69,7 @@ export default async function getGoalsForReport(reportId: number) { LEFT JOIN "ActivityReportGoalFieldResponses" argfr ON gtfp.id = argfr."goalTemplateFieldPromptId" AND argfr."activityReportGoalId" = "activityReportGoals".id + WHERE "goalTemplate".id = gtfp."goalTemplateId" GROUP BY 1=1 )`), 'prompts'], ], From 52f12922df2a34a3c81fa340c06471c626854722 Mon Sep 17 00:00:00 2001 From: Matt Bevilacqua Date: Tue, 24 Sep 2024 12:40:46 -0400 Subject: [PATCH 6/7] Properly associate label with form field, event summary --- frontend/src/pages/TrainingReportForm/pages/eventSummary.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/pages/TrainingReportForm/pages/eventSummary.js b/frontend/src/pages/TrainingReportForm/pages/eventSummary.js index 6e46f728b4..8a98bdeac6 100644 --- a/frontend/src/pages/TrainingReportForm/pages/eventSummary.js +++ b/frontend/src/pages/TrainingReportForm/pages/eventSummary.js @@ -176,7 +176,7 @@ const EventSummary = ({
-