Skip to content

Address Codacy security findings - #107

Merged
rasifr merged 2 commits into
mainfrom
fix/SPOC-467/codacy-security
Apr 14, 2026
Merged

Address Codacy security findings#107
rasifr merged 2 commits into
mainfrom
fix/SPOC-467/codacy-security

Conversation

@mason-sharp

Copy link
Copy Markdown
Member
  • Sanitize SQL identifiers in merkle tree queries using pgx.Identifier.Sanitize() instead
    of interpolating raw table names
  • Replace fragile manual string escaping of resolvedAgainstOrigin with strconv.Atoi
    validation
  • Add // nosemgrep annotations to false-positive SQL injection findings (all use
    parameterized queries or sanitized identifiers)
  • Bump Go 1.25.4 → 1.25.9 (CVE-2025-61730, CVE-2026-27142, CVE-2025-61727, CVE-2026-32281,
    CVE-2026-32289, CVE-2026-32288)
  • Bump moby/buildkit v0.27.1 → v0.28.1 (CVE-2026-33747, CVE-2026-33748)
  • Bump grpc v1.79.1 → v1.80.0 (CVE-2026-33186)
  • Bump otel exporters v1.38–1.41 → v1.43.0 (CVE-2026-39882)
  • Pin GitHub Actions to full commit SHAs
  • Add explicit USER nonroot to Dockerfile

Not addressed

Test plan

  • Unit tests pass (go test ./... -short)
  • TestBuildRowHashQuery passes (validates merkle identifier quoting change)
  • Codacy re-scan shows reduced findings

@coderabbitai

coderabbitai Bot commented Apr 11, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 70a0aced-b007-4470-8744-55f25cbd8bf1

📥 Commits

Reviewing files that changed from the base of the PR and between 630a7cc and 833f15d.

📒 Files selected for processing (1)
  • internal/consistency/diff/table_diff.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • internal/consistency/diff/table_diff.go

📝 Walkthrough

Walkthrough

Updated CI Go version to 1.26, added explicit USER nonroot in the Docker runtime stage, bumped OTLP gRPC exporters to v1.43.0, refactored SQL helpers to accept schema and table separately, and added multiple // nosemgrep inline suppressions across DB call sites.

Changes

Cohort / File(s) Summary
Build & Infrastructure
\.github/workflows/test.yml, Dockerfile, go.mod
CI Go toolchain changed from 1.241.26; Docker runtime stage now includes USER nonroot; OTLP exporter gRPC modules bumped from v1.38.0v1.43.0.
Query Builder Refactoring
internal/consistency/mtree/merkle.go, internal/consistency/mtree/merkle_test.go
Row-hash and fetch helpers split to accept schema and table separately (signatures changed); tests updated to pass separate schema/table; qualified table name constructed internally.
DB Callsite Semgrep Suppressions
db/queries/queries.go, internal/consistency/diff/table_diff.go, internal/consistency/diff/table_rerun.go, internal/consistency/repair/stale_repair.go, internal/consistency/repair/table_repair.go, internal/infra/cdc/listen.go, internal/infra/db/auth.go
Added // nosemgrep inline comments to many Query, QueryRow(...).Scan, and Exec callsites. table_diff.go also changed buildEffectiveFilter() to parse resolvedAgainstOrigin as an integer (strconv.Atoi) and return an error on parse failure.

Poem

🐰 I hopped from build to container den,
Split schema and table once again,
Whispered "no semgrep" on query lines,
Bumped Go and exporters up the pines,
A tidy warren in code — carrot-fed, not thin! 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.11% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Address Codacy security findings' accurately summarizes the main objectives of the PR, which involves addressing security findings from Codacy including SQL injection concerns, CVE fixes, and security configuration updates.
Description check ✅ Passed The description comprehensively details the security-focused changes including SQL sanitization, dependency updates with specific CVEs, nosemgrep annotations, and Docker configuration, with a clear test plan and explanation of unaddressed items.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/SPOC-467/codacy-security

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codacy-production

codacy-production Bot commented Apr 11, 2026

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 0 complexity · 0 duplication

Metric Results
Complexity 0
Duplication 0

View in Codacy

TIP This summary will be updated as you push new changes. Give us feedback

@mason-sharp mason-sharp changed the title Fix/spoc 467/codacy security Address Codacy security findings Apr 11, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (3)
internal/consistency/mtree/merkle.go (1)

379-388: Scope no semgrep suppressions to specific rule IDs.

Line 379/388/442/451/474/483 use broad suppression comments. Prefer rule-targeted suppressions plus a short reason so future unrelated findings on these lines aren’t accidentally masked.

Example refinement
- rowsH1, err := pool1.Query(m.Ctx, rowHashQuery, args...) // nosemgrep
+ rowsH1, err := pool1.Query(m.Ctx, rowHashQuery, args...) // nosemgrep: go.lang.security.sql-injection -- identifiers are sanitized with pgx.Identifier.Sanitize and values are parameterized

Also applies to: 442-452, 474-484

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/consistency/mtree/merkle.go` around lines 379 - 388, The broad "//
nosemgrep" suppressions on the pool1.Query and pool2.Query calls (and the other
occurrences noted) should be scoped to specific rule IDs and include a short
reason; replace each bare "// nosemgrep" comment with a targeted form like "//
nosemgrep:<RULE-ID> -- <short reason>" (e.g., reference the call sites
pool1.Query, pool2.Query, the m.Ctx usage, and the rowHashQuery/readRowHashes
logic) so only the intended Semgrep rule is suppressed and future findings
aren’t masked; update all occurrences mentioned (the lines around the
pool1.Query/pool2.Query blocks and the similar places referenced) to follow this
pattern.
internal/consistency/mtree/merkle_test.go (1)

37-160: Add one regression case for identifier-quoting behavior.

Given the security goal of this change, add a test that asserts schema/table identifiers are always quoted/sanitized (e.g., mixed-case or embedded quotes) to lock this behavior in.

Example test case addition
 tests := []struct {
   name           string
   schema         string
   table          string
@@
 }{
+  {
+    name:        "schema/table identifiers are sanitized",
+    schema:      `Public`,
+    table:       `Order"Items`,
+    key:         []string{"id"},
+    cols:        []string{"id"},
+    whereClause: "TRUE",
+    colTypes:    nil,
+    wantContains: []string{
+      `FROM "Public"."Order""Items"`,
+    },
+    wantOrderBy: `"id"`,
+  },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/consistency/mtree/merkle_test.go` around lines 37 - 160, Add a
regression test case to TestBuildRowHashQuery that verifies schema/table
identifiers are always quoted and sanitized: add a test entry (e.g., name
"identifier quoting", schema with mixed-case and an embedded quote like
`MiXeD"Sch`, table like `weird"Table`, key e.g., ["id"], cols include "id") and
assert the returned query contains the properly double-quoted/escaped schema and
table (e.g., quotes around identifiers and internal quotes doubled), that ORDER
BY uses the quoted key, and that buildRowHashQuery is used to generate the query
and orderBy to validate the exact quoted identifiers.
.github/workflows/test.yml (1)

20-20: Use go-version-file: go.mod to keep workflow Go version in sync with the module.

Currently pinning 1.25 while go.mod requires 1.25.9. This allows patch drift and reduces reproducibility. Either use go-version-file: go.mod or explicitly pin to 1.25.9.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/test.yml at line 20, The workflow currently pins
go-version: '1.25' which can drift from the module's exact runtime; update the
step to either use go-version-file: go.mod so the runner reads the Go version
from your module or explicitly pin go-version to '1.25.9' to match go.mod;
change the key from go-version to go-version-file: go.mod (or set go-version:
'1.25.9') in the job that defines the Go setup.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/release.yaml:
- Line 34: Update the GoReleaser cross image tag to match the Go version in
go.mod: replace the goreleaser image tag "v1.25.8" with "v1.25.9" (the tag shown
as goreleaser/goreleaser-cross:v1.25.8) so the workflow's toolchain aligns with
the Go version declared in go.mod (Go 1.25.9); ensure the updated tag appears
wherever goreleaser/goreleaser-cross is referenced in the workflow.

In `@internal/consistency/diff/table_diff.go`:
- Line 338: The nosemgrep suppressions hide a real SQL injection:
buildEffectiveFilter() currently constructs EffectiveFilter by
string-concatenating user-provided TableFilter and that raw string is embedded
into SQL via templates and fmt.Sprintf in the queries executed (see the
pool.QueryRow/Query calls that reference EffectiveFilter and the templates in
db/queries/templates.go). Fix by removing the suppressions and replacing string
embedding with a safe approach: change buildEffectiveFilter() to either (A)
parse/validate the incoming TableFilter against a strict
whitelist/SQL-expression grammar (or build an AST) and produce a parameterized
predicate plus a slice of parameters, or (B) refactor the API to accept
structured filter objects (column/operator/value) and build the WHERE clause
using placeholders. Then update the query templates and the code paths that call
pool.QueryRow / pool.Query (the functions that currently fmt.Sprintf
EffectiveFilter into SQL) to use prepared/parameterized queries and pass the
parameters instead of injecting the raw string. Also add input validation in the
HTTP handler that accepts TableFilter to reject anything not matching the
allowed grammar/whitelist.

---

Nitpick comments:
In @.github/workflows/test.yml:
- Line 20: The workflow currently pins go-version: '1.25' which can drift from
the module's exact runtime; update the step to either use go-version-file:
go.mod so the runner reads the Go version from your module or explicitly pin
go-version to '1.25.9' to match go.mod; change the key from go-version to
go-version-file: go.mod (or set go-version: '1.25.9') in the job that defines
the Go setup.

In `@internal/consistency/mtree/merkle_test.go`:
- Around line 37-160: Add a regression test case to TestBuildRowHashQuery that
verifies schema/table identifiers are always quoted and sanitized: add a test
entry (e.g., name "identifier quoting", schema with mixed-case and an embedded
quote like `MiXeD"Sch`, table like `weird"Table`, key e.g., ["id"], cols include
"id") and assert the returned query contains the properly double-quoted/escaped
schema and table (e.g., quotes around identifiers and internal quotes doubled),
that ORDER BY uses the quoted key, and that buildRowHashQuery is used to
generate the query and orderBy to validate the exact quoted identifiers.

In `@internal/consistency/mtree/merkle.go`:
- Around line 379-388: The broad "// nosemgrep" suppressions on the pool1.Query
and pool2.Query calls (and the other occurrences noted) should be scoped to
specific rule IDs and include a short reason; replace each bare "// nosemgrep"
comment with a targeted form like "// nosemgrep:<RULE-ID> -- <short reason>"
(e.g., reference the call sites pool1.Query, pool2.Query, the m.Ctx usage, and
the rowHashQuery/readRowHashes logic) so only the intended Semgrep rule is
suppressed and future findings aren’t masked; update all occurrences mentioned
(the lines around the pool1.Query/pool2.Query blocks and the similar places
referenced) to follow this pattern.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 27132716-a2e4-4d98-a891-f4ede8ee17bf

📥 Commits

Reviewing files that changed from the base of the PR and between cf8794d and 419381a.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (13)
  • .github/workflows/release.yaml
  • .github/workflows/test.yml
  • Dockerfile
  • db/queries/queries.go
  • go.mod
  • internal/consistency/diff/table_diff.go
  • internal/consistency/diff/table_rerun.go
  • internal/consistency/mtree/merkle.go
  • internal/consistency/mtree/merkle_test.go
  • internal/consistency/repair/stale_repair.go
  • internal/consistency/repair/table_repair.go
  • internal/infra/cdc/listen.go
  • internal/infra/db/auth.go

Comment thread .github/workflows/release.yaml Outdated
Comment thread internal/consistency/diff/table_diff.go
@mason-sharp
mason-sharp requested a review from rasifr April 13, 2026 00:25
@mason-sharp

Copy link
Copy Markdown
Member Author

Will rebase and modify as a small follow up to #109

Sanitize SQL identifiers in merkle tree queries and validate origin filter

- buildRowHashQuery, buildFetchRowsSQLSimple, buildFetchRowsSQLComposite
  now take separate schema/table args and quote them with
  pgx.Identifier.Sanitize() instead of interpolating a raw
  QualifiedTableName string.

- buildEffectiveFilter: replace fragile strings.ReplaceAll("'","''")
  escaping of resolvedAgainstOrigin with strconv.Atoi validation. Spock
  node IDs are integers; reject non-numeric values instead of escaping.

Add nosemgrep annotations for false-positive SQL injection findings

All flagged query sites use pgx.Identifier.Sanitize() for identifiers
and parameterized placeholders ($N) for values. Annotate each with the
specific reason so opengrep suppressions survive line shifts.

Bump Go version pin GitHub Actions to commit SHAs, update dependencies

Add explicit USER nonroot to Dockerfile for Codacy scanner
@mason-sharp
mason-sharp force-pushed the fix/SPOC-467/codacy-security branch from 419381a to 630a7cc Compare April 13, 2026 21:21

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@internal/consistency/diff/table_diff.go`:
- Around line 255-258: The code validates t.resolvedAgainstOrigin with
strconv.Atoi but then interpolates the original string, which can cause
mismatches for equivalent numeric forms; change the logic to parse and normalize
the value (e.g. use strconv.Atoi or strconv.ParseInt to get an integer) and use
the normalized numeric string (via strconv.Itoa or fmt.Sprintf("%d", parsed))
when building the SQL predicate in the parts append call so the predicate uses
the canonical numeric form of t.resolvedAgainstOrigin.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2da19a3f-0f6d-449d-bfc5-0be6f424fb86

📥 Commits

Reviewing files that changed from the base of the PR and between 419381a and 630a7cc.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (12)
  • .github/workflows/test.yml
  • Dockerfile
  • db/queries/queries.go
  • go.mod
  • internal/consistency/diff/table_diff.go
  • internal/consistency/diff/table_rerun.go
  • internal/consistency/mtree/merkle.go
  • internal/consistency/mtree/merkle_test.go
  • internal/consistency/repair/stale_repair.go
  • internal/consistency/repair/table_repair.go
  • internal/infra/cdc/listen.go
  • internal/infra/db/auth.go
✅ Files skipped from review due to trivial changes (9)
  • .github/workflows/test.yml
  • internal/infra/cdc/listen.go
  • go.mod
  • internal/infra/db/auth.go
  • internal/consistency/diff/table_rerun.go
  • db/queries/queries.go
  • internal/consistency/repair/stale_repair.go
  • internal/consistency/repair/table_repair.go
  • internal/consistency/mtree/merkle_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • Dockerfile

Comment thread internal/consistency/diff/table_diff.go Outdated
Addresses Coderabbit feedback
@rasifr
rasifr merged commit b7abffe into main Apr 14, 2026
3 checks passed
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