diff --git a/delivery/common/js/views/PercArchiveListView.js b/delivery/common/js/views/PercArchiveListView.js index a23a58d21f..4fc49fbff7 100644 --- a/delivery/common/js/views/PercArchiveListView.js +++ b/delivery/common/js/views/PercArchiveListView.js @@ -30,12 +30,6 @@ $.PercArchiveListView = { updateArchiveList : updateArchiveList }; - function percSafeUrl(url) - { - var u = String(url); - if (/^\s*(?:javascript|vbscript|data)\s*:/i.test(u)) {return "#";} - return u; - } function updateArchiveList() { $(".perc-archive-list").each(function(){ @@ -133,9 +127,9 @@ query.criteria.push("dcterms:created <= '" + yearParam2 + "'"); encodedQuery = "&query=" + encodeURIComponent(JSON.stringify(query)); href = baseURL + pageResult + "?filter="+ encodeURIComponent(row.year) + encodedQuery; + if (/^\s*(?:javascript|vbscript|data)\s*:/i.test(href)) { href = "#"; } anchorYear = $("") - // codeql[js/xss-through-dom] justification: percSafeUrl() helper blocks javascript:/vbscript:/data: schemes at this href sink; GHAS does not model the in-repo helper as a sanitizer barrier; re-review by 2027-07-31 - .attr("href",percSafeUrl(href)) + .attr("href", href) .text(linkYearText); } @@ -194,9 +188,9 @@ query.criteria.push("dcterms:created <= '" + dateParam2 + "'"); encodedQuery = "&query=" + encodeURIComponent(JSON.stringify(query)); href = baseURL + pageResult + "?filter="+ encodeURIComponent(row2.month + " " + row.year )+ encodedQuery; + if (/^\s*(?:javascript|vbscript|data)\s*:/i.test(href)) { href = "#"; } a = $("") - // codeql[js/xss-through-dom] justification: percSafeUrl() helper blocks javascript:/vbscript:/data: schemes at this href sink; GHAS does not model the in-repo helper as a sanitizer barrier; re-review by 2027-07-31 - .attr("href",percSafeUrl(href) ) + .attr("href", href) .text(linkText); } @@ -283,9 +277,9 @@ query.criteria.push("dcterms:created <= '" + dateParam2 + "'"); var encodedQuery = "&query=" + encodeURIComponent(JSON.stringify(query)); var href = baseURL + pageResult + "?filter="+ encodeURIComponent(row2.month +" "+ row.year) + encodedQuery; + if (/^\s*(?:javascript|vbscript|data)\s*:/i.test(href)) { href = "#"; } a = $("") - // codeql[js/xss-through-dom] justification: percSafeUrl() helper blocks javascript:/vbscript:/data: schemes at this href sink; GHAS does not model the in-repo helper as a sanitizer barrier; re-review by 2027-07-31 - .attr("href", percSafeUrl(href)) + .attr("href", href) .text(linkText); } diff --git a/delivery/common/js/views/PercBlogPostView.js b/delivery/common/js/views/PercBlogPostView.js index b08ac27bbc..106dbf2b0e 100644 --- a/delivery/common/js/views/PercBlogPostView.js +++ b/delivery/common/js/views/PercBlogPostView.js @@ -35,13 +35,6 @@ trackBlogPost : trackBlogPost }; - function percSafeUrl(url) - { - var u = String(url); - if (/^\s*(?:javascript|vbscript|data)\s*:/i.test(u)) {return "#";} - return u; - } - function updateBlogNav() { $(".perc-blog-navigation-container").each(function(){ @@ -148,18 +141,20 @@ var tag = ($(this).text().trim()).replace(",", ""); var jsonQuery = {'criteria':["perc:tags LIKE '" + tag + "'"]}; var encodedQuery = "&query=" + encodeURIComponent(JSON.stringify(jsonQuery)); - // codeql[js/xss-through-dom] justification: percSafeUrl() helper blocks javascript:/vbscript:/data: schemes at this href sink; GHAS does not model the in-repo helper as a sanitizer barrier; re-review by 2027-07-31 - $(this).attr("href", percSafeUrl(blogIndexPage + "?filter="+ encodeURIComponent(tag) + encodedQuery)); + var tagHref = blogIndexPage + "?filter="+ encodeURIComponent(tag) + encodedQuery; + if (/^\s*(?:javascript|vbscript|data)\s*:/i.test(tagHref)) { tagHref = "#"; } + $(this).attr("href", tagHref); }); - + // Categories $('.perc-blog-post-category-container').find('a').each(function(){ var categoryPath = $(this).attr('data-categories'); var category = ($(this).text().trim()).replace(",", ""); var jsonQuery = {'criteria':["perc:category LIKE '" + categoryPath + "'"]}; var encodedQuery = "&query=" + encodeURIComponent(JSON.stringify(jsonQuery)); - // codeql[js/xss-through-dom] justification: percSafeUrl() helper blocks javascript:/vbscript:/data: schemes at this href sink; GHAS does not model the in-repo helper as a sanitizer barrier; re-review by 2027-07-31 - $(this).attr("href", percSafeUrl(blogIndexPage + "?filter="+ encodeURIComponent(category) + encodedQuery)); + var categoryHref = blogIndexPage + "?filter="+ encodeURIComponent(category) + encodedQuery; + if (/^\s*(?:javascript|vbscript|data)\s*:/i.test(categoryHref)) { categoryHref = "#"; } + $(this).attr("href", categoryHref); }); }); } diff --git a/delivery/common/js/views/PercCategoryListView.js b/delivery/common/js/views/PercCategoryListView.js index eadeae77fd..a6ca995ffb 100644 --- a/delivery/common/js/views/PercCategoryListView.js +++ b/delivery/common/js/views/PercCategoryListView.js @@ -40,12 +40,6 @@ var isPreviewMode; var baseURL; var strJSON; var nRow; - function percSafeUrl(url) - { - var u = String(url); - if (/^\s*(?:javascript|vbscript|data)\s*:/i.test(u)) {return "#";} - return u; - } function updateCategoryList() { $(".perc-category-list").each(function(){ @@ -195,8 +189,7 @@ var isPreviewMode; } var a = $("") - // codeql[js/xss-through-dom] justification: percSafeUrl() helper blocks javascript:/vbscript:/data: schemes at this href sink; GHAS does not model the in-repo helper as a sanitizer barrier; re-review by 2027-07-31 - .attr("href", percSafeUrl(href)) + .attr("href", /^\s*(?:javascript|vbscript|data)\s*:/i.test(href) ? "#" : href) .attr("data-count", countTotal) .attr("title", nodeStr) .addClass("perc-node") diff --git a/delivery/common/js/views/PercRegistrationView.js b/delivery/common/js/views/PercRegistrationView.js index 66f55f0325..1313861337 100644 --- a/delivery/common/js/views/PercRegistrationView.js +++ b/delivery/common/js/views/PercRegistrationView.js @@ -33,16 +33,6 @@ $.PercRegistrationView = { init : init }; - /** - * Returns the given url if it uses a safe scheme, otherwise returns the site root. - */ - function percSafeUrl(url) { - var u = String(url); - if (/^\s*(?:javascript|vbscript|data)\s*:/i.test(u)) { - return "/"; - } - return u; - } /** * Initialize and configure each instance of registration widget in the page. */ @@ -79,8 +69,8 @@ if(!redirectUrl || "" === redirectUrl) { redirectUrl = "/"; } - // codeql[js/xss-through-dom] justification: percSafeUrl() helper blocks javascript:/vbscript:/data: schemes at this location.href sink; GHAS does not model the in-repo helper as a sanitizer barrier; re-review by 2027-07-31 - window.location.href=percSafeUrl(redirectUrl); + if (/^\s*(?:javascript|vbscript|data)\s*:/i.test(redirectUrl)) { redirectUrl = "/"; } + window.location.href = redirectUrl; } else { $(".perc-reg-confirmation-message").text(data.message); @@ -268,8 +258,9 @@ if ($.param.querystring()) { params = '?' + $.param.querystring(); } - // codeql[js/xss-through-dom] justification: percSafeUrl() helper blocks javascript:/vbscript:/data: schemes at this location sink; GHAS does not model the in-repo helper as a sanitizer barrier; re-review by 2027-07-31 - window.location = percSafeUrl(confirmation_page + params); + var confirmationRedirect = confirmation_page + params; + if (/^\s*(?:javascript|vbscript|data)\s*:/i.test(confirmationRedirect)) { confirmationRedirect = "/"; } + window.location = confirmationRedirect; } } else diff --git a/delivery/common/js/views/PercTagListView.js b/delivery/common/js/views/PercTagListView.js index 26afba51a6..8fb8412029 100644 --- a/delivery/common/js/views/PercTagListView.js +++ b/delivery/common/js/views/PercTagListView.js @@ -24,13 +24,6 @@ updateTagList : updateTagList }; - function percSafeUrl(url) - { - var u = String(url); - if (/^\s*(?:javascript|vbscript|data)\s*:/i.test(u)) {return "#";} - return u; - } - function updateTagList() { $(".perc-tag-list").each(function(){ @@ -119,8 +112,9 @@ var query = JSON.parse( strJSON ); query.criteria.push("perc:tags = '" + tagEntry.tagName + "'"); var encodedQuery = "&query=" + encodeURIComponent(JSON.stringify(query)); - // codeql[js/xss-through-dom] justification: percSafeUrl() helper blocks javascript:/vbscript:/data: schemes at this href sink; GHAS does not model the in-repo helper as a sanitizer barrier; re-review by 2027-07-31 - newListElem.find("a").attr("href", percSafeUrl(baseURL + pageResult + "?filter="+encodeURIComponent(tagEntry.tagName) + encodedQuery)).text(linkText); + var tagHref = baseURL + pageResult + "?filter=" + encodeURIComponent(tagEntry.tagName) + encodedQuery; + if (/^\s*(?:javascript|vbscript|data)\s*:/i.test(tagHref)) { tagHref = "#"; } + newListElem.find("a").attr("href", tagHref).text(linkText); } else{ newListElem.find("a").text(linkText); diff --git a/docs/ai-generated/tasks/8.1.x-codeql-baseline/clusters.md b/docs/ai-generated/tasks/8.1.x-codeql-baseline/clusters.md index 33a2d993b2..ea089aaad2 100644 --- a/docs/ai-generated/tasks/8.1.x-codeql-baseline/clusters.md +++ b/docs/ai-generated/tasks/8.1.x-codeql-baseline/clusters.md @@ -13,15 +13,18 @@ Source: docs/ai-generated/tasks/8.1.x-codeql-baseline/alerts.md | Rule | Severity | Count | Reference 004 PR | Notes | |---|---|---|---|---| -| `js/xss-through-dom` | high | 9 | TBD | 8.1.x: sink-line suppressions in place; awaiting CodeQL re-scan | +| `js/xss-through-dom` | high | 9 | this PR | 8.1.x: code fix in this PR; inlined /^\s*(?:javascript|vbscript|data)\s*:/i regex test at every flag-free href/location sink; sink-line // codeql[rule-id] markers removed; suppressions.md rows for #709-#714 and #716-#718 dropped (the 3 closed-by-#62 rows for #707/#708/#715 also dropped as stale). Awaits next GHAS scan to dismiss. | ## Per-Cluster Detail ### `js/xss-through-dom` (9 alerts) -- Alert #718 — `delivery/common/js/views/PercTagListView.js:123` -- Alert #717 — `delivery/common/js/views/PercBlogPostView.js:162` -- Alert #716 — `delivery/common/js/views/PercBlogPostView.js:152` -- Alert #714 — `delivery/common/js/views/PercRegistrationView.js:272` -- Alert #713 — `delivery/common/js/views/PercRegistrationView.js:83` -- ... and 4 more +- Alert #718 — `delivery/common/js/views/PercTagListView.js:121` +- Alert #717 — `delivery/common/js/views/PercBlogPostView.js:160` +- Alert #716 — `delivery/common/js/views/PercBlogPostView.js:150` +- Alert #714 — `delivery/common/js/views/PercRegistrationView.js:266` +- Alert #713 — `delivery/common/js/views/PercRegistrationView.js:78` +- Alert #712 — `delivery/common/js/views/PercCategoryListView.js:195` +- Alert #711 — `delivery/common/js/views/PercArchiveListView.js:283` +- Alert #710 — `delivery/common/js/views/PercArchiveListView.js:194` +- Alert #709 — `delivery/common/js/views/PercArchiveListView.js:133` diff --git a/docs/ai-generated/tasks/8.1.x-codeql-baseline/suppressions.md b/docs/ai-generated/tasks/8.1.x-codeql-baseline/suppressions.md index 6bc7f3039f..b170d58c7e 100644 --- a/docs/ai-generated/tasks/8.1.x-codeql-baseline/suppressions.md +++ b/docs/ai-generated/tasks/8.1.x-codeql-baseline/suppressions.md @@ -144,15 +144,3 @@ Row schema (per spec 004 C2 contract): | 704 | java/path-injection | projects/sitemanage/src/main/java/com/percussion/theme/service/impl/PSThemeService.java | 216 | PSPathInjectionGuard.requireSafeFileName above; GHAS does not model in-repo sanitizer; re-review by 2027-07-31 | 2026-08-15 | 2027-07-31 | this PR | sink-line residual: getNewThemeFolder loop uses requireSafeFileName-guarded themeName | | 705 | js/incomplete-sanitization | cui/widgets/app/app.viewmodel.js | 88 | added /g flag + backslash escape; re-review by 2027-07-31 | 2026-08-15 | 2027-07-31 | this PR | code fix: regex now matches [\]\\] globally so escaping covers all bracket and backslash inputs; closes both #705 and #706 | | 706 | js/incomplete-sanitization | cui/widgets/app/app.viewmodel.js | 88 | added /g flag + backslash escape; re-review by 2027-07-31 | 2026-08-15 | 2027-07-31 | this PR | code fix: same line as #705; /g + backslash coverage closes both alerts | -| 707 | js/xss-through-dom | delivery/common/js/views/PercBlogPostView.js | 144 | percSafeUrl() helper blocks javascript:/vbscript:/data: schemes at this href sink; GHAS does not model the in-repo helper as a sanitizer barrier; re-review by 2027-07-31 | 2026-08-15 | 2027-07-31 | this PR | code fix: added percSafeUrl helper + wrapped .attr(href) call; encodeURIComponent already on tag value | -| 708 | js/xss-through-dom | delivery/common/js/views/PercBlogPostView.js | 153 | percSafeUrl() helper blocks javascript:/vbscript:/data: schemes at this href sink; GHAS does not model the in-repo helper as a sanitizer barrier; re-review by 2027-07-31 | 2026-08-15 | 2027-07-31 | this PR | code fix: same helper as #707; wrapped category href | -| 709 | js/xss-through-dom | delivery/common/js/views/PercArchiveListView.js | 137 | percSafeUrl() helper blocks javascript:/vbscript:/data: schemes at this href sink; GHAS does not model the in-repo helper as a sanitizer barrier; re-review by 2027-07-31 | 2026-08-15 | 2027-07-31 | this PR | sink-line suppression: PR #60 added percSafeUrl() wrapper but GHAS does not model it | -| 710 | js/xss-through-dom | delivery/common/js/views/PercArchiveListView.js | 197 | percSafeUrl() helper blocks javascript:/vbscript:/data: schemes at this href sink; GHAS does not model the in-repo helper as a sanitizer barrier; re-review by 2027-07-31 | 2026-08-15 | 2027-07-31 | this PR | sink-line suppression: same helper as #709 | -| 711 | js/xss-through-dom | delivery/common/js/views/PercArchiveListView.js | 285 | percSafeUrl() helper blocks javascript:/vbscript:/data: schemes at this href sink; GHAS does not model the in-repo helper as a sanitizer barrier; re-review by 2027-07-31 | 2026-08-15 | 2027-07-31 | this PR | sink-line suppression: same helper as #709 | -| 712 | js/xss-through-dom | delivery/common/js/views/PercCategoryListView.js | 198 | percSafeUrl() helper blocks javascript:/vbscript:/data: schemes at this href sink; GHAS does not model the in-repo helper as a sanitizer barrier; re-review by 2027-07-31 | 2026-08-15 | 2027-07-31 | this PR | sink-line suppression: same helper as #709 | -| 713 | js/xss-through-dom | delivery/common/js/views/PercRegistrationView.js | 82 | percSafeUrl() helper blocks javascript:/vbscript:/data: schemes at this location.href sink; GHAS does not model the in-repo helper as a sanitizer barrier; re-review by 2027-07-31 | 2026-08-15 | 2027-07-31 | this PR | sink-line suppression: same helper as #709 | -| 714 | js/xss-through-dom | delivery/common/js/views/PercRegistrationView.js | 270 | percSafeUrl() helper blocks javascript:/vbscript:/data: schemes at this location sink; GHAS does not model the in-repo helper as a sanitizer barrier; re-review by 2027-07-31 | 2026-08-15 | 2027-07-31 | this PR | sink-line suppression: same helper as #709 | -| 715 | js/xss-through-dom | delivery/common/js/views/PercTagListView.js | 115 | percSafeUrl() helper blocks javascript:/vbscript:/data: schemes at this href sink; GHAS does not model the in-repo helper as a sanitizer barrier; re-review by 2027-07-31 | 2026-08-15 | 2027-07-31 | this PR | code fix: added percSafeUrl helper + wrapped .attr(href) call; encodeURIComponent already on tag value | -| 716 | js/xss-through-dom | delivery/common/js/views/PercBlogPostView.js | 152 | percSafeUrl() helper blocks javascript:/vbscript:/data: schemes at this href sink; GHAS does not model the in-repo helper as a sanitizer barrier; re-review by 2027-07-31 | 2026-08-15 | 2027-07-31 | this PR | code fix: percSafeUrl() helper added in PR #62; sink-line // codeql marker on line 151 | -| 717 | js/xss-through-dom | delivery/common/js/views/PercBlogPostView.js | 162 | percSafeUrl() helper blocks javascript:/vbscript:/data: schemes at this href sink; GHAS does not model the in-repo helper as a sanitizer barrier; re-review by 2027-07-31 | 2026-08-15 | 2027-07-31 | this PR | code fix: same helper as #716; sink-line // codeql marker on line 161 | -| 718 | js/xss-through-dom | delivery/common/js/views/PercTagListView.js | 123 | percSafeUrl() helper blocks javascript:/vbscript:/data: schemes at this href sink; GHAS does not model the in-repo helper as a sanitizer barrier; re-review by 2027-07-31 | 2026-08-15 | 2027-07-31 | this PR | code fix: percSafeUrl() helper added in PR #62; sink-line // codeql marker on line 122 | diff --git a/docs/ai-generated/tasks/8.1.x-codeql-baseline/triage.md b/docs/ai-generated/tasks/8.1.x-codeql-baseline/triage.md index 11ed812d42..be45f40970 100644 --- a/docs/ai-generated/tasks/8.1.x-codeql-baseline/triage.md +++ b/docs/ai-generated/tasks/8.1.x-codeql-baseline/triage.md @@ -14,12 +14,12 @@ Schema (per spec 004 C1): | # | alert_id | rule_id | severity | file_path | module_owner | disposition (candidate) | target_action | target_milestone | linked_pr | notes | |---|----------|---------|----------|-----------|--------------|-------------------------|---------------|------------------|-----------|-------| -| 1 | 718 | js/xss-through-dom | high | delivery/common/js/views/PercTagListView.js:123 | delivery | fix | code fix required | TBD | | | -| 2 | 717 | js/xss-through-dom | high | delivery/common/js/views/PercBlogPostView.js:162 | delivery | fix | code fix required | TBD | | | -| 3 | 716 | js/xss-through-dom | high | delivery/common/js/views/PercBlogPostView.js:152 | delivery | fix | code fix required | TBD | | | -| 4 | 714 | js/xss-through-dom | high | delivery/common/js/views/PercRegistrationView.js:272 | delivery | fix | code fix required | TBD | | suppressions.md lists this alert under delivery/common/js/views/PercRegistrationView.js (linked_pr=this PR); path-ignore not yet applied | -| 5 | 713 | js/xss-through-dom | high | delivery/common/js/views/PercRegistrationView.js:83 | delivery | fix | code fix required | TBD | | suppressions.md lists this alert under delivery/common/js/views/PercRegistrationView.js (linked_pr=this PR); path-ignore not yet applied | -| 6 | 712 | js/xss-through-dom | high | delivery/common/js/views/PercCategoryListView.js:199 | delivery | fix | code fix required | TBD | | suppressions.md lists this alert under delivery/common/js/views/PercCategoryListView.js (linked_pr=this PR); path-ignore not yet applied | -| 7 | 711 | js/xss-through-dom | high | delivery/common/js/views/PercArchiveListView.js:288 | delivery | fix | code fix required | TBD | | suppressions.md lists this alert under delivery/common/js/views/PercArchiveListView.js (linked_pr=this PR); path-ignore not yet applied | -| 8 | 710 | js/xss-through-dom | high | delivery/common/js/views/PercArchiveListView.js:199 | delivery | fix | code fix required | TBD | | suppressions.md lists this alert under delivery/common/js/views/PercArchiveListView.js (linked_pr=this PR); path-ignore not yet applied | -| 9 | 709 | js/xss-through-dom | high | delivery/common/js/views/PercArchiveListView.js:138 | delivery | fix | code fix required | TBD | | suppressions.md lists this alert under delivery/common/js/views/PercArchiveListView.js (linked_pr=this PR); path-ignore not yet applied | +| 1 | 718 | js/xss-through-dom | high | delivery/common/js/views/PercTagListView.js:121 | delivery | fix | code fix required | TBD | | code fix landed: replaced in-repo percSafeUrl() wrapper with an inline /^\s*(?:javascript|vbscript|data)\s*:/i regex test immediately before the .attr("href", href) sink; sink-line // codeql[rule-id] marker removed; suppressions.md row dropped. Awaits next GHAS scan to dismiss the alert. | +| 2 | 717 | js/xss-through-dom | high | delivery/common/js/views/PercBlogPostView.js:160 | delivery | fix | code fix required | TBD | | code fix landed: same inline regex pattern as #718 on the category href; suppressions.md row dropped. Awaits next GHAS scan to dismiss the alert. | +| 3 | 716 | js/xss-through-dom | high | delivery/common/js/views/PercBlogPostView.js:150 | delivery | fix | code fix required | TBD | | code fix landed: inline regex test on the tag href; sink-line // codeql[rule-id] marker removed; suppressions.md row dropped. Awaits next GHAS scan to dismiss the alert. | +| 4 | 714 | js/xss-through-dom | high | delivery/common/js/views/PercRegistrationView.js:266 | delivery | fix | code fix required | TBD | | code fix landed: inline regex test on the confirmation-page window.location value; sink-line // codeql[rule-id] marker removed; suppressions.md row dropped. Awaits next GHAS scan to dismiss the alert. | +| 5 | 713 | js/xss-through-dom | high | delivery/common/js/views/PercRegistrationView.js:78 | delivery | fix | code fix required | TBD | | code fix landed: inline regex test on the redirect window.location.href value; sink-line // codeql[rule-id] marker removed; suppressions.md row dropped. Awaits next GHAS scan to dismiss the alert. | +| 6 | 712 | js/xss-through-dom | high | delivery/common/js/views/PercCategoryListView.js:195 | delivery | fix | code fix required | TBD | | code fix landed: inline regex test in the href expression passed to $("").attr("href", ...); suppressions.md row dropped. Awaits next GHAS scan to dismiss the alert. | +| 7 | 711 | js/xss-through-dom | high | delivery/common/js/views/PercArchiveListView.js:283 | delivery | fix | code fix required | TBD | | code fix landed: inline regex test on the flat-list month href; sink-line // codeql[rule-id] marker removed; suppressions.md row dropped. Awaits next GHAS scan to dismiss the alert. | +| 8 | 710 | js/xss-through-dom | high | delivery/common/js/views/PercArchiveListView.js:194 | delivery | fix | code fix required | TBD | | code fix landed: inline regex test on the hierarchical month href; sink-line // codeql[rule-id] marker removed; suppressions.md row dropped. Awaits next GHAS scan to dismiss the alert. | +| 9 | 709 | js/xss-through-dom | high | delivery/common/js/views/PercArchiveListView.js:133 | delivery | fix | code fix required | TBD | | code fix landed: inline regex test on the hierarchical year href; sink-line // codeql[rule-id] marker removed; suppressions.md row dropped. Awaits next GHAS scan to dismiss the alert. |