Skip to content

fix(ci): self-install pinned gosec and resolve findings to green Security Scanning - #1363

Merged
cristim merged 7 commits into
mainfrom
fix/ci-security-gosec
Jul 16, 2026
Merged

fix(ci): self-install pinned gosec and resolve findings to green Security Scanning#1363
cristim merged 7 commits into
mainfrom
fix/ci-security-gosec

Conversation

@cristim

@cristim cristim commented Jul 13, 2026

Copy link
Copy Markdown
Member

Root Cause

The security-scan job used the securego/gosec Docker action (@v2.26.1), which bundles its own Go 1.26.1 toolchain with GOTOOLCHAIN=local. The repository's go.mod requires Go 1.26.5 — a newer patch. With GOTOOLCHAIN=local, the bundled Go refuses to load the module, causing gosec to scan 0 files and exit 1 with a toolchain mismatch, not real findings. CI has been red since go.mod was bumped past 1.26.1.

CI Change

Replace the Docker action with a run: step that uses the job's existing setup-go (1.26.5) to install gosec:

- name: Run gosec Security Scanner
  run: |
    go install github.com/securego/gosec/v2/cmd/gosec@v2.26.1
    gosec -fmt sarif -out gosec-results.sarif ./...
- name: Upload gosec results to GitHub Security
  if: always()
  uses: github/codeql-action/upload-sarif@...

gosec stays hard-fail (no -no-fail). The SARIF upload gets if: always() so results reach the Security tab even when the scan finds issues.

Finding Disposition

Rule Count Action
G104 unhandled errors 6 real Fixed: os.Setenv returns checked in cmd/server/main.go and testutil; both m.Close() return values handled in migrate.go. False positives (hash.Write, tabwriter.Flush to bytes.Buffer) annotated.
G115 integer overflow 10 2 real: math.MaxInt32 bounds guards added in database/connection.go. Remainder annotated where values are provably bounded by AWS API limits, CLI flag defaults, or operator config.
G101 hardcoded credential 14 All false positives: credential-type name constants, email template body copy, env-var name constants for secret ARN lookups, public sentinel hash for timing-safe compare. Each annotated with concrete justification.
G204 subprocess variable 8 All deploy/CI tooling with hardcoded binary names (az, gcloud, npm, docker) and code-controlled args. Annotated.
G304 file path variable 7 All operator-configured paths (CLI args, WalkDir descendants, deployment config at ~/.cudly/). Annotated.
G303/G122 WalkDir TOCTOU 1 Deploy tooling reading its own output directory. Annotated.
G703 path traversal taint 3 Static file server: resolveStaticFilePath validates with filepath.Abs + containment check. Annotated.
G505 SHA-1 import 1 TOTP (RFC 6238) mandates HMAC-SHA1; switching to SHA256 breaks all authenticator apps. Annotated.
G706 log injection taint 10 Diagnostic logging of operator-controlled env vars and task type strings (validated before dispatch, printed with %q). Annotated.
G702 command injection 1 CI sanity test az invocation with hardcoded binary. Annotated.
G705 XSS via taint 1 Lambda response proxy; Content-Type set from validated Lambda response headers. Annotated.
G117 marshaled secret 2 Intentional marshaling of GCP/Azure credential structs for secure storage in the credential store. Annotated.

Final gosec result: Issues: 0, Nosec: 68, exit 0.

Verification

  • go build ./... exit 0
  • gosec ./... exit 0, Issues: 0, Nosec: 68
  • go test -short ./... 4716 passed in 21 packages, exit 0
  • govulncheck ./... no vulnerabilities found across all modules

Notes

The Lint Code check will remain red on this PR — that is pre-existing lint debt unrelated to security scanning and tracked separately.

Summary by CodeRabbit

  • Bug Fixes
    • Improved migration recovery error reporting by capturing and logging failures when closing database resources.
    • Improved test stability by handling environment variable set/restore failures during cleanup.
  • Build & Release
    • Build metadata environment variables now fail more transparently, logging when environment setting is unsuccessful.
  • Security
    • Updated CI security scanning: gosec now runs via a pinned install with merged SARIF results; Terraform IaC scanning now uses Trivy with distinct SARIF outputs and pinned Trivy version.

…rity Scanning

The securego/gosec Docker action bundles Go 1.26.1 with GOTOOLCHAIN=local,
which refuses to load the go.mod requiring Go 1.26.5. This causes gosec to
scan 0 files and exit 1 with a toolchain mismatch rather than real findings.

Fix: replace the Docker action with a go install step that uses the job's
existing setup-go toolchain (1.26.5) to install gosec@v2.26.1, then run it
directly. Add `if: always()` to the SARIF upload so results are uploaded
even when gosec finds issues.

After unblocking the toolchain gate, resolve all 68 real findings:
- G104 (unhandled errors): handle os.Setenv return values in cmd/server and
  testutil.SetEnv; handle both m.Close() return values in migrate.go;
  annotate hash.Hash64.Write and tabwriter.Flush into bytes.Buffer which
  cannot return errors per their respective interface contracts
- G115 (integer overflow): add math.MaxInt32 bounds guards in database
  connection pool config; annotate conversions where values are
  provably bounded by API/operator limits (RI counts, CLI flags, pool sizes)
- G101 (credential false positives): annotate credential-type name constants,
  email template body text, env-var name constants, and sentinel hash
- G204/G304/G122 (subprocess/file path): annotate deploy tooling (npm,
  docker, az, gcloud) where binary is hardcoded and args are code-controlled;
  annotate WalkDir-derived paths and operator-configured file paths
- G505 (SHA-1): annotate TOTP HMAC-SHA1 required by RFC 6238
- G706 (log injection): annotate diagnostic logging of operator-controlled
  env vars and validated task type strings
- G703 (path traversal): annotate static file server backed by
  resolveStaticFilePath with directory-containment validation
- G702 (command injection): annotate CI sanity test tooling with hardcoded binary
- G705 (XSS via taint): annotate Lambda response body proxy with explicit
  Content-Type guard
- G117 (marshaled secret fields): annotate intentional credential struct
  marshaling for secure storage

Result: gosec exits 0, Issues: 0, Nosec: 68.
go build ./... exits 0. go test -short ./... 4716 passed. govulncheck clean.
@cristim cristim added triaged Item has been triaged priority/p1 Next up; this sprint severity/high Significant harm urgency/now Drop other things impact/all-users Affects every user effort/m Days type/security Security finding labels Jul 13, 2026
@cristim

cristim commented Jul 13, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 40 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 06eb3800-404f-4289-b17e-ceffc9df309a

📥 Commits

Reviewing files that changed from the base of the PR and between d1db972 and c9cae65.

📒 Files selected for processing (1)
  • .github/workflows/ci.yml
📝 Walkthrough

Walkthrough

The pull request updates CI security scans, adds targeted gosec annotations across Go code, improves migration close-error logging, checks selected environment-setting failures, and handles test environment restoration errors.

Changes

Security lint and CI scanning

Layer / File(s) Summary
Security scan workflow
.github/workflows/ci.yml
Pinned gosec and Trivy versions are used; Terraform scanning now uses Trivy configuration analysis with separate SARIF output.
CLI, cloud, and deployment command paths
ci_cd_sanity_tests/..., cmd/..., internal/deploy/...
Validated conversions, credential operations, external commands, file access, and deployment paths receive targeted gosec annotations.

Application and server handling

Layer / File(s) Summary
Application security annotations and migration cleanup
internal/api/..., internal/auth/..., internal/config/..., internal/credentials/..., internal/database/..., internal/email/..., internal/oidc/..., internal/reporter/...
Security annotations document validated operations; migration recovery now captures and logs close errors.
Server logging, static paths, and environment errors
cmd/server/main.go, internal/server/..., internal/testutil/testutil.go
Server logging and static path operations receive annotations, environment export failures are logged, and test environment restoration checks Setenv errors.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related issues

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main CI change: self-installing pinned gosec and addressing security scan findings.
Docstring Coverage ✅ Passed Docstring coverage is 95.83% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/ci-security-gosec

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

@github-advanced-security

Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/ci.yml:
- Around line 321-327: Update the gosec workflow step to discover and scan every
Go module, including the root, pkg, and providers/* modules, rather than only
running gosec against root ./.... Generate SARIF output for each module, merge
the results into gosec-results.sarif, and preserve that merged file for the
existing upload and hard-fail checks.

In `@ci_cd_sanity_tests/cmd/ri-exchange/main.go`:
- Line 77: Validate the operator-provided targetCount before the int32
conversions used for TargetCount and the other referenced fields. In the main
CLI flow, enforce that targetCount is within the int32 range and reject
out-of-range values before downstream validation or exchange requests; retain
the existing G115 suppressions after this guard.

In `@ci_cd_sanity_tests/cmd/sanity/main.go`:
- Line 28: Validate the CLI maxList value before the int32 conversion used in
MaxList, rejecting any input outside the int32 range with an appropriate error.
Only perform the cast and retain the G115 suppression after validation, while
preserving accepted in-range values and the existing default behavior.

In `@internal/auth/service_mfa.go`:
- Line 7: Update the comment on the crypto/sha1 import to state that SHA-1 is
retained for broad authenticator compatibility and existing otpauth
provisioning; remove the claim that RFC 6238 mandates HMAC-SHA1 and acknowledge
that the RFC also permits SHA-256 and SHA-512.

In `@internal/deploy/frontend.go`:
- Line 95: Before the os.ReadFile call in the deployment file traversal,
validate the WalkDir entry’s type and reject entries whose Type includes
os.ModeSymlink. Ensure symlinked files are skipped or returned as an error
before reading, while preserving normal reads for regular deployment files.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 27874f72-a120-400f-a78e-e6eff63cb30d

📥 Commits

Reviewing files that changed from the base of the PR and between 79642c4 and 111d590.

📒 Files selected for processing (31)
  • .github/workflows/ci.yml
  • ci_cd_sanity_tests/cmd/ri-exchange/main.go
  • ci_cd_sanity_tests/cmd/sanity/main.go
  • ci_cd_sanity_tests/pkg/sanity/azure/azure.go
  • cmd/configure_azure.go
  • cmd/configure_gcp.go
  • cmd/helpers.go
  • cmd/multi_service_csv.go
  • cmd/server/main.go
  • internal/api/handler_purchases_revoke.go
  • internal/api/handler_ri_exchange.go
  • internal/auth/service_mfa.go
  • internal/auth/service_password.go
  • internal/config/constants.go
  • internal/credentials/cipher.go
  • internal/credentials/gcp_federated.go
  • internal/credentials/resolver.go
  • internal/database/connection.go
  • internal/database/postgres/migrations/migrate.go
  • internal/deploy/docker.go
  • internal/deploy/frontend.go
  • internal/deploy/profiles.go
  • internal/email/templates.go
  • internal/oidc/jwks.go
  • internal/reporter/reporter.go
  • internal/server/app.go
  • internal/server/handler.go
  • internal/server/http.go
  • internal/server/scheduledauth/validator.go
  • internal/server/static.go
  • internal/testutil/testutil.go

Comment thread .github/workflows/ci.yml Outdated
Comment thread ci_cd_sanity_tests/cmd/ri-exchange/main.go Outdated
Comment thread ci_cd_sanity_tests/cmd/sanity/main.go Outdated
Comment thread internal/auth/service_mfa.go Outdated
Comment thread internal/deploy/frontend.go Outdated
Once the gosec toolchain fix let the security-scan job run past gosec, the
previously-masked tfsec step ran and hard-failed on a parse error:

  scan failed: terraform/modules/deployment-checks/main.tf:61:
  Blocks of type "check" are not expected here

aquasecurity/tfsec-action is deprecated (tfsec is folded into Trivy) and its
bundled HCL parser does not understand Terraform 1.5+ `check {}` blocks. Its
soft_fail only downgrades findings, not scan/parse errors, so the step
hard-failed the job.

Replace it with Trivy config scanning (tfsec's official successor) scoped to
terraform/, preserving IaC misconfiguration coverage. Trivy parses `check {}`
blocks correctly and, like the existing filesystem Trivy step, uses the
default exit-code 0 so findings report to the Security tab without gating the
job, matching tfsec's prior soft_fail: true behaviour. The results upload uses
a distinct SARIF category so it does not overwrite the filesystem Trivy
analysis (both report as tool "Trivy").

The action stays pinned to the same aquasecurity/trivy-action SHA (v0.36.0)
already used for the filesystem scan.

Verified locally with Trivy 0.72.0: `trivy config terraform/` parses all 20
config files with no parse error, exit 0, 0 CRITICAL/HIGH findings.
@cristim

cristim commented Jul 13, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

The trivy-action IaC config scan panicked in CI:

  panic: value is null
  cty.Value.AsString(...)
  trivy/pkg/iac/adapters/terraform/aws/provider.adaptDefaultTags adapt.go:147
  Process completed with exit code 2

Root cause: aquasecurity/trivy-action@v0.36.0 (the latest release) bundles
Trivy v0.70.0, which panics in adaptDefaultTags on
terraform/environments/aws/main.tf's provider default_tags block because those
tag vars resolve to null when no tfvars are passed to the scan. The panic
exits 2 and no SARIF is written, so the upload step then fails on a missing
file. The bug is fixed in Trivy >= v0.72.0.

Since v0.36.0 is already the newest trivy-action release, pin the Trivy binary
independently via the action's `version` input, which it forwards to
aquasecurity/setup-trivy. Set both the filesystem scan and the IaC config scan
to v0.72.0 so they share one pinned binary. Both keep the default exit-code 0,
so findings report to the Security tab without gating the job.

Verified locally with Trivy 0.72.0: `trivy config terraform/` and `trivy fs .`
both run with no panic and exit 0.
@cristim

cristim commented Jul 13, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

cristim added 2 commits July 16, 2026 16:22
…nnotate nosec across modules

- ci_cd_sanity_tests/cmd/ri-exchange: add explicit range validation (1..math.MaxInt32)
  before int32 casts of --target-count; update #nosec G115 justification accordingly
- ci_cd_sanity_tests/cmd/sanity: same bounds check for --max-list
- internal/deploy/frontend.go: reject symlinks in WalkDir callback before os.ReadFile
  (ModeSymlink check); update #nosec G304,G122 with accurate justification
- internal/auth/service_mfa.go: correct #nosec G505 comment -- RFC 6238 also permits
  SHA-256/SHA-512; SHA-1 retained for broad authenticator app compatibility
- providers/aws/provider.go: fix init() to handle RegisterProvider error (panic on
  duplicate registration); annotate #nosec G101 on SDK provider-type name constants
- providers/azure/provider.go: same init() fix
- providers/gcp/provider.go: same init() fix; annotate #nosec G703 on CLOUDSDK_CONFIG
  and APPDATA env-var paths (standard system vars, not user input)
- providers/azure/services/{compute,internal/reservations}: annotate #nosec G104 on
  resp.Body.Close() calls where body is fully drained before Close
- providers/aws/services/{ec2,rds,redshift,opensearch,memorydb,elasticache}: annotate
  #nosec G115 on int32(rec.Count) -- CE recommendation counts stay far below MaxInt32
- pkg/logging/logger.go: annotate #nosec G115 on int32(level) -- Level is a bounded
  enum (0-3)
- pkg/config/load.go: annotate #nosec G101 on CUDLY_API_KEY (env var name, not
  credential) and #nosec G304 on operator-supplied config file path
- pkg/common/audit.go: extend existing #nosec G302 to cover G304 on audit log path
Root ./... silently misses pkg/ and providers/* (each is a separate Go
module). Mirror the govulncheck per-module loop: run gosec against each
of the six modules (., pkg, providers/aws, providers/azure, providers/gcp,
tests/e2e), collect per-module SARIF output to RUNNER_TEMP, then merge
all runs into gosec-results.sarif via a Python one-liner before the
existing upload-SARIF step.

All six modules are clean (0 findings) after the preceding commit.
@cristim

cristim commented Jul 16, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

…nline python

The multi-line python heredoc embedded in the run block started at
column 1, escaping the literal block scalar and making the whole
workflow file unparseable (run 29501998444 concluded failure with
zero jobs). Replace it with a single jq -s merge; jq is preinstalled
on the GitHub Ubuntu runner image so no new dependencies.

Validated with PyYAML parse, actionlint (exit 0), and a full local
simulation of the loop + merge (6 modules, 6 SARIF runs merged,
gosec exit 0 in every module).
@cristim

cristim commented Jul 16, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/deploy/frontend.go`:
- Around line 85-92: The uploadDirectory entry handling currently skips only
symlinks, allowing FIFOs, devices, and sockets to reach uploadFile. Before
calling uploadFile, obtain the entry info and require
d.Info().Mode().IsRegular(); skip and log non-regular entries, preserving
symlink rejection and adding a regression test covering a special file.

In `@providers/azure/services/internal/reservations/purchase.go`:
- Line 215: Handle the io.ReadAll errors before relying on the suppressed
resp.Body.Close calls: update the response-reading flows at
providers/azure/services/internal/reservations/purchase.go lines 214-215,
317-318, and 402-403 to check and propagate or otherwise appropriately handle
each read error before continuing. Ensure the Close annotations remain valid
only after a successful, fully drained read.

In `@providers/gcp/provider.go`:
- Around line 305-306: Update the `#nosec` G703 suppression comment beside the
os.Stat call in the relevant provider logic to describe CLOUDSDK_CONFIG and
APPDATA as environment-controlled under a trusted deployment, removing the
inaccurate claim that they are not user-controlled; leave the stat probe
unchanged.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: b1d1aa3b-ea2f-49b1-92e6-ba876baea9a0

📥 Commits

Reviewing files that changed from the base of the PR and between 4728c94 and d1db972.

📒 Files selected for processing (19)
  • .github/workflows/ci.yml
  • ci_cd_sanity_tests/cmd/ri-exchange/main.go
  • ci_cd_sanity_tests/cmd/sanity/main.go
  • internal/auth/service_mfa.go
  • internal/deploy/frontend.go
  • pkg/common/audit.go
  • pkg/config/load.go
  • pkg/logging/logger.go
  • providers/aws/provider.go
  • providers/aws/services/ec2/client.go
  • providers/aws/services/elasticache/client.go
  • providers/aws/services/memorydb/client.go
  • providers/aws/services/opensearch/client.go
  • providers/aws/services/rds/client.go
  • providers/aws/services/redshift/client.go
  • providers/azure/provider.go
  • providers/azure/services/compute/client.go
  • providers/azure/services/internal/reservations/purchase.go
  • providers/gcp/provider.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • internal/auth/service_mfa.go
  • ci_cd_sanity_tests/cmd/ri-exchange/main.go
  • .github/workflows/ci.yml

Comment on lines +85 to +92
// Reject symlinks: filepath.WalkDir does not traverse symlinks but
// os.ReadFile will dereference them. A symlinked file inside the build
// dir could point outside it, so we skip any symlink entry explicitly.
if d.Type()&fs.ModeSymlink != 0 {
log.Printf("deploy: skipping symlink %s", path)
return nil
}
// Convert to forward slashes for S3 keys
key := strings.ReplaceAll(relPath, string(filepath.Separator), "/")
return s.uploadFile(ctx, distDir, bucketName, path)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Map the relevant file first, then read the smallest useful slices.
ast-grep outline internal/deploy/frontend.go --view expanded || true

echo '--- file: internal/deploy/frontend.go (lines 1-220) ---'
cat -n internal/deploy/frontend.go | sed -n '1,220p'

Repository: LeanerCloud/CUDly

Length of output: 9865


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- search for uploadDirectory/uploadFile tests and special-file handling ---'
rg -n --hidden -S "uploadDirectory|uploadFile|ModeSymlink|IsRegular|WalkDir|special file|fifo|socket|device" internal . || true

echo '--- list test files near deploy package ---'
git ls-files 'internal/**' | rg '^internal/.+(_test\.go|testdata/)'

Repository: LeanerCloud/CUDly

Length of output: 13328


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- internal/deploy/frontend_test.go ---'
wc -l internal/deploy/frontend_test.go
cat -n internal/deploy/frontend_test.go | sed -n '1,260p'

echo '--- internal/deploy/coverage_extra_test.go ---'
wc -l internal/deploy/coverage_extra_test.go
cat -n internal/deploy/coverage_extra_test.go | sed -n '1,240p'

Repository: LeanerCloud/CUDly

Length of output: 19804


Reject all non-regular entries before reading them.

uploadDirectory only skips symlinks, so FIFOs, devices, or sockets can still reach os.ReadFile and block or read unintended data. Check d.Info().Mode().IsRegular() before calling uploadFile, and add a regression test for special files.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/deploy/frontend.go` around lines 85 - 92, The uploadDirectory entry
handling currently skips only symlinks, allowing FIFOs, devices, and sockets to
reach uploadFile. Before calling uploadFile, obtain the entry info and require
d.Info().Mode().IsRegular(); skip and log non-regular entries, preserving
symlink rejection and adding a regression test covering a special file.

}
body, _ := io.ReadAll(resp.Body)
resp.Body.Close()
resp.Body.Close() // #nosec G104 -- body fully drained by io.ReadAll before Close; transport close error does not affect correctness

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Check io.ReadAll errors before relying on the Close suppression.

Each site ignores the preceding read error, so the response may be partial despite the annotation claiming it was fully drained.

  • providers/azure/services/internal/reservations/purchase.go#L215-L215: handle the io.ReadAll error at Line 214 before continuing.
  • providers/azure/services/internal/reservations/purchase.go#L318-L318: handle the io.ReadAll error at Line 317 before continuing.
  • providers/azure/services/internal/reservations/purchase.go#L403-L403: handle the io.ReadAll error at Line 402 before continuing.
📍 Affects 1 file
  • providers/azure/services/internal/reservations/purchase.go#L215-L215 (this comment)
  • providers/azure/services/internal/reservations/purchase.go#L318-L318
  • providers/azure/services/internal/reservations/purchase.go#L403-L403
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@providers/azure/services/internal/reservations/purchase.go` at line 215,
Handle the io.ReadAll errors before relying on the suppressed resp.Body.Close
calls: update the response-reading flows at
providers/azure/services/internal/reservations/purchase.go lines 214-215,
317-318, and 402-403 to check and propagate or otherwise appropriately handle
each read error before continuing. Ensure the Close annotations remain valid
only after a successful, fully drained read.

Comment thread providers/gcp/provider.go
Comment on lines +305 to 306
_, err := os.Stat(filepath.Join(dir, adcFile)) // #nosec G703 -- CLOUDSDK_CONFIG is a standard gcloud env var set by the OS or gcloud CLI, not user-controlled input
return err == nil

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the file and inspect the relevant region with line numbers.
sed -n '280,330p' providers/gcp/provider.go

# Show the other mentioned suppression around line 309 if it differs nearby.
sed -n '300,315p' providers/gcp/provider.go

# Find all G703 suppressions in this file for context.
rg -n "nosec G703|CLOUDSDK_CONFIG|APPDATA" providers/gcp/provider.go

Repository: LeanerCloud/CUDly

Length of output: 3830


Fix the G703 suppression wording CLOUDSDK_CONFIG and APPDATA are environment-controlled, so the comment should state the trusted-deployment assumption instead of saying they are not user-controlled. The os.Stat probe itself is fine.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@providers/gcp/provider.go` around lines 305 - 306, Update the `#nosec` G703
suppression comment beside the os.Stat call in the relevant provider logic to
describe CLOUDSDK_CONFIG and APPDATA as environment-controlled under a trusted
deployment, removing the inaccurate claim that they are not user-controlled;
leave the stat probe unchanged.

Code scanning rejects a SARIF file whose runs share the same category
(github.blog changelog 2025-07-21): run 29512972014's gosec scan itself
passed on all six modules, but the upload-sarif step failed with "does
not support uploading multiple SARIF runs with the same category". The
Trivy IaC upload failure in the same run was a cascade (its scan step
was skipped after the gosec upload failed, so the file never existed).

Set a distinct automationDetails.id (gosec-<module>/) on each module's
run via jq before merging, so all six runs upload under their own
category. Verified locally: merged file contains 6 runs with 6 unique
automationDetails ids; PyYAML parse OK; actionlint exit 0.
@cristim

cristim commented Jul 16, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@cristim
cristim merged commit 904e993 into main Jul 16, 2026
16 of 18 checks passed
@cristim

cristim commented Jul 16, 2026

Copy link
Copy Markdown
Member Author

Merged to main: Security Scanning is GREEN on the merged head (gosec v2.26.1 pinned, ALL 6 Go modules scanned - the pre-merge review caught that only the root module was covered; 21 additional findings in pkg/providers fixed for real incl. two fail-loud init() fixes; per-module SARIF runs tagged with unique automationDetails.id after GitHub's same-category rejection; Trivy pinned v0.72.0). From here, any commit introducing a gosec finding fails its own PR. Lint Code remains the last debt job - #1364 retires it next. Closes the Security-Scanning half of the known-debt exception list.

@cristim
cristim deleted the fix/ci-security-gosec branch July 16, 2026 16:27
cristim added a commit that referenced this pull request Jul 16, 2026
gocritic importShadow: requireInt32Range's "flag" parameter shadowed the
imported flag package; rename to flagName. Surfaced after rebasing onto
main with #1363 merged.
cristim added a commit that referenced this pull request Jul 16, 2026
gocritic importShadow: requireInt32Range's "flag" parameter shadowed the
imported flag package; rename to flagName. Surfaced after rebasing onto
main with #1363 merged.
cristim added a commit that referenced this pull request Jul 16, 2026
gocritic importShadow: requireInt32Range's "flag" parameter shadowed the
imported flag package; rename to flagName. Surfaced after rebasing onto
main with #1363 merged.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/m Days impact/all-users Affects every user priority/p1 Next up; this sprint severity/high Significant harm triaged Item has been triaged type/security Security finding urgency/now Drop other things

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants