Creating draft PR with potential fix#36092
Conversation
❌ Issue Linking RequiredThis PR could not be linked to an issue. All PRs must be linked to an issue for tracking purposes. How to fix this:Option 1: Add keyword to PR body (Recommended - auto-removes this comment)
Why is this required?Issue linking ensures proper tracking, documentation, and helps maintain project history. It connects your code changes to the problem they solve.--- This comment was automatically generated by the issue linking workflow |
|
Claude finished @jcastro-dotcms's task in 3m 37s —— View job Code Review
SummaryThe PR rewrites the hot path for saving related content: instead of fetching and hydrating every related contentlet one-by-one, it reads raw identifiers from the Issues1. SQL injection via dynamic column names — Semgrep findings are real (
|
…ent-performance-improvements
|
Semgrep found 10
The method identified is susceptible to injection. The input should be validated and properly If this is a critical or high severity finding, please also link this issue in the #security channel in Slack. |
…ent-performance-improvements
…ent-performance-improvements
| .setSQL("SELECT COALESCE(MAX(tree_order), 0) + 1 AS next_position FROM tree" | ||
| + " WHERE " + whereColumn + " = ? AND relation_type = ?") |
There was a problem hiding this comment.
Semgrep identified a blocking 🔴 issue in your code:
The method identified is susceptible to injection. The input should be validated and properly
escaped.
Why this might be safe to ignore:
This query concatenates only the column name, and in this method that value is constrained by internal callers to the fixed literals "parent" or "child" while user-controlled values are still passed as parameters. The rule matched a generic string-built SQL pattern, but in this context there is no realistic injection path to the database.
To resolve this comment:
🔧 No guidance has been designated for this issue. Fix according to your organization's approved methods.
💬 Ignore this finding
Reply with Semgrep commands to ignore this finding.
/fp <comment>for false positive/ar <comment>for acceptable risk/other <comment>for all other reasons
Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by CUSTOM_INJECTION-2.
If this is a critical or high severity finding, please also link this issue in the #security channel in Slack.
You can view more details about this finding in the Semgrep AppSec Platform.
| "SELECT * FROM contentlet_version_info WHERE identifier IN (" | ||
| + DotConnect.createParametersPlaceholder(chunk.size()) + ")"); |
There was a problem hiding this comment.
Semgrep identified a blocking 🔴 issue in your code:
The method identified is susceptible to injection. The input should be validated and properly
escaped.
Why this might be safe to ignore:
This query builds only the number of parameter placeholders for an IN clause, and the actual identifier values are passed separately with addParam, so user input is not concatenated into SQL. The rule matched a SQL string concatenation pattern, but in this context it does not create a meaningful injection risk.
To resolve this comment:
🔧 No guidance has been designated for this issue. Fix according to your organization's approved methods.
💬 Ignore this finding
Reply with Semgrep commands to ignore this finding.
/fp <comment>for false positive/ar <comment>for acceptable risk/other <comment>for all other reasons
Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by CUSTOM_INJECTION-2.
If this is a critical or high severity finding, please also link this issue in the #security channel in Slack.
You can view more details about this finding in the Semgrep AppSec Platform.
|
Semgrep found 3
The method identified is susceptible to injection. The input should be validated and properly If this is a critical or high severity finding, please also link this issue in the #security channel in Slack. |
|
Regarding Semgrep's analysis, all three are false positives: Finding analysis
.setSQL("SELECT COALESCE(MAX(tree_order), 0) + 1 AS next_position FROM tree"
+ " WHERE " + whereColumn + " = ? AND relation_type = ?")The rule fires on the string concatenation, but the only concatenated variable is whereColumn, which is a private method parameter whose only two callers pass the hardcoded literals "parent" and "child". Everything user-controllable (id, relationType) goes through addParam bound parameters. No injection path exists.
.setSQL("SELECT * FROM contentlet_version_info WHERE identifier IN ("
+ DotConnect.createParametersPlaceholder(chunk.size()) + ")");The concatenated value is the output of createParametersPlaceholder(int) — a generated ?,?,?... string derived from a list size, never from content. All identifiers are bound via addParam. This is also the established house pattern: ContentletIndexAPIImpl.SELECT_CONTENTLET_VERSION_INFO and ESContentFactoryImpl build chunked IN clauses with the exact same helper. |
Proposed Changes
Checklist
Additional Info
** any additional useful context or info **
Screenshots