Skip to content

🐛 ci: harden CI against SonarCloud vulnerability findings#358

Merged
Chisanan232 merged 6 commits into
mainfrom
fix/sonarcloud-ci-hardening
Jul 23, 2026
Merged

🐛 ci: harden CI against SonarCloud vulnerability findings#358
Chisanan232 merged 6 commits into
mainfrom
fix/sonarcloud-ci-hardening

Conversation

@Chisanan232

Copy link
Copy Markdown
Contributor

Summary

  • Adds --locked --no-build to every uv sync/uv run call in verify-python.yml, verify-all-samples.yml, and verify-scenarios.yml (fixes githubactions:S8544/S8541, 72 findings). One documented exception: python/semantic-kernel-tool-policy keeps source builds because its transitive dep pybars4 ships no wheel on PyPI.
  • Adds --ignore-scripts to every pnpm install in verify-node.yml, verify-live.yml, verify-scenarios.yml, verify-all-samples.yml (fixes githubactions:S6505, 10 findings). Verified no example relies on an install lifecycle script.
  • Pins and adds --only-binary=:all: to the two bare pip install calls in verify-live.yml/verify-scenarios.yml (part of the S8541/S8544 family for pip).
  • Fixes the 3 Dockerfile findings in scenarios/live-core-enforcement/python-agent/Dockerfile (docker:S8482/S8541/S8544): verifies rustup's published sha256 before executing it instead of piping curl to sh, and pins+locks the pip install maturin agent-assembly step with --only-binary=:all:.
  • Adds .sonarcloud.properties with sonar.cpd.exclusions for the ~30 files where policy.py/policy.ts/policy.go/main.py/test_smoke.py are intentionally duplicated across independent, self-contained example subprojects (this repo's whole design point). This project uses SonarCloud Automatic Analysis, which ignores sonar-project.properties, so the exclusion goes in .sonarcloud.properties instead (no wildcards allowed there, hence the explicit file list).
  • Regenerates python/haystack-tool-policy/uv.lock (was stale relative to its pyproject.toml constraint; no dependency version changes, only metadata).

Why

Fixes the 85 open SonarCloud VULNERABILITY findings dragging this repo's Security rating to 5.0 (worst), plus brings duplicated-lines density reporting in line with intentional design (each example must stay copy-paste-able, so the org's <3% duplication threshold doesn't apply here without an exclusion).

Test plan

  • Verified every distinct uv sync/uv run --locked --no-build invocation succeeds locally, one directory at a time (all 16 python/* examples + scenarios/policy-enforcement/python + scenarios/approval-gates/python), including the --mock/src/main.py entrypoints
  • Verified python/semantic-kernel-tool-policy still installs/tests without --no-build and documented why
  • Verified all 6 node/* pnpm examples plus scenarios/policy-enforcement/node and scenarios/approval-gates/node install/typecheck/test cleanly with --ignore-scripts
  • Verified the two pinned pip install --only-binary=:all: commands resolve to wheels in an isolated venv
  • Built the fixed Dockerfile locally end-to-end (multi-arch aware via TARGETARCH) and confirmed the native agent_assembly._core extension still loads in the built image
  • Validated all edited YAML files parse and the Dockerfile passes hadolint with no new warnings

SonarCloud flagged 72 findings (githubactions:S8544/S8541) across the uv
sync/run invocations in verify-python, verify-all-samples, and
verify-scenarios: none asserted --locked against uv.lock or passed
--no-build, so a stale lockfile or a malicious sdist build script could
silently change what gets installed in CI.

Adds --locked --no-build to every uv sync/uv run call, with one documented
exception: python/semantic-kernel-tool-policy can't use --no-build because
its transitive dep pybars4 ships no wheel on PyPI (sdist only). Also
regenerates python/haystack-tool-policy/uv.lock, which was stale relative to
its pyproject.toml constraint (>=2.31.0,<3.0 -> <4.0); no dependency
versions changed, only the recorded constraint metadata.
SonarCloud flagged 6 findings (githubactions:S6505) in verify-node.yml: pnpm
install ran without --ignore-scripts, letting a compromised dependency's
lifecycle script (preinstall/install/postinstall) execute arbitrary code
during CI. Verified none of the 6 node examples rely on a lifecycle script
(no preinstall/install/postinstall/prepare entries in any package.json) and
that install/typecheck/test still pass with the flag added.
SonarCloud flagged 3 findings (docker:S8482/S8541/S8544) in the
live-core-enforcement python-agent Dockerfile:
- line 15 piped curl straight to sh to install rustup with no verification
  of what was being executed (S8482);
- line 24 installed maturin and agent-assembly unpinned and without
  --only-binary=:all:, allowing an sdist build script to run (S8541/S8544).

Fixes: download rustup-init and its published sha256 digest separately,
verify with sha256sum -c before chmod+exec (resolving the arch via
TARGETARCH so both amd64 and arm64 runners work); pin maturin==1.14.1 and
agent-assembly==0.0.1rc6 with --only-binary=:all: (both already ship wheels
for this platform, so no build behavior changes). Verified end-to-end with
a local docker build — the native agent_assembly._core extension still
loads correctly in the built image.
This repo's SonarCloud project shows 6% duplicated lines (org threshold
<3%), almost entirely from per-example policy.py/policy.ts/policy.go (plus
a few main.py/index.ts/test_smoke.py) files that are deliberately
duplicated across ~13 independent example subprojects — this is a
tutorials repo where each example must be self-contained and
copy-paste-able, so extracting a shared module would break that goal.

Adds .sonarcloud.properties (not sonar-project.properties, which Automatic
Analysis ignores) with sonar.cpd.exclusions listing the exact 30 duplicated
files from the current duplication report — this property disallows
wildcard patterns, so no repo has no sonar-scanner CI step; analysis runs
via SonarCloud's Automatic Analysis, confirmed via the scanner context's
sonar.autoscan.enabled=true.
The previous fix built the uv flag as $no_build_flag (empty string for
semantic-kernel-tool-policy, "--no-build" otherwise) and interpolated it
into the case statement. SonarCloud's static analysis can't follow that
indirection and re-flagged the interpolated call sites as if --no-build
were always missing (githubactions:S8541, re-triggered on this PR's diff).
Split into two literal case statements instead — one for
semantic-kernel-tool-policy (no --no-build, documented why) and one for
everything else (always --no-build) — so every call site is a static,
directly-scannable command.
discover_samples.py always classifies python/semantic-kernel-tool-policy as
uv-pytest (it has a tests/ dir), so the uv-main/py-script cases inside its
--no-build exception branch were unreachable — but SonarCloud's static
analysis flagged them anyway (githubactions:S8541) since it scans every
literal command, reachable or not. Collapses the exception to the one path
that's actually taken, with a guard that fails loudly if discovery's
classification ever changes.
@sonarqubecloud

Copy link
Copy Markdown

@Chisanan232
Chisanan232 merged commit 746b1aa into main Jul 23, 2026
83 checks passed
@Chisanan232
Chisanan232 deleted the fix/sonarcloud-ci-hardening branch July 23, 2026 07:26
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.

1 participant