Skip to content

Fix Codacy audit findings: Docker, CI, deps, and dev tools#98

Merged
dpage merged 18 commits into
mainfrom
fix/codacy-audit-fixes
Apr 21, 2026
Merged

Fix Codacy audit findings: Docker, CI, deps, and dev tools#98
dpage merged 18 commits into
mainfrom
fix/codacy-audit-fixes

Conversation

@dpage
Copy link
Copy Markdown
Member

@dpage dpage commented Apr 21, 2026

Summary

Addresses all 105 SRM security findings from the Codacy audit in #97.
40 findings are fixed by code/config changes; 58 are confirmed false
positives; 7 are exempt by project policy (MCP tools execute arbitrary
SQL by design).

Fixes

  • Harden Dockerfiles (7 findings): Add non-root USER directives
    to all 4 Dockerfiles. Add hadolint ignore for unpinned
    ca-certificates.
  • Pin GitHub Actions to commit SHAs (7 findings): Replace mutable
    version tags with full 40-character commit SHAs across all 9
    workflow files.
  • Update Python dependencies (5 findings): Bump urllib3
    2.5.0→2.6.3, requests 2.32.5→2.33.1, Pygments 2.19.2→2.20.0
    to fix 5 known CVEs.
  • Restrict webhook listener (1 finding): Change binding from
    0.0.0.0 to 127.0.0.1.
  • Bump Go to 1.26.2 (17 findings): Update Dockerfiles and CI
    workflows to Go 1.26.2, fixing stdlib CVEs in crypto/x509,
    html/template, archive/tar, and internal/syscall/unix. go.mod
    toolchain stays at 1.26.1 for local dev compatibility.
  • Add .catch() handlers (3 findings): Fix unhandled promise
    rejections in Chart data refresh and CopyCodeButton clipboard
    write.

Confirmed false positives (no code changes)

  • SQL injection (29): All use parameterized queries or trusted
    internal values. No user input reaches SQL without placeholders.
  • SQL injection — MCP tools (11): Exempt by policy.
  • SSRF (1): Only relative paths used; no user-controlled URLs.
  • XSS (8): DOM references in test code and standard React
    patterns.
  • Hardcoded passwords (8): localStorage keys, not credentials.
  • Cookie Secure flag (1): Already set via secureCookie
    auto-detection.

Test plan

  • make test-all passes (all Go and React tests, linting,
    coverage).
  • Verify Docker builds succeed with new USER directives.
  • Verify CI workflows run correctly with SHA-pinned actions.
  • Verify mkdocs build --strict works with updated Python deps.

Fixes #97

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Improved error handling and logging for live data refresh and clipboard copy operations.
  • Security Improvements

    • Containers now run as dedicated non-root users.
    • Webhook listener restricted to localhost access.
    • Static assets container process now runs under a non-root user.
  • Chores

    • Go toolchain updated to 1.26.2.
    • Python dependency pins updated.
    • CI/CD workflows pinned to fixed action revisions; Dependabot enabled for GitHub Actions.

dpage and others added 4 commits April 21, 2026 10:32
Addresses Codacy findings for containers running as root.
Add non-root appuser to alerter, collector, and server.
Use built-in nginx user for client container.
Add hadolint ignore for unpinned ca-certificates in server.

Fixes part of #97

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Change binding from 0.0.0.0 to 127.0.0.1 since this is
a local development tool.

Fixes part of #97

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- urllib3 2.5.0 -> 2.6.3 (CVE-2026-21441, CVE-2025-66418, CVE-2025-66471)
- requests 2.32.5 -> 2.33.1 (CVE-2026-25645)
- Pygments 2.19.2 -> 2.20.0 (CVE-2026-4539)

Fixes part of #97

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace mutable version tags with commit SHAs across all
9 workflow files. Version tags retained as trailing comments
for readability.

Fixes part of #97

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 21, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Pin GitHub Actions to commit SHAs across CI workflows; bump Go toolchain to 1.26.2 in CI and Dockerfiles; add non-root USERs in Dockerfiles; update Python deps in requirements.txt; restrict webhook listener to localhost; add async error handling in two React components; add Dependabot config.

Changes

Cohort / File(s) Summary
GitHub Actions SHA pinning & Go matrix
\.github/workflows/ci-alerter.yml, \.github/workflows/ci-client.yml, \.github/workflows/ci-collector.yml, \.github/workflows/ci-docker.yml, \.github/workflows/ci-docs.yml, \.github/workflows/ci-server.yml, \.github/workflows/ci-walkthrough.yml, \.github/workflows/docker-publish.yml, \.github/workflows/release.yml
Replaced tag-based uses: references with pinned commit SHAs for multiple actions; updated Go matrix entries and conditional guards from 1.261.26.2 where applicable.
Dockerfile hardening
alerter/Dockerfile, collector/Dockerfile, server/Dockerfile, client/Dockerfile
Bumped builder images to golang:1.26.2 where used; added non-root users (appuser for server/alerter/collector, nginx for client), adjusted ownership of runtime directories, added hadolint ignore in server Dockerfile.
Python dependency updates
requirements.txt
Bumped Pygments 2.19.2→2.20.0, requests 2.32.5→2.33.1, urllib3 2.5.0→2.6.3.
Webhook listener binding
tools/webhook_listener.py
Changed HTTP bind address from 0.0.0.0 to 127.0.0.1.
React async error handling
client/src/components/Chart/Chart.tsx, client/src/components/shared/CopyCodeButton.tsx
Unified refresh logic with error handling (.catch() / try-catch + console.error) and made clipboard handler async with await and error logging.
Dependabot config
.github/dependabot.yml
Added Dependabot config enabling weekly updates for the github-actions ecosystem.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 78.26% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title clearly summarizes the main change: fixing Codacy audit findings across Docker, CI workflows, dependencies, and dev tools, matching the comprehensive scope of changes.
Linked Issues check ✅ Passed All coding-related requirements from issue #97 are implemented: Docker hardening (USER directives, hadolint ignore), GitHub Actions SHA pinning, Python CVE remediation, webhook listener restriction, Go 1.26.2 upgrade, and unhandled async error handlers.
Out of Scope Changes check ✅ Passed All changes are directly scoped to the Codacy audit findings documented in issue #97: hardening Dockerfiles, pinning Actions, updating dependencies, restricting network binding, and fixing promise rejections.

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


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

@codacy-production
Copy link
Copy Markdown

codacy-production Bot commented Apr 21, 2026

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

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
.github/workflows/release.yml (1)

39-39: Consider automating SHA refreshes for pinned actions.

With this many pinned refs, add/confirm Dependabot updates for github-actions to reduce stale-SHA drift and manual maintenance.

Based on learnings, this repository previously experienced breakage from bad SHA pinning, so automated updates/validation can reduce recurrence risk.

Also applies to: 241-241

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

In @.github/workflows/release.yml at line 39, The workflow pins actions using a
raw SHA (e.g., actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd);
enable automated SHA refreshes by configuring Dependabot to update GitHub
Actions: add/update a .github/dependabot.yml entry with package-ecosystem:
"github-actions", target the repository (or paths containing your release
workflow), set a sensible schedule, and allow the job to open PRs to refresh
pinned refs (so actions like actions/checkout and any other pinned refs —
including the one referenced at line ~241 — get updated automatically).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@server/Dockerfile`:
- Around line 41-42: The Dockerfile drops to a non-root user `appuser` but does
not ensure the declared VOLUME `/data` is owned/writable by that user; create
the directory and set ownership before switching users so `appuser` can write to
`/data`. Concretely, add a step (before `USER appuser`) that creates `/data` if
missing and chowns it to `appuser:appuser` (reference the `appuser` user and the
`/data` VOLUME declaration) so runtime writes to `/data` won’t fail after
dropping root.

---

Nitpick comments:
In @.github/workflows/release.yml:
- Line 39: The workflow pins actions using a raw SHA (e.g.,
actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd); enable automated SHA
refreshes by configuring Dependabot to update GitHub Actions: add/update a
.github/dependabot.yml entry with package-ecosystem: "github-actions", target
the repository (or paths containing your release workflow), set a sensible
schedule, and allow the job to open PRs to refresh pinned refs (so actions like
actions/checkout and any other pinned refs — including the one referenced at
line ~241 — get updated automatically).
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: bbf867ae-ca46-4ba2-a91d-0fa70928cbea

📥 Commits

Reviewing files that changed from the base of the PR and between e3182cc and 27a2cec.

📒 Files selected for processing (15)
  • .github/workflows/ci-alerter.yml
  • .github/workflows/ci-client.yml
  • .github/workflows/ci-collector.yml
  • .github/workflows/ci-docker.yml
  • .github/workflows/ci-docs.yml
  • .github/workflows/ci-server.yml
  • .github/workflows/ci-walkthrough.yml
  • .github/workflows/docker-publish.yml
  • .github/workflows/release.yml
  • alerter/Dockerfile
  • client/Dockerfile
  • collector/Dockerfile
  • requirements.txt
  • server/Dockerfile
  • tools/webhook_listener.py

Comment thread server/Dockerfile Outdated
dpage and others added 3 commits April 21, 2026 11:08
Add error handling to promise chains in Chart data refresh
and CopyCodeButton clipboard write to prevent unhandled
rejection warnings.

Fixes part of #97

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update Go version across go.mod files, Dockerfiles, and CI
workflows to fix stdlib CVEs in crypto/x509, html/template,
archive/tar, and internal/syscall/unix.

Fixes part of #97

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Keep Dockerfiles and CI at Go 1.26.2 for production builds,
but allow local development with Go 1.26.1 by not forcing
the toolchain directive.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
client/src/components/Chart/Chart.tsx (1)

260-264: Consolidate refresh logic and handle refresh errors explicitly.

Lines 263 and 287 suppress failures with empty catches, so refresh errors become invisible and debugging gets harder. Extract one refreshData callback used by both paths, and log/report failures.

Proposed refactor
+    const refreshData = useCallback(() => {
+        if (!onDataRefresh) {
+            return;
+        }
+        onDataRefresh()
+            .then((refreshed) => {
+                setLiveData(refreshed);
+            })
+            .catch((err) => {
+                console.error('Chart refresh failed:', err);
+            });
+    }, [onDataRefresh]);
+
     useEffect(() => {
-        if (!liveUpdate || !onDataRefresh) {
+        if (!liveUpdate) {
             return;
         }
 
         const id = setInterval(() => {
-            onDataRefresh().then((refreshed) => {
-                setLiveData(refreshed);
-            }).catch(() => {});
+            refreshData();
         }, updateInterval);
 
         return () => clearInterval(id);
-    }, [liveUpdate, onDataRefresh, updateInterval]);
+    }, [liveUpdate, refreshData, updateInterval]);
@@
     const handleRefresh = useCallback(() => {
-        if (onDataRefresh) {
-            onDataRefresh().then((refreshed) => {
-                setLiveData(refreshed);
-            }).catch(() => {});
-        }
-    }, [onDataRefresh]);
+        refreshData();
+    }, [refreshData]);
As per coding guidelines: "`**/*.{go,js,ts,tsx}`: Minimize code duplication; refactor as needed."

Also applies to: 283-288

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

In `@client/src/components/Chart/Chart.tsx` around lines 260 - 264, Extract a
single async refreshData function (e.g., const refreshData = async () => { const
refreshed = await onDataRefresh(); setLiveData(refreshed); }) and use it both
inside the setInterval handler and wherever the second duplicate refresh call
exists, replacing the duplicate .then/.catch blocks; ensure you add explicit
error handling in refreshData (catch and call console.error or the app logger
with the caught error) instead of swallowing errors with empty catches so
refresh failures are visible.
client/src/components/shared/CopyCodeButton.tsx (1)

29-34: Guard clipboard access and stop swallowing copy failures silently.

Line 30 may throw synchronously when Clipboard API is unavailable, and Line 33 drops async failures with no signal. Please add an API guard and at least log/report the error (similar behavior exists in client/src/components/AdminPanel/AdminTokenScopes.tsx Lines 505-536).

Proposed fix
-    const handleCopy = useCallback(() => {
-        navigator.clipboard.writeText(code).then(() => {
-            setCopied(true);
-            setTimeout(() => setCopied(false), 2000);
-        }).catch(() => {});
-    }, [code]);
+    const handleCopy = useCallback(async () => {
+        try {
+            if (!navigator.clipboard?.writeText) {
+                throw new Error('Clipboard API unavailable in this context.');
+            }
+            await navigator.clipboard.writeText(code);
+            setCopied(true);
+            setTimeout(() => setCopied(false), 2000);
+        } catch (err) {
+            console.error('Failed to copy code:', err);
+        }
+    }, [code]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/src/components/shared/CopyCodeButton.tsx` around lines 29 - 34,
handleCopy in CopyCodeButton currently calls navigator.clipboard.writeText
without guarding for Clipboard API presence and swallows errors; update
handleCopy to first check for navigator?.clipboard?.writeText and return a
fallback if missing, then call writeText inside a try/catch (or await it) so
failures are caught and reported (use console.error or the same reporting helper
used in AdminTokenScopes) and only call setCopied(true) on success; ensure any
async errors are logged instead of silently ignored.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@client/src/components/Chart/Chart.tsx`:
- Around line 260-264: Extract a single async refreshData function (e.g., const
refreshData = async () => { const refreshed = await onDataRefresh();
setLiveData(refreshed); }) and use it both inside the setInterval handler and
wherever the second duplicate refresh call exists, replacing the duplicate
.then/.catch blocks; ensure you add explicit error handling in refreshData
(catch and call console.error or the app logger with the caught error) instead
of swallowing errors with empty catches so refresh failures are visible.

In `@client/src/components/shared/CopyCodeButton.tsx`:
- Around line 29-34: handleCopy in CopyCodeButton currently calls
navigator.clipboard.writeText without guarding for Clipboard API presence and
swallows errors; update handleCopy to first check for
navigator?.clipboard?.writeText and return a fallback if missing, then call
writeText inside a try/catch (or await it) so failures are caught and reported
(use console.error or the same reporting helper used in AdminTokenScopes) and
only call setCopied(true) on success; ensure any async errors are logged instead
of silently ignored.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1b566294-ef89-4845-b3e7-3c1cf42feda8

📥 Commits

Reviewing files that changed from the base of the PR and between 27a2cec and 2e3e16f.

📒 Files selected for processing (9)
  • .github/workflows/ci-alerter.yml
  • .github/workflows/ci-collector.yml
  • .github/workflows/ci-server.yml
  • .github/workflows/release.yml
  • alerter/Dockerfile
  • client/src/components/Chart/Chart.tsx
  • client/src/components/shared/CopyCodeButton.tsx
  • collector/Dockerfile
  • server/Dockerfile
🚧 Files skipped from review as they are similar to previous changes (7)
  • alerter/Dockerfile
  • collector/Dockerfile
  • .github/workflows/release.yml
  • .github/workflows/ci-alerter.yml
  • server/Dockerfile
  • .github/workflows/ci-server.yml
  • .github/workflows/ci-collector.yml

dpage and others added 11 commits April 21, 2026 11:37
Ensure appuser owns /etc/pgedge (all services) and /data
(server) so the non-root user can write to these directories
at runtime.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Deduplicate Chart refresh logic into a shared callback and
log errors. Guard clipboard API availability in CopyCodeButton
and log failures instead of swallowing them silently.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Auto-update SHA-pinned action references weekly to prevent
stale SHA drift.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
All 40 flagged locations use parameterized queries or trusted
internal values. Adding nosemgrep: go-sql-concat-sqli to
suppress confirmed false positives in Codacy scans.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add unknown type annotation to catch callback in Chart.
Remove unnecessary clipboard API guard in CopyCodeButton.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The data directory is resolved from flags before the config
file is loaded. Without --data-dir, it defaults to a path
relative to the binary (/usr/local/bin/data) which the
non-root appuser cannot create.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The server resolves its data directory from --data-dir flag
before loading the config file. When invoked via docker
compose exec (e.g., for user management), the CMD args
don't apply and the binary falls back to a path relative
to the executable. Create and chown this fallback directory.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Nginx must start as root to bind privileged port 80, then
drops to the nginx user for worker processes via its own
configuration. The USER directive prevented port binding.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@dpage dpage merged commit 9372b51 into main Apr 21, 2026
27 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.

Codacy audit: code quality and security fixes

1 participant