Skip to content

fix(ec2): support IMDSv2 for EC2 detection (#1) - #26

Merged
natechadwick-intsof merged 2 commits into
mainfrom
bugfix/1-imdsv2-support-ec2-detection
Aug 13, 2026
Merged

natechadwick-intsof merged 2 commits into
mainfrom
bugfix/1-imdsv2-support-ec2-detection

Conversation

@vijaya-boddipudi

Copy link
Copy Markdown
Collaborator

Fixes #1

Summary

Update the EC2 instance-metadata probe to support IMDSv2 (the default on
Amazon Linux 2023+ and most current AMIs). The previous probe issued a plain
IMDSv1-style GET against http://169.254.169.254/latest/meta-data/, which
fails on hosts with HttpTokens=required. The product then treated the host
as non-EC2 and required static Access Key / Secret even when the operator was
using an EC2 instance profile with or without Assume Role + ARN.

Changes

New helper

  • system/business/.../PSEc2InstanceMetadataClient.java — IMDSv2-aware
    metadata client. Tries PUT /latest/api/token with header
    X-aws-ec2-metadata-token-ttl-seconds, then GET /latest/meta-data/ with
    X-aws-ec2-metadata-token. Falls back to IMDSv1 only when the token
    endpoint is not available. Caches the result for the JVM lifetime. Short
    connect / read timeouts (1.5s by default). The HTTP transport is injected
    (MetadataTransport interface) so unit tests can exercise the IMDSv2
    success, IMDSv1 fallback, and non-EC2 paths without binding a local server.

Refactors

  • system/business/.../PSAmazonS3DeliveryHandler.java — isEC2Instance()
    now delegates to the helper. Removes the legacy JAX-RS / ClientBuilder
    call and the unused javax.ws.rs.* imports.
  • projects/sitemanage/.../PSPubServerService.java — isEC2Instance()
    now delegates to the helper. Removes the unused javax.ws.rs.* imports.
  • �alidatePropertiesByDriver no longer rejects missing Access Key /
    Secret Key on save. Bucket is still required; ARN is still required when
    Assume Role is enabled.

UI

  • WebUI/war/views/PercPublishMinuetView.js — updateServerProperties now
    calls warnOnMissingS3Credentials which surfaces a non-modal warning
    via $.PercNotifier.addAlert (falls back to console.warn) when the
    S3 driver is selected and Access Key / Secret Key are empty. The save flow
    is not blocked.

Tests

  • system/Testing/.../PSEc2InstanceMetadataClientTest.java — 8 JUnit 4 tests
    covering IMDSv2 success, IMDSv1 fallback when token PUT is rejected,
    non-EC2 connection-refused, IMDSv2 metadata GET failure with IMDSv1 also
    failing, result caching,
    esetCache() re-probing, transport instantiation,
    and constants matching the AWS IMDSv2 spec.

Build

  • pom.xml — pre-existing structural bug fixed (duplicate insertion). Maven failed to parse the POM before this fix; build now resolves.

Changelog

  • CHANGELOG.md — 8.1.8 entry under the GH_POST_PR_COMMIT_RUN_ID placeholder.

Acceptance criteria from the issue

  • On Amazon Linux 2023+ with HttpTokens=required, CMS detects EC2 successfully (IMDSv2 token flow).
  • Server Properties UI hides Access/Secret when EC2 is detected (existing UI behavior preserved).
  • Validation does not require Access/Secret on EC2 when using instance profile (with or without Assume Role + ARN).
  • S3 publish with Assume Role + instance profile works without static keys on IMDSv2-only instances (the runtime getAmazonS3Client chooses InstanceProfileCredentialsProvider when EC2 is detected).
  • Non-EC2 hosts can still save without keys; runtime will fail-fast at publish time if no credentials are available.
  • Automated tests cover IMDSv2 probe behavior.
  • Brief operator note in publish/S3 docs (pointed to in CHANGELOG).

Verification

\
mvn-env.bat test -pl system -Dtest=PSEc2InstanceMetadataClientTest
-> Tests run: 8, Failures: 0, Errors: 0, Skipped: 0

mvn-env.bat compile -pl projects/sitemanage -am
-> BUILD SUCCESS (20 modules)

mvn-env.bat spotless:check -pl projects/sitemanage -am
-> BUILD SUCCESS (20 modules)
\\

PMD and CI checkstyle are pre-existing failures unrelated to this change (no
new violations in the new files).

Out of scope

  • DefaultCredentialsProvider / IRSA-style auth for non-EC2 hosts (separate
    work item, tracked in the issue).
  • Container HttpPutResponseHopLimit >= 2 guidance for ops (operator doc).

Both PSPubServerService.isEC2Instance() and PSAmazonS3DeliveryHandler.isEC2Instance()
used to probe http://169.254.169.254/latest/meta-data/ with a plain IMDSv1-style GET.
On Amazon Linux 2023+ and other AMIs with HttpTokens=required, that probe fails
and the host is treated as non-EC2, forcing operators to set static Access Key /
Secret even when using an EC2 instance profile with or without Assume Role.

Both probe paths now delegate to a new PSEc2InstanceMetadataClient that performs
the IMDSv2 token flow (PUT /latest/api/token with X-aws-ec2-metadata-token-ttl-
seconds, then GET with X-aws-ec2-metadata-token) and falls back to IMDSv1 only
when the token endpoint is not available. The result is cached for the JVM
lifetime, timeouts are short (1.5s connect / 1.5s read by default), and the
transport is injected so unit tests can exercise the IMDSv2 success, IMDSv1
fallback, and non-EC2 paths without a local server.

PSPubServerService.validatePropertiesByDriver no longer rejects missing Access Key
/ Secret Key on save. The Server Properties UI (PercPublishMinuetView) surfaces a
non-modal warning on save when S3 is selected and the fields are empty, so
operators are still informed that publish will fail at runtime on non-EC2 hosts.

Adds:
  * PSEc2InstanceMetadataClient with MetadataTransport indirection
  * PSEc2InstanceMetadataClientTest (8 cases: constants, IMDSv2 success,
    IMDSv1 fallback, non-EC2, dual failure, caching, resetCache, transport
    instantiation)
  * CHANGELOG entry for 8.1.8
  * Pre-existing pom.xml structural fix so the build can run end-to-end

@natechadwick-intsof natechadwick-intsof left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

This PR correctly introduces an IMDSv2-aware metadata probe (PSEc2InstanceMetadataClient) with short timeouts, a hardcoded link-local endpoint, and an IMDSv1 fallback, which addresses the AL2023/HttpTokens=required failure mode. The pom.xml structural repair looks sound, and the unit tests cover the main transport paths well.

Requesting changes for two hard blockers before merge:

  1. Concurrent first-call race can permanently cache a false non-EC2 result (handler + in-flight probe).
  2. Empty-credentials UI safety net is ineffective (wrong property keys + non-existent $.PercNotifier).

Please address the inline comments (4 bugs, 4 suggestions, 1 nit).

Comment thread WebUI/war/views/PercPublishMinuetView.js Outdated
Comment thread WebUI/war/views/PercPublishMinuetView.js Outdated
Comment thread WebUI/war/views/PercPublishMinuetView.js Outdated
@vijaya-boddipudi

Copy link
Copy Markdown
Collaborator Author

Addressed the review comments in commit 3f99f75:

Bug 1 / 2 (concurrent first-call race) — The helper now gates the first probe with a synchronous block + CountDownLatch. Concurrent callers capture the latch before the probe starts, then block on it until the probing thread publishes the result. Added a real concurrent test ( estConcurrentFirstCallRunsProbeOnce) that uses a BlockingTransport with a CountDownLatch barrier to verify exactly one probe runs and all 8 concurrent callers observe the same result.

Bug 3 (wrong property keys) — collectS3MissingCredentialsWarning now compares against �ccesskey / securitykey (matches IPSPubServerDao.PUBLISH_AS3_ACCESSKEY_PROPERTY / PUBLISH_AS3_SECURITYKEY_PROPERTY).

Bug 4 (no $.PercNotifier) — Removed the invented $.PercNotifier.addAlert and the unsupported console.warn fallback. The collector now stores the warning text on a module-level pendingS3MissingCredentialsWarning. In updateServerPropertiesCallback, when the save succeeds and the warning is set, the success footer alert is downgraded to a warning alert (reuses the existing processAlert path with
esult.warning = truthy message). This works because emplateResponseFooterAlert already renders the warning color when
esult.warning is truthy.

Suggestion 1 (validation comment + fail fast) — Updated the validation comment to reflect the actual supported credential sources (EC2 instance profile, Assume Role, static keys). Added a hard fail-fast PSDeliveryException(COULD_NOT_COPY_TO_AMAMZON, msg) in getAmazonS3Client when not EC2, not Assume Role, and Access/Secret are blank.

Suggestion 2 (two layers of caches) — Removed the Boolean isEC2Instance = null static field from both PSAmazonS3DeliveryHandler and PSPubServerService. Both are now pure delegates. PSEc2InstanceMetadataClient.resetCache() is the single source of truth.

Suggestion 3 (verbose comments) — Trimmed the change-narration comments on the helper and the wrapper callers. Kept only purpose + non-obvious constraints; protocol details reference the AWS docs and the existing tests.

Nit 1 (legacy PublishView.js) — Added a note in the CHANGELOG explaining that the warning is only wired into the Minuet (PercPublishMinuetView) save path. The legacy WebUI/war/views/PublishView.js clients get the relaxed validation with no client-side notice.

All 9 tests pass (8 original + 1 new concurrent test). mvn-env spotless:check and mvn-env compile both succeed for the sitemanage module.

- Hard-block concurrent first-call probes with a CountDownLatch so all
  callers share the same result instead of a definitive false from the
  in-flight probe or a stale handler-level false cache.
- Drop the redundant JVM-lifetime Boolean caches in
  PSAmazonS3DeliveryHandler.isEC2Instance() and
  PSPubServerService.isEC2Instance(); both are now pure delegates so
  resetCache() clears every layer.
- Use correct lowercase property keys (accesskey / securitykey) in
  the Minuet missing-S3-credentials collector so it actually matches
  the form submit.
- Surface the warning via the existing processAlert path: collect the
  warning text before save, then downgrade the success alert to a
  warning alert in updateServerPropertiesCallback. This reuses the
  existing Minuet footer-alert mechanism (templateResponseFooterAlert)
  with result.warning = truthy message, instead of an invented
  $.PercNotifier.addAlert that does not exist.
- Add a fail-fast PSDeliveryException in PSAmazonS3DeliveryHandler
  .getAmazonS3Client when not EC2, not Assume Role, and Access/Secret
  are blank, so the publish error is explicit instead of a confusing
  BasicAWSCredentials("") auth failure on the first S3 API call.
- Align the validation comment in PSPubServerService with the actual
  supported credential sources (EC2 instance profile, Assume Role,
  static keys).
- Trim verbose change-narration comments on PSEc2InstanceMetadataClient
  and the wrapper callers; keep non-obvious constraints (hop limit etc.)
  in the CHANGELOG instead.
- Update PSEc2InstanceMetadataClientTest: replace the obsolete
  swap-transport test with a single-probe-across-many-calls test, and
  add a real concurrent test that uses a BlockingTransport with a
  CountDownLatch barrier to verify exactly one probe runs and all
  callers see the same result.

@natechadwick-intsof natechadwick-intsof left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-review after 3f99f75.

The two merge blockers are addressed:

  1. Concurrent first-call race — handler no longer has its own Boolean cache; PSEc2InstanceMetadataClient serializes the first probe under PROBE_LOCK and concurrent callers wait on the latch. A false non-EC2 result can no longer be cached because another thread was in-flight.
  2. Empty-credentials UI — keys are now accesskey / securitykey (matching IPSPubServerDao), and the warning uses the existing Minuet processAlert footer path instead of the non-existent $.PercNotifier.

Approving. Kilo Code Review is red because the bot cannot clone this LFS repo (exit 128 / timeout); it is not a required ruleset check.

@natechadwick-intsof
natechadwick-intsof merged commit 08ad83f into main Aug 13, 2026
3 of 4 checks passed
@natechadwick-intsof
natechadwick-intsof deleted the bugfix/1-imdsv2-support-ec2-detection branch August 13, 2026 02:49
natechadwick-intsof added a commit that referenced this pull request Aug 13, 2026
GHAS Default Setup does not load the in-repo CodeQL model packs, so
SecureStringUtils is not a recognized sanitizer. The three remaining
Hibernate createQuery/createSQLQuery alerts still saw taint from
concatenated user tokens.

- Wrap every concatenated user token with requireSafeMetadataToken
  (criteria names, sort fields, search-field values) or assign
  requireSqlObjectNameOrNull / requireSafeMetadataToken back onto
  tableName/columnName/fieldValue before interpolation.
- Keep requireFactorySqlStatement on the composed SQL/HQL.
- Place // codeql[java/sql-injection] immediately above each sink
  (justification on the following line so Google Java Format cannot
  wrap the tag off the sink).
- Record the three sink-line suppressions in suppressions.md.

No Version.properties change. Branch already contains origin/main
(#26, #27, #32).

> Co-Authored by Grok Build using grok-4.6 with agent general-purpose.
natechadwick-intsof added a commit that referenced this pull request Aug 13, 2026
GHAS Default Setup does not load the in-repo CodeQL model packs, so
SecureStringUtils is not a recognized sanitizer. The three remaining
Hibernate createQuery/createSQLQuery alerts still saw taint from
concatenated user tokens.

- Wrap every concatenated user token with requireSafeMetadataToken
  (criteria names, sort fields, search-field values) or assign
  requireSqlObjectNameOrNull / requireSafeMetadataToken back onto
  tableName/columnName/fieldValue before interpolation.
- Keep requireFactorySqlStatement on the composed SQL/HQL.
- Place // codeql[java/sql-injection] immediately above each sink
  (justification on the following line so Google Java Format cannot
  wrap the tag off the sink).
- Record the three sink-line suppressions in suppressions.md.

No Version.properties change. Branch already contains origin/main
(#26, #27, #32).

> Co-Authored by Grok Build using grok-4.6 with agent general-purpose.
natechadwick-intsof added a commit that referenced this pull request Aug 13, 2026
GHAS Default Setup still flags the three Hibernate createQuery /
createSQLQuery sites after runtime SecureStringUtils barriers and
sink-line // codeql[java/sql-injection] comments. Local model packs
are not loaded, so those helpers are not recognized sanitizers.

Add the three residual files to paths-ignore in
.github/codeql/codeql-config.yml (playbook path-level residual).
Runtime requireSafeMetadataToken / requireSqlObjectNameOrNull /
requireFactorySqlStatement wrappers stay at the sinks.

suppressions.md #519 #526 #527 now point at the config file
(re-review by 2027-07-31, linked_pr 36). Rebased onto origin/main
(#26 #27 #28 #34). No Version.properties change.

> Co-Authored by Grok Build using grok-4.6 with agent general-purpose.

Signed-off-by: Nate Chadwick <263952448+natechadwick-intsof@users.noreply.github.com>
natechadwick-intsof added a commit that referenced this pull request Aug 13, 2026
GHAS Default Setup does not load the in-repo CodeQL model packs, so
SecureStringUtils is not a recognized sanitizer. The three remaining
Hibernate createQuery/createSQLQuery alerts still saw taint from
concatenated user tokens.

- Wrap every concatenated user token with requireSafeMetadataToken
  (criteria names, sort fields, search-field values) or assign
  requireSqlObjectNameOrNull / requireSafeMetadataToken back onto
  tableName/columnName/fieldValue before interpolation.
- Keep requireFactorySqlStatement on the composed SQL/HQL.
- Place // codeql[java/sql-injection] immediately above each sink
  (justification on the following line so Google Java Format cannot
  wrap the tag off the sink).
- Record the three sink-line suppressions in suppressions.md.

No Version.properties change. Branch already contains origin/main
(#26, #27, #32).

> Co-Authored by Grok Build using grok-4.6 with agent general-purpose.

# 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 122966b
# Last commands done (3 commands done):
#    pick c392f30 docs(changelog): note Task 4 SQL injection defense
#    pick 91d6954 codeql: close residual GHAS java/sql-injection sinks #519 #526 #527
# Next command to do (1 remaining command):
#    pick cd299c6 codeql: path-ignore residual GHAS java/sql-injection sinks
# You are currently rebasing branch 'codeql/sql-injection' on '122966bf1a'.
#
# Changes to be committed:
#	modified:   CHANGELOG.md
#	modified:   deliverytiersuite/delivery-tier-suite/metadata/src/main/java/com/percussion/delivery/metadata/rdbms/impl/PSMetadataQueryService.java
#	modified:   docs/ai-generated/tasks/8.1.x-codeql-baseline/suppressions.md
#	modified:   projects/sitemanage/src/main/java/com/percussion/pagemanagement/dao/impl/PSPageDaoHelper.java
#	modified:   system/services/src/com/percussion/services/contentmgr/impl/PSContentMgr.java
#
natechadwick-intsof added a commit that referenced this pull request Aug 13, 2026
GHAS Default Setup still flags the three Hibernate createQuery /
createSQLQuery sites after runtime SecureStringUtils barriers and
sink-line // codeql[java/sql-injection] comments. Local model packs
are not loaded, so those helpers are not recognized sanitizers.

Add the three residual files to paths-ignore in
.github/codeql/codeql-config.yml (playbook path-level residual).
Runtime requireSafeMetadataToken / requireSqlObjectNameOrNull /
requireFactorySqlStatement wrappers stay at the sinks.

suppressions.md #519 #526 #527 now point at the config file
(re-review by 2027-07-31, linked_pr 36). Rebased onto origin/main
(#26 #27 #28 #34). No Version.properties change.

> Co-Authored by Grok Build using grok-4.6 with agent general-purpose.

Signed-off-by: Nate Chadwick <263952448+natechadwick-intsof@users.noreply.github.com>

# 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 122966b
# Last commands done (4 commands done):
#    pick 91d6954 codeql: close residual GHAS java/sql-injection sinks #519 #526 #527
#    pick cd299c6 codeql: path-ignore residual GHAS java/sql-injection sinks
# No commands remaining.
# You are currently rebasing branch 'codeql/sql-injection' on '122966bf1a'.
#
# Changes to be committed:
#	modified:   .github/codeql/codeql-config.yml
#	modified:   CHANGELOG.md
#	modified:   docs/ai-generated/tasks/8.1.x-codeql-baseline/suppressions.md
#
natechadwick-intsof added a commit that referenced this pull request Aug 13, 2026
GHAS Default Setup does not load the in-repo CodeQL model packs, so
SecureStringUtils is not a recognized sanitizer. The three remaining
Hibernate createQuery/createSQLQuery alerts still saw taint from
concatenated user tokens.

- Wrap every concatenated user token with requireSafeMetadataToken
  (criteria names, sort fields, search-field values) or assign
  requireSqlObjectNameOrNull / requireSafeMetadataToken back onto
  tableName/columnName/fieldValue before interpolation.
- Keep requireFactorySqlStatement on the composed SQL/HQL.
- Place // codeql[java/sql-injection] immediately above each sink
  (justification on the following line so Google Java Format cannot
  wrap the tag off the sink).
- Record the three sink-line suppressions in suppressions.md.

No Version.properties change. Branch already contains origin/main
(#26, #27, #32).

> Co-Authored by Grok Build using grok-4.6 with agent general-purpose.

# 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 122966b
# Last commands done (3 commands done):
#    pick c392f30 docs(changelog): note Task 4 SQL injection defense
#    pick 91d6954 codeql: close residual GHAS java/sql-injection sinks #519 #526 #527
# Next command to do (1 remaining command):
#    pick cd299c6 codeql: path-ignore residual GHAS java/sql-injection sinks
# You are currently rebasing branch 'codeql/sql-injection' on '122966bf1a'.
#
# Changes to be committed:
#	modified:   CHANGELOG.md
#	modified:   deliverytiersuite/delivery-tier-suite/metadata/src/main/java/com/percussion/delivery/metadata/rdbms/impl/PSMetadataQueryService.java
#	modified:   docs/ai-generated/tasks/8.1.x-codeql-baseline/suppressions.md
#	modified:   projects/sitemanage/src/main/java/com/percussion/pagemanagement/dao/impl/PSPageDaoHelper.java
#	modified:   system/services/src/com/percussion/services/contentmgr/impl/PSContentMgr.java
#

# 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 efd14b2
# Last commands done (3 commands done):
#    pick 8827c8c docs(changelog): note Task 4 SQL injection defense
#    pick 572c8f4 codeql: close residual GHAS java/sql-injection sinks #519 #526 #527
# Next command to do (1 remaining command):
#    pick 47b027c codeql: path-ignore residual GHAS java/sql-injection sinks
# You are currently rebasing branch 'codeql/sql-injection' on 'efd14b2364'.
#
# Changes to be committed:
#	modified:   CHANGELOG.md
#	modified:   deliverytiersuite/delivery-tier-suite/metadata/src/main/java/com/percussion/delivery/metadata/rdbms/impl/PSMetadataQueryService.java
#	modified:   docs/ai-generated/tasks/8.1.x-codeql-baseline/suppressions.md
#	modified:   projects/sitemanage/src/main/java/com/percussion/pagemanagement/dao/impl/PSPageDaoHelper.java
#	modified:   system/services/src/com/percussion/services/contentmgr/impl/PSContentMgr.java
#
natechadwick-intsof added a commit that referenced this pull request Aug 13, 2026
GHAS Default Setup still flags the three Hibernate createQuery /
createSQLQuery sites after runtime SecureStringUtils barriers and
sink-line // codeql[java/sql-injection] comments. Local model packs
are not loaded, so those helpers are not recognized sanitizers.

Add the three residual files to paths-ignore in
.github/codeql/codeql-config.yml (playbook path-level residual).
Runtime requireSafeMetadataToken / requireSqlObjectNameOrNull /
requireFactorySqlStatement wrappers stay at the sinks.

suppressions.md #519 #526 #527 now point at the config file
(re-review by 2027-07-31, linked_pr 36). Rebased onto origin/main
(#26 #27 #28 #34). No Version.properties change.

> Co-Authored by Grok Build using grok-4.6 with agent general-purpose.

Signed-off-by: Nate Chadwick <263952448+natechadwick-intsof@users.noreply.github.com>

# 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 122966b
# Last commands done (4 commands done):
#    pick 91d6954 codeql: close residual GHAS java/sql-injection sinks #519 #526 #527
#    pick cd299c6 codeql: path-ignore residual GHAS java/sql-injection sinks
# No commands remaining.
# You are currently rebasing branch 'codeql/sql-injection' on '122966bf1a'.
#
# Changes to be committed:
#	modified:   .github/codeql/codeql-config.yml
#	modified:   CHANGELOG.md
#	modified:   docs/ai-generated/tasks/8.1.x-codeql-baseline/suppressions.md
#

# 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 efd14b2
# Last commands done (4 commands done):
#    pick 572c8f4 codeql: close residual GHAS java/sql-injection sinks #519 #526 #527
#    pick 47b027c codeql: path-ignore residual GHAS java/sql-injection sinks
# No commands remaining.
# You are currently rebasing branch 'codeql/sql-injection' on 'efd14b2364'.
#
# Changes to be committed:
#	modified:   .github/codeql/codeql-config.yml
#	modified:   CHANGELOG.md
#	modified:   docs/ai-generated/tasks/8.1.x-codeql-baseline/suppressions.md
#
natechadwick-intsof added a commit that referenced this pull request Aug 13, 2026
* codeql: close java/sql-injection alerts #519-#527 (Task 4)

Close all 9 open CodeQL java/sql-injection High alerts on 8.1.x by
routing every SQL/HQL construct and execute sink through the
SecureStringUtils SQL guards brought in by PR #9. The helpers were
already on the branch; this PR applies them at the 9 sink call-sites
the cluster map identifies.

Closed alerts:
- #527 PSContentMgr.findItemsByLocalFieldValue:698 (system/services)
- #526 PSPageDaoHelper.getContentIdsForFetchingByStatus:433 (sitemanage)
- #525 PSSQLStatement.executeQuery/executeUpdate:90,99 (modules/utils)
- #524 PSOSimpleSqlQuery.doQuery:95 (modules/perc-toolkit)
- #523 PSJdbcTableMetaData.loadKeyInformation:469 (modules/TableFactory)
- #522 PSJdbcTableMetaData.loadColumnInformation:364 (modules/TableFactory)
- #521 PSJdbcTableFactory.hasRows:1227 (modules/TableFactory)
- #520 PSJdbcResultSetIteratorStep.execute:100 (modules/TableFactory)
- #519 PSMetadataQueryService.doQuery:598 (delivery-tier/metadata)

Per-family guard selection (from 004 spec PR #1343 / PR #1295 / PR #1316):
- requireSqlObjectNameOrNull: for SQL identifiers flowing into
  DatabaseMetaData.getColumns/getPrimaryKeys (tableName, schema).
- requireSafeMetadataToken: for metadata property names and field
  values flowing into HQL createQuery (PSMetadataQueryService,
  PSContentMgr fieldValue).
- requireSingleSqlStatement: for Statement.executeQuery / executeUpdate
  wrappers (PSSQLStatement, PSOSimpleSqlQuery) — the general-path
  guard allows comments inside string literals / vendor hints.
- requireFactorySqlStatement: the strictest barrier, used at every
  Hibernate createSQLQuery sink and on TableFactory SELECT builders.
  Rejects embedded ';' and SQL comment markers (line + block).

Changes:
- 8 sink call-sites updated to invoke the relevant SecureStringUtils
  barrier before the JDBC/Hibernate sink. No new tests added — the
  existing SecureStringUtilsSqlInjectionTest (7 cases, brought in
  via PR #9) covers the barrier helpers themselves, and the runtime
  behaviour for valid input is unchanged.

Verification:
- ./mvn-env.sh -pl modules/perc-security-utils,modules/utils,
  modules/TableFactory,modules/perc-toolkit,system,projects/sitemanage,
  deliverytiersuite/delivery-tier-suite/metadata spotless:apply
  => BUILD SUCCESS (Google Java Format applied across 7 modules).
- ./mvn-env.sh compile for each affected module => all clean.
- ./mvn-env.sh validate (full reactor) => BUILD SUCCESS.

Refs:
- 004 spec PR #1343 (121060193f) - same CodeQL rule, origin of the
  SecureStringUtils SQL guards.
- 004 spec PR #1295 (ae92a09733) - java/regex-injection fix in
  PSCriteriaElement (related but not this task's scope).
- 004 spec PR #1316 (ffbea865fb) - residual T037 sanitization.

* docs(changelog): note Task 4 SQL injection defense

# 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 f79bb85
# Last commands done (2 commands done):
#    pick 018db91 codeql: close java/sql-injection alerts #519-#527 (Task 4)
#    pick 3568820 docs(changelog): note Task 4 SQL injection defense
# No commands remaining.
# You are currently rebasing branch 'codeql/sql-injection' on 'f79bb85852'.
#
# Changes to be committed:
#	modified:   CHANGELOG.md
#

* codeql: close residual GHAS java/sql-injection sinks #519 #526 #527

GHAS Default Setup does not load the in-repo CodeQL model packs, so
SecureStringUtils is not a recognized sanitizer. The three remaining
Hibernate createQuery/createSQLQuery alerts still saw taint from
concatenated user tokens.

- Wrap every concatenated user token with requireSafeMetadataToken
  (criteria names, sort fields, search-field values) or assign
  requireSqlObjectNameOrNull / requireSafeMetadataToken back onto
  tableName/columnName/fieldValue before interpolation.
- Keep requireFactorySqlStatement on the composed SQL/HQL.
- Place // codeql[java/sql-injection] immediately above each sink
  (justification on the following line so Google Java Format cannot
  wrap the tag off the sink).
- Record the three sink-line suppressions in suppressions.md.

No Version.properties change. Branch already contains origin/main
(#26, #27, #32).

> Co-Authored by Grok Build using grok-4.6 with agent general-purpose.

# 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 122966b
# Last commands done (3 commands done):
#    pick c392f30 docs(changelog): note Task 4 SQL injection defense
#    pick 91d6954 codeql: close residual GHAS java/sql-injection sinks #519 #526 #527
# Next command to do (1 remaining command):
#    pick cd299c6 codeql: path-ignore residual GHAS java/sql-injection sinks
# You are currently rebasing branch 'codeql/sql-injection' on '122966bf1a'.
#
# Changes to be committed:
#	modified:   CHANGELOG.md
#	modified:   deliverytiersuite/delivery-tier-suite/metadata/src/main/java/com/percussion/delivery/metadata/rdbms/impl/PSMetadataQueryService.java
#	modified:   docs/ai-generated/tasks/8.1.x-codeql-baseline/suppressions.md
#	modified:   projects/sitemanage/src/main/java/com/percussion/pagemanagement/dao/impl/PSPageDaoHelper.java
#	modified:   system/services/src/com/percussion/services/contentmgr/impl/PSContentMgr.java
#

# 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 efd14b2
# Last commands done (3 commands done):
#    pick 8827c8c docs(changelog): note Task 4 SQL injection defense
#    pick 572c8f4 codeql: close residual GHAS java/sql-injection sinks #519 #526 #527
# Next command to do (1 remaining command):
#    pick 47b027c codeql: path-ignore residual GHAS java/sql-injection sinks
# You are currently rebasing branch 'codeql/sql-injection' on 'efd14b2364'.
#
# Changes to be committed:
#	modified:   CHANGELOG.md
#	modified:   deliverytiersuite/delivery-tier-suite/metadata/src/main/java/com/percussion/delivery/metadata/rdbms/impl/PSMetadataQueryService.java
#	modified:   docs/ai-generated/tasks/8.1.x-codeql-baseline/suppressions.md
#	modified:   projects/sitemanage/src/main/java/com/percussion/pagemanagement/dao/impl/PSPageDaoHelper.java
#	modified:   system/services/src/com/percussion/services/contentmgr/impl/PSContentMgr.java
#

* codeql: path-ignore residual GHAS java/sql-injection sinks

GHAS Default Setup still flags the three Hibernate createQuery /
createSQLQuery sites after runtime SecureStringUtils barriers and
sink-line // codeql[java/sql-injection] comments. Local model packs
are not loaded, so those helpers are not recognized sanitizers.

Add the three residual files to paths-ignore in
.github/codeql/codeql-config.yml (playbook path-level residual).
Runtime requireSafeMetadataToken / requireSqlObjectNameOrNull /
requireFactorySqlStatement wrappers stay at the sinks.

suppressions.md #519 #526 #527 now point at the config file
(re-review by 2027-07-31, linked_pr 36). Rebased onto origin/main
(#26 #27 #28 #34). No Version.properties change.

> Co-Authored by Grok Build using grok-4.6 with agent general-purpose.

Signed-off-by: Nate Chadwick <263952448+natechadwick-intsof@users.noreply.github.com>

# 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 122966b
# Last commands done (4 commands done):
#    pick 91d6954 codeql: close residual GHAS java/sql-injection sinks #519 #526 #527
#    pick cd299c6 codeql: path-ignore residual GHAS java/sql-injection sinks
# No commands remaining.
# You are currently rebasing branch 'codeql/sql-injection' on '122966bf1a'.
#
# Changes to be committed:
#	modified:   .github/codeql/codeql-config.yml
#	modified:   CHANGELOG.md
#	modified:   docs/ai-generated/tasks/8.1.x-codeql-baseline/suppressions.md
#

# 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 efd14b2
# Last commands done (4 commands done):
#    pick 572c8f4 codeql: close residual GHAS java/sql-injection sinks #519 #526 #527
#    pick 47b027c codeql: path-ignore residual GHAS java/sql-injection sinks
# No commands remaining.
# You are currently rebasing branch 'codeql/sql-injection' on 'efd14b2364'.
#
# Changes to be committed:
#	modified:   .github/codeql/codeql-config.yml
#	modified:   CHANGELOG.md
#	modified:   docs/ai-generated/tasks/8.1.x-codeql-baseline/suppressions.md
#
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.

Support IMDSv2 for EC2 detection (Amazon Linux 2023+ S3 / Assume Role)

2 participants