Skip to content

fix(security): validate patterns_path in drift service (sonar S2083)#167

Merged
zaebee merged 2 commits into
mainfrom
fix/sonar-drift-path-validation
Jun 11, 2026
Merged

fix(security): validate patterns_path in drift service (sonar S2083)#167
zaebee merged 2 commits into
mainfrom
fix/sonar-drift-path-validation

Conversation

@zaebee

@zaebee zaebee commented Jun 11, 2026

Copy link
Copy Markdown
Owner

Summary

  • Taint flow: cgis_drift(db_path, patterns_path, ...) in mcp_server.pyanalyze_drift(db_path, patterns_path, ...) in drift_service.pyDriftScorer.__init__ doing Path(patterns_config).read_text() in drift.py:109. An LLM agent driving the MCP server could feed arbitrary paths (e.g. .env, /etc/passwd) — parse-error echoes from the YAML parser could leak content fragments.
  • Fix: In analyze_drift (the shared service layer used by both MCP and CLI), patterns_path is now canonicalized via Path(patterns_path).resolve() before use. The resolved path must have suffix .yaml or .yml (raises ValueError otherwise) and must exist as a file (raises FileNotFoundError otherwise). The resolved canonical path string is passed into DriftScorer, breaking the direct taint chain.
  • Deliberate non-containment: No cwd-containment (path.is_relative_to(cwd)) was added. cgis is a local-first dev tool where pointing at sibling repos is a supported cross-repo use-case; containment would break that workflow.

Tests added (tests/unit/test_drift_service.py)

  • test_analyze_drift_bad_suffix_raises — wrong suffix (.txt) → ValueError
  • test_analyze_drift_resolved_path_works — valid .yaml file → correct DriftAnalysis returned

Gates

All 722 unit + self-parsing tests pass; ruff, mypy strict, and pre-commit hooks clean.

Sonar note

If Sonar's taint engine does not recognize the suffix check + resolve() as a sanitizer, the issue should be marked accepted with this PR as justification: the path is validated to a YAML-only resolved canonical value before being read, and arbitrary file disclosure is not achievable through this vector.

🤖 Generated with Claude Code

Resolves SonarCloud BLOCKER S2083 (path injection): canonicalize and
suffix-check patterns_path in analyze_drift() before constructing
DriftScorer, breaking the taint chain from MCP tool inputs to the YAML
parser. Two new unit tests cover the ValueError and happy-path cases.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request introduces validation for the patterns_path in the analyze_drift function, ensuring it has a valid .yaml or .yml suffix and exists on disk after being resolved. Corresponding unit tests have also been added to verify this behavior. The review feedback correctly identifies that the suffix check is case-sensitive and suggests using .lower() to ensure case-insensitive matching for extensions like .YAML.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/cgis/query/drift_service.py Outdated
@zaebee

zaebee commented Jun 11, 2026

Copy link
Copy Markdown
Owner Author

/guardian review

@github-actions github-actions 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.

LGTM — no defects found in this diff.

Reviewed diff for logic correctness, type safety, library contracts, ontology compliance, and test coverage. All changes are correct and properly tested.


🤖 mistral-medium-latest · 4,460 prompt + 39 completion = 4,499 tokens · graph 1/2 files (50%)

github-actions Bot added a commit that referenced this pull request Jun 11, 2026
Path.suffix preserves original casing, so .YAML/.Yml were rejected.
Normalize with .lower() before the allow-list check (gemini review).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

@zaebee zaebee merged commit 1f7d35c into main Jun 11, 2026
3 checks passed
@zaebee zaebee deleted the fix/sonar-drift-path-validation branch June 11, 2026 11:15
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