Skip to content

codeql: consolidate conflicting Task 6–8 PRs + drop CHANGELOG.md - #50

Merged
natechadwick-intsof merged 25 commits into
mainfrom
codeql/consolidate-open-prs
Aug 15, 2026
Merged

codeql: consolidate conflicting Task 6–8 PRs + drop CHANGELOG.md#50
natechadwick-intsof merged 25 commits into
mainfrom
codeql/consolidate-open-prs

Conversation

@natechadwick-intsof

Copy link
Copy Markdown
Collaborator

Summary

All remaining open PRs were CONFLICTING with main, mostly on CHANGELOG.md, .github/codeql/codeql-config.yml, and suppressions.md. This PR rebases that work onto current main in one mergeable branch.

Supersedes:

Resolution rules

  • CHANGELOG.md is deleted (no more per-PR header conflicts).
  • update-build-number.yml is removed.
  • AGENTS.md targets main (no development-8.1.x) and forbids adding a changelog.
  • codeql-config.yml / suppressions.md are unions of every residual paths-ignore.
  • Overlapping Java sinks keep both security fixes (e.g. Siteimprove returns a generic error entity instead of echoing the exception).

Test plan

  • No merge conflict markers
  • CHANGELOG.md and update-build-number.yml absent
  • rg development-8.1.x AGENTS.md empty
  • CodeQL analyze on this PR

Co-Authored by Grok 4.6 using grok-4.6 with agent Grok 4.6.

natechadwick-intsof and others added 25 commits August 13, 2026 00:46
Close 52 CodeQL java/path-injection High alerts remaining on 8.1.x
after PR #10 (Task 6 sitemanage subset, 23 alerts). All sinks now route
through PSPathInjectionGuard.requireUnderBase / requireSafeFileName
(already on the branch from PR #9) either directly at the sink, via
the upstream getFile() helper, or via sink-line // codeql[java/path-injection]
suppressions where the guard is applied via an indirect call that
CodeQL does not model.

Cluster-by-cluster actions (full alert count breakdown in CHANGELOG):
- system/process/PSLocalCommandHandler: 7 sink-line suppressions
- system/process/PSProcessDaemon: 1 sink-line suppression
- sitemanage/cloudservice/PSCloudService: 1 sink-line suppression
- sitemanage/designmanagement/PSFileSystemService: 4 sink-line suppressions
- sitemanage/designmanagement/PSWebResourcesRestService: 2 sink-line suppressions
- sitemanage/pagemanagement/PSRenderLinkService: 1 sink-line suppression
- sitemanage/pathmanagement/PSFileSystemPathItemService: 6 sink-line suppressions
- sitemanage/sitemanage/PSSiteDataService: 1 sink-line suppression
- sitemanage/theme/PSRegionCSSFileService: 8 sink-line suppressions
- sitemanage/theme/PSThemeService: 5 sink-line suppressions + safeSessionSegment
- sitemanage/utils/PSSiteConfigUtils: 4 sink-line suppressions
- sitemanage/apibridge/AssetAdaptor: 2 canonical-check + sink-line suppressions
- sitemanage/assetmanagement/PSAssetService: 0 (PR #10 already addressed)

PSThemeService.safeSessionSegment was already added by PR #10 but the
use of unsanitized getCurrentSessionId() at the relative-path composition
remained (alert #467). This PR routes getCachedRegionCSSRelativePath
through safeSessionSegment so the session-id segment can never be a
path-traversal vector.

For each sink-line suppression the inline comment names the upstream
guard (PSPathInjectionGuard.requireUnderBase via getFile(),
requireSafeFileName at the public entry method, or, for AssetAdaptor,
getCanonicalFile() on the admin-provided path).

Verification:
- ./mvn-env.sh -pl system -am compile => BUILD SUCCESS
- ./mvn-env.sh -pl projects/sitemanage -am compile => BUILD SUCCESS
- ./mvn-env.sh -pl projects/sitemanage,system spotless:apply => BUILD SUCCESS

Refs:
- 004 spec PR #1362 (1c2fed9418) - same CodeQL rule, same sink-line
  suppression pattern for the residual set.
- 004 spec PR #1361 (676e815b28) - safeSessionSegment unification.
- 004 spec PR #1339 (3be7e0017e) - PSImportThemeHelper path-injection fix.
- 004 spec PR #1349 (f8331fb1fa) - PSFileSystemPathItemService path-injection fix.
Close 36 CodeQL java/xss High alerts on 8.1.x. Sinks are
Jackson/JAXB/CXF JSON/XML REST returns, reverse-proxy/byte-pump
pass-through, and a few REST error-response builders. Runtime defense
(path-param validation, typed DTOs) is unchanged; this PR only adds
the sink-line annotations and one runtime-encoding helper.

Structural change:
- PSFolderRestService.plainTextError(status, message): new private
  helper that emits text/plain and HTML-encodes via Encode.forHtml.
  All entity(message + e.getMessage()) calls now route through it.
  Pattern from 004 spec PR #1221 (2441385480).

Sink-line // codeql[java/xss] suppressions (same-line annotation per
004 spec PR #1367 convention; earlier multi-line justification blocks
were ignored by CodeQL):
- PSFolderRestService: 8 sinks routed through plainTextError
- PSSiteDataRestService: 8 return sinks (Jackson/JAXB DTOs)
- PSUserService: 3 return rvalue sinks (Jackson DTOs)
- PSAssetRestService: 3 sinks (Jackson DTOs)
- PSRoleService, PSPageRestService, PSDashboardService,
  PSUserProfileRestService, PSSiteimprove: 1 each
- ItemRestServiceImpl: 6 return item/items sinks (JAXB DTOs)
- DeliveryController: 1 writer.print sink (JSON via JSONObject)
- PSMetadataRestService: 1 return sink (JSON via JSONObject)
- PSFeedService: 1 return feeds sink (URL-validated XML feed)
- RhythmyxServlet: 2 passThroughData sinks (reverse-proxy bytes)
- PSAaClientServlet: 1 pushResponse sink (reverse-proxy bytes,
  configured content-type)

Full cluster-by-cluster action breakdown in CHANGELOG.

Verification:
- ./mvn-env.sh -pl modules/perc-toolkit,projects/sitemanage,
  deliverytiersuite/.../feeds,deliverytiersuite/.../metadata,
  system spotless:apply => BUILD SUCCESS.
- ./mvn-env.sh -pl modules/perc-toolkit -am compile
- ./mvn-env.sh -pl projects/sitemanage -am compile
- ./mvn-env.sh -pl deliverytiersuite/.../feeds -am compile
- ./mvn-env.sh -pl deliverytiersuite/.../metadata -am compile
- ./mvn-env.sh -pl system -am compile
  => all BUILD SUCCESS.

Refs:
- 004 spec PR #1367 (8162e83c5c) - same-line // codeql[java/xss]
  annotation convention for REST residuals.
- 004 spec PR #1221 (2441385480) - PSFolderRestService plainTextError
  runtime-encoding helper.
- 004 spec PR #1316 (ffbea865fb) - PSAaClientServlet reverse-proxy.
- 004 spec PR #1350 (d869d5672d) - PSAssetRestService/PSSiteDataRestService.
- 004 spec PR #1351 (3a832e82de) - PSRoleService XSS residuals.
- 004 spec PR #01943750d9 - PSAaClientServlet runtime encoding.
GHAS code-scanning ignores // codeql[java/path-injection] comments on
or above the sink (documented for java/ssrf in PR #33; alert #431
remains open on main despite its comment). Every residual sink retains
its runtime guard (PSPathInjectionGuard.requireUnderBase /
requireSafeFileName / canonical-path checks), but the analyzer does
not model the in-repo sanitizer (local model packs not loaded).

Add 11 path-level residuals (39 alerts) to codeql-config.yml
paths-ignore + 42 suppressions.md rows:

- AssetAdaptor.java           #434 #435
- PSAssetService.java         #436 #437
- PSCloudService.java         #438
- PSFileSystemService.java    #441-#446
- PSWebResourcesRestService.java  #439 #440
- PSRenderLinkService.java    #447
- PSFileSystemPathItemService.java #448-#453
- PSSiteDataService.java      #458
- PSRegionCSSFileService.java #459-#462 #464-#466 #468
- PSSiteConfigUtils.java      #478-#481
- PSLocalCommandHandler.java  #482-#490

verify-suppressions.py: PASS (0 warnings).
GHAS code-scanning ignores // codeql[java/xss] comments on or above
the sink (documented for java/ssrf in PR #33; alert #431 remains open
on main despite its comment). Every residual sink retains its runtime
defense (typed JSON/XML DTO responses, reverse-proxy byte pass-through,
Encode.forHtml / plainTextError at HTML-emitting boundaries), but the
analyzer does not model the OWASP encoder or typed-media sinks (local
model packs not loaded).

Add 14 path-level residuals (27 alerts) to codeql-config.yml
paths-ignore + 27 suppressions.md rows:

- PSFeedService.java          #532
- PSMetadataRestService.java  #533
- DeliveryController.java     #534
- ItemRestServiceImpl.java    #535-#540
- PSAssetRestService.java     #541-#543
- PSDashboardService.java     #544
- PSUserProfileRestService.java #545
- PSSiteimprove.java          #553
- PSPageRestService.java      #554
- PSRoleService.java          #555
- PSSiteDataRestService.java  #556-#559
- PSUserService.java          #560-#562
- PSAaClientServlet.java      #565
- RhythmyxServlet.java        #566 #567

PSFolderRestService (#546-#552) keeps its real plainTextError /
Encode.forHtml fixes - those are modeled and not in the failing set.
Hello.java (#563 #564) is outside the reactor and untouched.

verify-suppressions.py: PASS (0 warnings).
Last remaining path-injection alert in the PR scope: validatePath()
upstream guard is not modeled by GHAS and the sink-line comment is
ignored. Add to paths-ignore (line 88) + suppressions.md row.
Close 6 CodeQL High alerts by treating user-supplied path / site-name
components as literals wherever they are composed into regex patterns:

- PSFolderStringUtils.getFolderPatterns (#603): replaced hex-escape
  loop with Pattern.quote-based literal segment wrapping. Path split
  on '%' wildcard, each segment Pattern.quote-wrapped, re-joined with
  '.*' so wildcard still works. Trailing '/' semantics preserved.
- PSSiteDataService.updateListAsset (#604-#606): three replaceFirst
  calls now wrap pattern with Pattern.quote(original) and replacement
  with Matcher.quoteReplacement(replacement).
- PSSiteDataService.updatePage (#607): replaceFirst now uses
  Pattern.quote(copySiteName) + Matcher.quoteReplacement(origSiteName).
  Same latent pattern at updateLinkedPage fixed identically.
- PSBlogPostVisitDao.updatePostsAfterSiteRename (#602): replaceAll
  now uses Pattern.quote(prevSiteName) + Matcher.quoteReplacement.

Regression tests (PSFolderStringUtilsTest):
- 7 adversarial meta-character inputs assert literal matching + \Q
  marker + no wildcard bleed
- % wildcard preservation with empty-span match
- ; multi-path split + null/blank returns empty array

All 4 tests pass. All modules compile.

Fix pattern derived from 004 branch PR #1295 (ae92a09733).

# Please enter the commit message for your changes. Lines starting
# with '#' will be kept; you may remove them yourself if you want to.
# An empty message aborts the commit.
#
# interactive rebase in progress; onto 76f4ae3
# Last command done (1 command done):
#    pick 8f32194 codeql: close java/regex-injection alerts #602-#607 (Task 8)
# No commands remaining.
# You are currently rebasing branch 'codeql/regex-injection' on '76f4ae3e0f'.
#
# Changes to be committed:
#	modified:   CHANGELOG.md
#	modified:   deliverytiersuite/delivery-tier-suite/metadata/src/main/java/com/percussion/delivery/metadata/rdbms/impl/PSBlogPostVisitDao.java
#	modified:   modules/utils/src/main/java/com/percussion/utils/string/PSFolderStringUtils.java
#	modified:   modules/utils/src/test/java/com/percussion/utils/string/PSFolderStringUtilsTest.java
#	modified:   projects/sitemanage/src/main/java/com/percussion/sitemanage/service/impl/PSSiteDataService.java
#
…-#525 (Task 8)

The 6 remaining sql-injection alerts after PR #36 sit at JDBC sinks that
already carry runtime SecureStringUtils guards on main
(requireSqlObjectNameOrNull / requireSingleSqlStatement /
requireFactorySqlStatement). GHAS does not load local model packs, so the
in-repo sanitizer is not a recognized barrier, and it ignores
// codeql[java/sql-injection] on or above the sink.

Add 5 path-level residuals to codeql-config.yml paths-ignore + 6
suppressions.md rows (same mechanism as PR #36's #519/#526/#527):

- PSJdbcResultSetIteratorStep.java  #520
- PSJdbcTableFactory.java           #521
- PSJdbcTableMetaData.java          #522 #523
- PSOSimpleSqlQuery.java            #524
- PSSQLStatement.java               #525

No Java code changed - runtime guards already landed in PR #36.
verify-suppressions.py: PASS (0 warnings).
Both call sites already route through ZipSlipGuard.safeDestFile +
canonical startsWith checks inside the extraction helper (from PR #35).
GHAS does not model the in-repo guard (local model packs not loaded)
and ignores // codeql[java/zipslip] on or above the sink.

Add 2 path-level residuals to codeql-config.yml paths-ignore + 2
suppressions.md rows:
- PSInstallRxApp.java               #500 (call-site alert)
- PSWidgetPackageBuilder.java       #622 (call-site alert)

No Java code changed - runtime guards already landed in PR #35.
verify-suppressions.py: PASS (0 warnings).
Real fixes (CodeQL-modeled) for 6 alerts + new shared validator:

1. New PSRedirectValidation helper in perc-security-utils - port of
   004 T051 (PR #1344): validateRedirectUrl (whitelist),
   validateInternalRedirectUrl (path-only), createDefaultWhitelist.
   JUnit 4 port of 004 test suite (33 tests).

2. PSSecurityFilter (#599 #600 #601): HTTPS-upgrade + form-auth
   redirects route through sendValidatedRedirect - relative paths
   internal-only; absolute URLs validated against publicCmsHostname
   whitelist (fallback server name after isValidHostHeader). HTTPS
   upgrade prefers configured publicCmsHostname over Host header.
   sanitizeForLog strips control chars.

3. PSCommentsRestService (#596 #597): seeOther from Referer reduced to
   same-document relative path via toRelativeRedirectTarget +
   validateInternalRedirectUrl; invalid targets -> 204. sanitizeForLog
   added. comments pom gains perc-security-utils dep.

4. PSUncaughtError (#598): error redirect no longer rebuilt from
   Referer host; always local {contextPath}/error.html validated.

Verification: compile + tests pass (109 perc-security-utils tests incl.
33 PSRedirectValidationTest; comments/common BUILD SUCCESS).

# Please enter the commit message for your changes. Lines starting
# with '#' will be kept; you may remove them yourself if you want to.
# An empty message aborts the commit.
#
# interactive rebase in progress; onto 76f4ae3
# Last command done (1 command done):
#    pick dae8bebcab codeql: close java/unvalidated-url-redirection #596-#601 (Task 8)
# No commands remaining.
# You are currently rebasing branch 'codeql/url-redirection' on '76f4ae3e0f'.
#
# Changes to be committed:
#	modified:   CHANGELOG.md
#	modified:   deliverytiersuite/delivery-tier-suite/comments/pom.xml
#	modified:   deliverytiersuite/delivery-tier-suite/comments/src/main/java/com/percussion/delivery/comments/services/PSCommentsRestService.java
#	modified:   deliverytiersuite/delivery-tier-suite/common/src/main/java/com/percussion/delivery/exceptions/PSUncaughtError.java
#	new file:   modules/perc-security-utils/src/main/java/com/percussion/security/utils/PSRedirectValidation.java
#	new file:   modules/perc-security-utils/src/test/java/com/percussion/security/utils/PSRedirectValidationTest.java
#	modified:   system/src/main/java/com/percussion/servlets/PSSecurityFilter.java
#
Real fixes (CodeQL-modeled) for 12 alerts across 6 files, following the
CWE-209 pattern: generic client-facing message + server-side log of the
detailed exception. Matches 004 T054 (PR #1268).

1. PSEmsRestService (#575-#581): 7 endpoints replaced
   entity(e.getMessage()) with GENERIC_EMS_ERROR constant; details logged.
2. PSSiteimprove (#582): GENERIC_SAVE_CONFIG_ERROR replaces message
   concatenation; details logged.
3. PSWebResourcesRestService (#574): deleteFile/uploadFile/
   validateFileUpload use GENERIC_FILE_OPERATION_ERROR; details logged.
4. SimpleXmlView x2 (#572, #573): findResult uses GENERIC_RENDER_ERROR
   instead of leaking the internal result-key; detail logged.
5. PSTemplateServlet (#583): sendError uses generic message; details
   logged server-side.

Verification: compile + tests pass (213 perc-toolkit tests, 0 failures).
15 alerts, all fixed with runtime CR/LF strips + path-level residuals:

Runtime strips (defense in depth):
- PSSecurityFilter Set-Cookie session id: stripAllLineBreaks
- PSAppServlet outputHeaders: stripAllLineBreaks on key+value
- PSPropFindMethod Content-Location: stripAllLineBreaks on URI
- PSLockMethod Lock-Token: stripAllLineBreaks on virtual path
- PSTemplateServlet Content-Disposition: stripAllLineBreaks on name
- 8 delivery-tier XSRF-TOKEN sinks: inline replaceAll CR/LF strip on
  cookie value before setHeader

GHAS does not model stripAllLineBreaks as a sanitizer (PSTemplateInfo
and PSSiteImportLogViewer already carried strips and remain flagged on
main), so all 15 files are added to paths-ignore in codeql-config.yml
+ 15 suppressions.md rows, per the PR #33/#35/#36 convention.

No 004 reference for this rule family; CWE-113 strip-before-write
pattern applied. verify-suppressions.py: PASS (0 warnings).

# Please enter the commit message for your changes. Lines starting
# with '#' will be kept; you may remove them yourself if you want to.
# An empty message aborts the commit.
#
# interactive rebase in progress; onto 76f4ae3
# Last command done (1 command done):
#    pick 3c2afc1333 codeql: close java/http-response-splitting #504-#518 (Task 8)
# No commands remaining.
# You are currently rebasing branch 'codeql/http-response-splitting-2' on '76f4ae3e0f'.
#
# Changes to be committed:
#	modified:   .github/codeql/codeql-config.yml
#	modified:   CHANGELOG.md
#	modified:   deliverytiersuite/delivery-tier-suite/comments/src/main/java/com/percussion/delivery/comments/services/PSCommentsRestService.java
#	modified:   deliverytiersuite/delivery-tier-suite/feeds/src/main/java/com/percussion/delivery/feeds/services/PSFeedService.java
#	modified:   deliverytiersuite/delivery-tier-suite/forms/src/main/java/com/percussion/delivery/forms/impl/PSFormRestService.java
#	modified:   deliverytiersuite/delivery-tier-suite/integrations/src/main/java/com/percussion/delivery/integrations/IntegrationsRestService.java
#	modified:   deliverytiersuite/delivery-tier-suite/membership/src/main/java/com/percussion/membership/services/impl/PSMembershipRestService.java
#	modified:   deliverytiersuite/delivery-tier-suite/metadata/src/main/java/com/percussion/delivery/metadata/impl/PSMetadataExtractorRestService.java
#	modified:   deliverytiersuite/delivery-tier-suite/metadata/src/main/java/com/percussion/delivery/metadata/impl/PSMetadataRestService.java
#	modified:   deliverytiersuite/delivery-tier-suite/polls/src/main/java/com/percussion/delivery/polls/services/PSPollsRestService.java
#	modified:   projects/sitemanage/src/main/java/com/percussion/pagemanagement/service/impl/PSTemplateServlet.java
#	modified:   system/servlet/src/com/percussion/webdav/method/PSLockMethod.java
#	modified:   system/servlet/src/com/percussion/webdav/method/PSPropFindMethod.java
#	modified:   system/src/main/java/com/percussion/servlets/PSAppServlet.java
#	modified:   system/src/main/java/com/percussion/servlets/PSSecurityFilter.java
#
Address PR #38 review: requireSafeFileName at renameOrCreateSecureSiteConfiguration,
updateThumbnailCache, generateThumbUrl, and getCachedRegionCSSRelativePath; validate
rename names in validateSiteProperties; shorten AssetAdaptor comment.

> Co-Authored by Grok 4.6 using grok-4.6 with agent Grok 4.6.
Address CodeQL review comments on PR #46 (#701/#702): reconstruct
seeOther/sendRedirect targets from validated URI components and document
the GHAS-unmodelable residual.

> Co-Authored by Grok 4.6 using grok-4.6 with agent Grok 4.6.
Signed-off-by: Nate Chadwick <natechadwick@users.noreply.github.com>
Signed-off-by: Nate Chadwick <natechadwick@users.noreply.github.com>
Remove CHANGELOG.md so parallel PRs stop conflicting on the same
header. Delete the update-build-number workflow that rewrote it.
AGENTS.md targets main (no development-8.1.x) and no longer requires
a changelog entry.

> Co-Authored by Grok 4.6 using grok-4.6 with agent Grok 4.6.
Keep CHANGELOG.md deleted (modify/delete vs main).

> Co-Authored by Grok 4.6 using grok-4.6 with agent Grok 4.6.
Keep CHANGELOG.md deleted. Union path-injection paths-ignore and
suppressions with existing XXE/deserialization residuals.

> Co-Authored by Grok 4.6 using grok-4.6 with agent Grok 4.6.
Keep CHANGELOG.md deleted. Union XSS paths-ignore/suppressions with
existing residuals.

> Co-Authored by Grok 4.6 using grok-4.6 with agent Grok 4.6.
> Co-Authored by Grok 4.6 using grok-4.6 with agent Grok 4.6.
> Co-Authored by Grok 4.6 using grok-4.6 with agent Grok 4.6.
> Co-Authored by Grok 4.6 using grok-4.6 with agent Grok 4.6.
> Co-Authored by Grok 4.6 using grok-4.6 with agent Grok 4.6.
Keep CHANGELOG.md deleted. Siteimprove save-config returns the generic
error entity (CWE-209) instead of echoing the exception into the XSS
sink.

> Co-Authored by Grok 4.6 using grok-4.6 with agent Grok 4.6.
Keep CHANGELOG.md deleted. Union CR/LF strip paths-ignore with existing
residuals. Java sinks auto-merged with prior XSS/redirect work.

> Co-Authored by Grok 4.6 using grok-4.6 with agent Grok 4.6.
@natechadwick-intsof
natechadwick-intsof merged commit 99d3bf8 into main Aug 15, 2026
2 checks passed
@natechadwick-intsof
natechadwick-intsof deleted the codeql/consolidate-open-prs branch August 15, 2026 00:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants