);
@@ -26,10 +60,12 @@ FeedArticle.propTypes = {
content: PropTypes.string.isRequired,
unread: PropTypes.bool.isRequired,
partial: PropTypes.bool,
+ openLinksInNewTab: PropTypes.bool,
};
FeedArticle.defaultProps = {
partial: false,
+ openLinksInNewTab: false,
};
export default FeedArticle;
diff --git a/frontend/src/components/FeedArticle.scss b/frontend/src/components/FeedArticle.scss
index d6a891c27b..9160599c04 100644
--- a/frontend/src/components/FeedArticle.scss
+++ b/frontend/src/components/FeedArticle.scss
@@ -1,39 +1,15 @@
-@use '../colors.scss' as *;
-
-/**
-this hides the initial "author inforation" blocks"
-**/
-.ttahub-feed-article:not(.ttahub-feed-article--partial) div[data-contents="true"] > [data-block="true"]:nth-child(1),
-.ttahub-feed-article:not(.ttahub-feed-article--partial) div[data-contents="true"] > [data-block="true"]:nth-child(2),
-.ttahub-feed-article:not(.ttahub-feed-article--partial) div[data-contents="true"] > [data-block="true"]:nth-child(3),
-.ttahub-feed-article:not(.ttahub-feed-article--partial) div[data-contents="true"] > [data-block="true"]:last-child,
-.ttahub-feed-article div[data-contents="true"] > [data-block="true"]:empty,
-.ttahub-feed-article h4:empty {
+// hide the "blog post by" text
+.ttahub-feed-article-content p:has(a:not([href])){
display: none;
}
-
-// fix the margins and spacing of the read only editor
-.ttahub-feed-article .public-DraftStyleDefault-block {
- font-size: 1.06rem;
- line-height: 1.5;
- margin: 0;
- white-space: normal;
+// remove inline styles from feed
+// - since they are inline, we have to use !important
+.ttahub-feed-article-content .feed > div {
+ border: none !important;
+ padding: 0 !important;
}
-// hide the big old link icon that pops up
-.ttahub-feed-article .rdw-link-decorator-icon {
+.ttahub-feed-article-content .feed div:last-child{
display: none;
-}
-
-.ttahub-feed-article .public-DraftStyleDefault-block a:after,
-.ttahub-read-more--external:after {
- content: "\f35d";
- display: inline-block;
- font: normal normal normal 16px/1 FontAwesome;
- margin: 0 8px;
-}
-
-.ttahub-feed-article .public-DraftStyleDefault-block a:hover:after {
- opacity: 0.75;
-}
+}
\ No newline at end of file
diff --git a/frontend/src/components/GoalForm/ObjectiveTopics.js b/frontend/src/components/GoalForm/ObjectiveTopics.js
index 5f7424d038..7bb5ba7971 100644
--- a/frontend/src/components/GoalForm/ObjectiveTopics.js
+++ b/frontend/src/components/GoalForm/ObjectiveTopics.js
@@ -9,7 +9,6 @@ import Drawer from '../Drawer';
import Req from '../Req';
import ContentFromFeedByTag from '../ContentFromFeedByTag';
import DrawerTriggerButton from '../DrawerTriggerButton';
-import './ObjectiveTopics.scss';
export default function ObjectiveTopics({
error,
diff --git a/frontend/src/components/GoalForm/ObjectiveTopics.scss b/frontend/src/components/GoalForm/ObjectiveTopics.scss
deleted file mode 100644
index 7758fc0545..0000000000
--- a/frontend/src/components/GoalForm/ObjectiveTopics.scss
+++ /dev/null
@@ -1,9 +0,0 @@
-.ttahub-drawer--objective-topics-guidance div.rdw-center-aligned-block:nth-child(1),
-.ttahub-drawer--objective-topics-guidance div.rdw-center-aligned-block:nth-child(2) {
- display: none;
-}
-
-.ttahub-drawer--objective-topics-guidance [data-block="true"]:nth-child(even) {
- margin-bottom: 1rem;
-}
-
diff --git a/frontend/src/components/GoalForm/index.js b/frontend/src/components/GoalForm/index.js
index 3f89df0267..345e601cc8 100644
--- a/frontend/src/components/GoalForm/index.js
+++ b/frontend/src/components/GoalForm/index.js
@@ -100,7 +100,7 @@ export default function GoalForm({
useDeepCompareEffect(() => {
const newPrompts = grantsToMultiValue(selectedGrants, { ...prompts });
if ((!isEqual(newPrompts, prompts))) {
- setSource(newPrompts);
+ setPrompts(newPrompts);
}
}, [prompts, selectedGrants]);
diff --git a/frontend/src/components/SupportTypeDrawer.js b/frontend/src/components/SupportTypeDrawer.js
index 853236dde4..756f954d47 100644
--- a/frontend/src/components/SupportTypeDrawer.js
+++ b/frontend/src/components/SupportTypeDrawer.js
@@ -2,7 +2,6 @@ import React from 'react';
import PropTypes from 'prop-types';
import Drawer from './Drawer';
import ContentFromFeedByTag from './ContentFromFeedByTag';
-import './SupportTypeDrawer.scss';
export default function SupportTypeDrawer({
drawerTriggerRef,
@@ -14,7 +13,7 @@ export default function SupportTypeDrawer({
stickyFooter
title="Support type guidance"
>
-
+
);
}
diff --git a/frontend/src/components/SupportTypeDrawer.scss b/frontend/src/components/SupportTypeDrawer.scss
deleted file mode 100644
index fa5bbc54d8..0000000000
--- a/frontend/src/components/SupportTypeDrawer.scss
+++ /dev/null
@@ -1,65 +0,0 @@
-/* hides centered header and misaligned bullet points */
-.ttahub-drawer--objective-support-type-guidance div.rdw-center-aligned-block:nth-child(2),
-.ttahub-drawer--objective-support-type-guidance div.rdw-center-aligned-block:nth-child(1),
-.ttahub-drawer--objective-support-type-guidance .public-DraftStyleDefault-ul {
- display: none;
-}
-
-/* creates left margin for bullet points */
-.ttahub-drawer--objective-support-type-guidance .public-DraftStyleDefault-ul + div > div > span > span {
- margin-left: 2em;
-}
-
-/* creates bullet points */
-.ttahub-drawer--objective-support-type-guidance .public-DraftStyleDefault-ul + div > div > span > span:before {
- content: '•';
- margin-right: 1em;
-}
-
-/* creates margin between bold headers */
-.ttahub-drawer--objective-support-type-guidance .rdw-editor-main > div > div > div > div > div:nth-child(12),
-.ttahub-drawer--objective-support-type-guidance .rdw-editor-main > div > div > div > div > div:nth-child(15),
-.ttahub-drawer--objective-support-type-guidance .rdw-editor-main > div > div > div > div > div:nth-child(22) {
- margin-top: 1rem;
-}
-
-/* creates margin between text and bullets */
-.ttahub-drawer--objective-support-type-guidance .rdw-editor-main > div > div > div > div > div:nth-child(4),
-.ttahub-drawer--objective-support-type-guidance .rdw-editor-main > div > div > div > div > div:nth-child(13),
-.ttahub-drawer--objective-support-type-guidance .rdw-editor-main > div > div > div > div > div:nth-child(16),
-.ttahub-drawer--objective-support-type-guidance .rdw-editor-main > div > div > div > div > div:nth-child(23) {
- margin-bottom: 10px;
-}
-
-/* hides centered header and misaligned bullet points */
-.ttahub-drawer--objective-support-type-guidance div.rdw-center-aligned-block:nth-child(2),
-.ttahub-drawer--objective-support-type-guidance div.rdw-center-aligned-block:nth-child(1),
-.ttahub-drawer--objective-support-type-guidance .public-DraftStyleDefault-ul {
- display: none;
-}
-
-/* creates left margin for bullet points */
-.ttahub-drawer--objective-support-type-guidance .public-DraftStyleDefault-ul + div > div > span > span {
- margin-left: 2em;
-}
-
-/* creates bullet points */
-.ttahub-drawer--objective-support-type-guidance .public-DraftStyleDefault-ul + div > div > span > span:before {
- content: '•';
- margin-right: 1em;
-}
-
-/* creates margin between bold headers */
-.rdw-editor-main > div > div > div > div > div:nth-child(12),
-.rdw-editor-main > div > div > div > div > div:nth-child(15),
-.rdw-editor-main > div > div > div > div > div:nth-child(22) {
- margin-top: 1rem;
-}
-
-/* creates margin between text and bullets */
-.rdw-editor-main > div > div > div > div > div:nth-child(4),
-.rdw-editor-main > div > div > div > div > div:nth-child(13),
-.rdw-editor-main > div > div > div > div > div:nth-child(16),
-.rdw-editor-main > div > div > div > div > div:nth-child(23) {
- margin-bottom: 10px;
-}
diff --git a/frontend/src/components/__tests__/ContentFromFeedByTag.js b/frontend/src/components/__tests__/ContentFromFeedByTag.js
index 57bc59f169..354e88a38a 100644
--- a/frontend/src/components/__tests__/ContentFromFeedByTag.js
+++ b/frontend/src/components/__tests__/ContentFromFeedByTag.js
@@ -45,9 +45,15 @@ const DEFAULT_RESPONSE = `
describe('ContentFromFeedByTag', () => {
afterEach(() => fetchMock.restore());
- const renderContentFromFeed = (tag = 'tag', content = DEFAULT_RESPONSE, selector = null) => {
+ const renderContentFromFeed = (
+ tag = 'tag',
+ content = DEFAULT_RESPONSE,
+ selector = null,
+ openLinksInNewTab = false,
+ ) => {
fetchMock.get(`/api/feeds/item?tag=${tag}`, content);
- render();
+ // eslint-disable-next-line max-len
+ render();
};
it('renders a feed', async () => {
@@ -112,4 +118,78 @@ describe('ContentFromFeedByTag', () => {
expect(readOnly).toBeTruthy();
});
});
+
+ it('properly formats support type response (as an example)', async () => {
+ const supportTypeResponse = `
+
+ Tag ttahub-tta-support-type
+
+ Confluence Syndication Feed
+ https://acf-ohs.atlassian.net/wiki
+
+ OHS guidance on TTA support types
+
+
+
+
+
+
+
+
+ User Author
+
+ tag:acf-ohs.atlassian.net,2009:page-184516720-11
+ 2024-09-13T15:11:34Z
+ 2024-09-13T15:11:34Z
+ <div class="feed"> <p>
+ Page
+ <b>edited</b> by
+ <a >User Author</a>
+ </p>
+ <div style="border-top: 1px solid #ddd; border-bottom: 1px solid #ddd; padding: 10px;">
+ <p>Support types are assigned at the objective level for each AR or TR. </p><p /><h2 id="OHSguidanceonTTAsupporttypes-TTAsupporttype"><strong>TTA support type</strong></h2><p>TTA support types describe the content of the TTA session and what that content was intended to support the recipient to accomplish. While the support types do build upon each other, there is no expectation that every goal will start with “Introducing” and end with “Maintaining”. Specialists should use the support types to describe the highest level of support offered during the session. When selecting support types consider how the content supports the recipient with:</p><h3 id="OHSguidanceonTTAsupporttypes-Introducing"><strong>Introducing</strong></h3><p>Introducing and assessing knowledge and/or awareness of concepts, subject matter, and practices.</p><p>Use this type for TTA activities that include content such as:</p><ul><li><p>introducing concepts or new practices</p></li><li><p>assessing participant knowledge</p></li><li><p>needs assessments</p></li></ul><h3 id="OHSguidanceonTTAsupporttypes-Planning"><strong>Planning</strong></h3><p>Planning to initiate new/revised services and systems.</p><p>Use this type for TTA activities that include content that involves participants developing a plan such as a coaching plan, staff wellness plan, corrective action plan, etc.</p><h3 id="OHSguidanceonTTAsupporttypes-Implementing"><strong>Implementing</strong></h3><p>Implementing new/revised services and systems.</p><p>Use this type for TTA activities that include content such as:</p><ul><li><p>developing or revising policies and procedures to address a service/system</p></li><li><p>training for staff to implement a new initiative</p></li></ul><h3 id="OHSguidanceonTTAsupporttypes-Maintaining"><strong>Maintaining</strong></h3><p>Maintaining and monitoring services and systems and ensuring ongoing quality improvement.</p><p>Use this type for TTA activities that include content such as:</p><ul><li><p>reviewing data to identify needed course corrections</p></li><li><p>reviewing ongoing monitoring data</p></li><li><p>conducting ongoing monitoring</p></li><li><p>reviewing progress on program goals</p></li></ul><hr/><h2 style="text-align: center;" id="OHSguidanceonTTAsupporttypes-Needmorehelp?">Need more help?</h2><p style="text-align: center;">If you can’t find an answer, <a class="external-link" href="https://app.smartsheetgov.com/b/form/f0b4725683f04f349a939bd2e3f5425a" rel="nofollow">contact support</a>.</p>
+ </div>
+ <div style="padding: 10px 0;">
+ <a href="https://acf-ohs.atlassian.net/wiki/spaces/OHSTTA/pages/184516720/OHS+guidance+on+TTA+support+types">email.notification.view.online</a>
+ ·
+ <a href="https://acf-ohs.atlassian.net/wiki/pages/diffpagesbyversion.action?pageId=184516720&revisedVersion=11&originalVersion=10">View Changes Online</a>
+ </div>
+</div>
+ User Author
+ 2024-09-13T15:11:34Z
+
+`;
+
+ act(() => {
+ renderContentFromFeed(
+ 'tag',
+ supportTypeResponse,
+ null,
+ true,
+ );
+ });
+
+ const article = document.querySelector('.ttahub-feed-article-content');
+ expect(article).not.toBeNull();
+ const lists = article.querySelectorAll('ul');
+ lists.forEach((list) => {
+ expect(list).toHaveClass('usa-list');
+ });
+
+ const tables = article.querySelectorAll('table');
+ tables.forEach((table) => {
+ expect(table).toHaveClass('usa-table');
+ });
+
+ const paragraphs = article.querySelectorAll('p');
+ paragraphs.forEach((paragraph) => {
+ expect(paragraph).toHaveClass('usa-prose');
+ });
+
+ const links = article.querySelectorAll('a');
+ links.forEach((link) => {
+ expect(link).toHaveAttribute('target', '_blank');
+ expect(link).toHaveAttribute('rel', 'noopener noreferrer');
+ });
+ });
});
diff --git a/frontend/src/pages/Notifications/components/WhatsNew.scss b/frontend/src/pages/Notifications/components/WhatsNew.scss
index 8836a4d33d..d03a54ac3c 100644
--- a/frontend/src/pages/Notifications/components/WhatsNew.scss
+++ b/frontend/src/pages/Notifications/components/WhatsNew.scss
@@ -8,6 +8,10 @@
padding-left: 2rem;
}
+.ttahub-feed-whats-new .ttahub-feed-article-content .feed div:last-child{
+ display: none;
+}
+
// this adds the little green circle to the left of the "new" notification
.ttahub-feed-whats-new .ttahub-feed-article--unread .ttahub-feed-article-content:before {
content: '';
diff --git a/frontend/src/pages/RecipientRecord/pages/components/ClassReview.scss b/frontend/src/pages/RecipientRecord/pages/components/ClassReview.scss
index f19b9ee26b..7673166e7c 100644
--- a/frontend/src/pages/RecipientRecord/pages/components/ClassReview.scss
+++ b/frontend/src/pages/RecipientRecord/pages/components/ClassReview.scss
@@ -24,3 +24,10 @@
margin-bottom: 12px;
padding-bottom: 0;
}
+
+.ttahub-class-feed-article .ttahub-feed-article p:has(strong){
+ text-align: left;
+}
+.ttahub-class-feed-article .ttahub-feed-article th .usa-prose {
+ margin: 0;
+}
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"}}}
diff --git a/frontend/yarn.lock b/frontend/yarn.lock
index ab9018c838..d2879d71e9 100644
--- a/frontend/yarn.lock
+++ b/frontend/yarn.lock
@@ -5026,12 +5026,21 @@ dom-serializer@^1.0.1:
domhandler "^4.2.0"
entities "^2.0.0"
+dom-serializer@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53"
+ integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==
+ dependencies:
+ domelementtype "^2.3.0"
+ domhandler "^5.0.2"
+ entities "^4.2.0"
+
domelementtype@1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f"
integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==
-domelementtype@^2.0.1, domelementtype@^2.2.0:
+domelementtype@^2.0.1, domelementtype@^2.2.0, domelementtype@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d"
integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==
@@ -5043,6 +5052,13 @@ domexception@^2.0.1:
dependencies:
webidl-conversions "^5.0.0"
+domhandler@5.0.3, domhandler@^5.0.2, domhandler@^5.0.3:
+ version "5.0.3"
+ resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31"
+ integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==
+ dependencies:
+ domelementtype "^2.3.0"
+
domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.1:
version "4.3.1"
resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.1.tgz#8d792033416f59d68bc03a5aa7b018c1ca89279c"
@@ -5072,6 +5088,15 @@ domutils@^2.5.2, domutils@^2.8.0:
domelementtype "^2.2.0"
domhandler "^4.2.0"
+domutils@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.1.0.tgz#c47f551278d3dc4b0b1ab8cbb42d751a6f0d824e"
+ integrity sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==
+ dependencies:
+ dom-serializer "^2.0.0"
+ domelementtype "^2.3.0"
+ domhandler "^5.0.3"
+
dot-case@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751"
@@ -5162,7 +5187,7 @@ ee-first@1.1.1:
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==
-ejs@^3.1.10, ejs@^3.1.6:
+ejs@^3.1.10, ejs@^3.1.6, ejs@^3.1.7:
version "3.1.10"
resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.10.tgz#69ab8358b14e896f80cc39e62087b88500c3ac3b"
integrity sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==
@@ -5248,6 +5273,11 @@ entities@^2.0.0:
resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55"
integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==
+entities@^4.2.0, entities@^4.5.0:
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48"
+ integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==
+
error-ex@^1.3.1:
version "1.3.2"
resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
@@ -6768,6 +6798,14 @@ hsluv@^0.0.3:
resolved "https://registry.yarnpkg.com/hsluv/-/hsluv-0.0.3.tgz#829107dafb4a9f8b52a1809ed02e091eade6754c"
integrity sha512-08iL2VyCRbkQKBySkSh6m8zMUa3sADAxGVWs3Z1aPcUkTJeK0ETG4Fc27tEmQBGUAXZjIsXOZqBvacuVNSC/fQ==
+html-dom-parser@5.0.7:
+ version "5.0.7"
+ resolved "https://registry.yarnpkg.com/html-dom-parser/-/html-dom-parser-5.0.7.tgz#33f029b34e8ec4076b7e2624c97debc79abb0c75"
+ integrity sha512-2YD2/yB0QgrlkBIn0CsGaRXC89E1gtuPVpiOGC52NTzPCC83n0WMdGD+5q7lpcKqbCpnWValQbovuy/NI/0kag==
+ dependencies:
+ domhandler "5.0.3"
+ htmlparser2 "9.1.0"
+
html-encoding-sniffer@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3"
@@ -6798,6 +6836,16 @@ html-minifier-terser@^6.0.2:
relateurl "^0.2.7"
terser "^5.10.0"
+html-react-parser@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/html-react-parser/-/html-react-parser-5.1.1.tgz#9863709ab1bb5d15bce273253b539a6dd4fa28e2"
+ integrity sha512-L5VK0rKN3VM7uzRH+4wxAL9elvHuCNDjyWKKjcCDR+YWW5Qr7WWSK7+e627DcePVAFi5IMqc+rAU8j/1DpC/Tw==
+ dependencies:
+ domhandler "5.0.3"
+ html-dom-parser "5.0.7"
+ react-property "2.0.2"
+ style-to-js "1.1.10"
+
html-to-draftjs@^1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/html-to-draftjs/-/html-to-draftjs-1.5.0.tgz#0df0eabf429deaedb63f5c859889e2c983606e86"
@@ -6822,6 +6870,16 @@ html2canvas@^1.4.1:
css-line-break "^2.1.0"
text-segmentation "^1.0.3"
+htmlparser2@9.1.0:
+ version "9.1.0"
+ resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-9.1.0.tgz#cdb498d8a75a51f739b61d3f718136c369bc8c23"
+ integrity sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==
+ dependencies:
+ domelementtype "^2.3.0"
+ domhandler "^5.0.3"
+ domutils "^3.1.0"
+ entities "^4.5.0"
+
htmlparser2@^6.1.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7"
@@ -7030,6 +7088,11 @@ ini@^1.3.5:
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
+inline-style-parser@0.2.2:
+ version "0.2.2"
+ resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.2.2.tgz#d498b4e6de0373458fc610ff793f6b14ebf45633"
+ integrity sha512-EcKzdTHVe8wFVOGEYXiW9WmJXPjqi1T+234YpJr98RiFYKHV3cdy1+3mkTE+KHTHxFFLH51SfaGOoUdW+v7ViQ==
+
internal-slot@^1.0.3:
version "1.0.4"
resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.4.tgz#8551e7baf74a7a6ba5f749cfb16aa60722f0d6f3"
@@ -10202,6 +10265,11 @@ react-plotly.js@^2.5.1:
dependencies:
prop-types "^15.8.1"
+react-property@2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/react-property/-/react-property-2.0.2.tgz#d5ac9e244cef564880a610bc8d868bd6f60fdda6"
+ integrity sha512-+PbtI3VuDV0l6CleQMsx2gtK0JZbZKbpdu5ynr+lbsuvtmgbNcS3VM0tuY2QjFNOcWxvXeHjDpy42RO+4U2rug==
+
react-redux@^7.1.0:
version "7.2.9"
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.9.tgz#09488fbb9416a4efe3735b7235055442b042481d"
@@ -11449,6 +11517,20 @@ style-loader@^3.3.1:
resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.1.tgz#057dfa6b3d4d7c7064462830f9113ed417d38575"
integrity sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ==
+style-to-js@1.1.10:
+ version "1.1.10"
+ resolved "https://registry.yarnpkg.com/style-to-js/-/style-to-js-1.1.10.tgz#ec20e1264ba11dc7f71b94b3a3a05566ed856e54"
+ integrity sha512-VC7MBJa+y0RZhpnLKDPmVRLRswsASLmixkiZ5R8xZpNT9VyjeRzwnXd2pBzAWdgSGv/pCNNH01gPCCUsB9exYg==
+ dependencies:
+ style-to-object "1.0.5"
+
+style-to-object@1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-1.0.5.tgz#5e918349bc3a39eee3a804497d97fcbbf2f0d7c0"
+ integrity sha512-rDRwHtoDD3UMMrmZ6BzOW0naTjMsVZLIjsGleSKS/0Oz+cgCfAPRspaqJuE8rDzpKha/nEvnM0IF4seEAZUTKQ==
+ dependencies:
+ inline-style-parser "0.2.2"
+
stylehacks@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-5.1.1.tgz#7934a34eb59d7152149fa69d6e9e56f2fc34bcc9"
diff --git a/src/goalServices/goals.js b/src/goalServices/goals.js
index d7b5a84d93..707163c98b 100644
--- a/src/goalServices/goals.js
+++ b/src/goalServices/goals.js
@@ -584,7 +584,7 @@ export async function createOrUpdateGoals(goals) {
if (!objective) {
objective = await Objective.create({
status: objectiveStatus,
- title,
+ title: title.trim(),
goalId: newGoal.id,
createdVia: 'rtr',
});