Skip to content

Fix path traversal via workspace consumer identifiers in DescriptionStorageService#7920

Merged
gavinbarron merged 2 commits into
mainfrom
gavinbarron/fix-description-storage-path-traversal
Jul 8, 2026
Merged

Fix path traversal via workspace consumer identifiers in DescriptionStorageService#7920
gavinbarron merged 2 commits into
mainfrom
gavinbarron/fix-description-storage-path-traversal

Conversation

@gavinbarron

Copy link
Copy Markdown
Contributor

Description

Fixes a path traversal vulnerability where workspace consumer identifiers (clientName / pluginName) and workspace configuration keys were used directly as filesystem path components when caching OpenAPI descriptions under .kiota/documents, with no canonicalization or containment validation.

A crafted consumer name such as junk/../Victim normalizes out of the intended .kiota/documents/<consumer>/ namespace and can overwrite a sibling consumer''s cached description. Subsequent client edit / plugin edit operations trust and load the poisoned cache before consulting the configured source, so SDKs/plugin manifests may be generated from an attacker-controlled specification (integrity violation).

Fixes #7919

Changes (defense-in-depth)

  1. Storage sinkDescriptionStorageService: added ValidateConsumerName and a normalized-containment check in GetDescriptionFilePath (mirrors the existing BaseApiConsumerConfiguration.ValidateOutputPath pattern). Rejects rooted / .. / separator names and any resolved path escaping .kiota/documents. Protects UpdateDescriptionAsync, GetDescriptionAsync, RemoveDescription.
  2. Builder serviceWorkspaceManagementService: early consumer-name validation wired into every entry point that receives a consumer identifier (IsConsumerPresentAsync, UpdateStateFromConfigurationAsync, GetDescriptionCopyAsync, RemoveClientAsync, RemovePluginAsync) — the chokepoint all CLI/RPC paths funnel through.
  3. Config inputWorkspaceConfigurationStorageService: validates client/plugin consumer keys on config load, closing the malicious-workspace.json vector.

Traversal names are rejected (throw InvalidOperationException) rather than silently sanitized. CLI handlers and RPC already catch and surface the friendly error message. Legitimate consumer names behave unchanged.

Testing

Developed via TDD (each test confirmed failing before its fix):

  • DescriptionStorageServiceTests — traversal names throw; victim cache remains untouched; valid names still work.

  • WorkspaceManagementServiceTests — all consumer entry points reject traversal names.

  • WorkspaceConfigurationStorageServiceTests — malicious client/plugin keys rejected on load.

  • dotnet test tests/Kiota.Builder.Tests2161 passed, 0 failed, 2 skipped.

  • dotnet build src/kiota (net8/9/10) — 0 warnings, 0 errors.

…torageService

Workspace consumer identifiers (clientName/pluginName) and workspace
configuration keys were used directly as filesystem path components when
caching OpenAPI descriptions under .kiota/documents, with no canonicalization
or containment validation. A crafted name such as junk/../Victim could escape
the intended consumer namespace and overwrite a sibling consumer's cached
description, which is later trusted by client/plugin edit operations.

Adds defense-in-depth validation:
- DescriptionStorageService: normalized-containment check + consumer-name
  validation at the storage sink.
- WorkspaceManagementService: early consumer-name validation at all entry
  points (is-present, update-state, get-description-copy, remove client/plugin).
- WorkspaceConfigurationStorageService: validates consumer keys on config load.

Adds regression tests for all three layers.

Fixes #7919

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@gavinbarron gavinbarron requested a review from a team as a code owner July 8, 2026 16:46
@msgraph-bot msgraph-bot Bot added this to Kiota Jul 8, 2026
Comment thread src/Kiota.Builder/WorkspaceManagement/DescriptionStorageService.cs Fixed
Comment thread src/Kiota.Builder/WorkspaceManagement/DescriptionStorageService.cs Dismissed
Comment thread tests/Kiota.Builder.Tests/WorkspaceManagement/DescriptionStorageServiceTests.cs Dismissed
Comment thread tests/Kiota.Builder.Tests/WorkspaceManagement/WorkspaceManagementServiceTests.cs Dismissed
Comment thread tests/Kiota.Builder.Tests/WorkspaceManagement/WorkspaceManagementServiceTests.cs Dismissed
Comment thread tests/Kiota.Builder.Tests/WorkspaceManagement/WorkspaceManagementServiceTests.cs Dismissed
@github-code-quality

github-code-quality Bot commented Jul 8, 2026

Copy link
Copy Markdown

Code Coverage Overview

Languages: C#

C# / code-coverage/dotnet

The overall coverage in the branch is 72%. Coverage data for the branch is not yet available.

Show a code coverage summary of the most covered files.
File 0d98948 +/-
/home/runner/wo...guageRefiner.cs 98%
/home/runner/wo...criptRefiner.cs 98%
/home/runner/wo...MethodWriter.cs 97%
/home/runner/wo...MethodWriter.cs 96%
/home/runner/wo...MethodWriter.cs 96%
/home/runner/wo...MethodWriter.cs 95%
/home/runner/wo...rs/GoRefiner.cs 93%
/home/runner/wo...KiotaBuilder.cs 90%
/home/runner/wo...ationService.cs 89%
/home/runner/wo...xGenerator.g.cs 75%

Updated July 08, 2026 18:55 UTC
Code Coverage is in Public Preview. Learn more and provide us with your feedback.

- Validate the description file extension (reject empty/rooted/separator) in
  GetDescriptionFilePath as defense-in-depth for the one non-constant segment.
- Use Path.Join instead of Path.Combine when joining the fixed relative
  documents subpath, silencing the analyzer's drop-earlier-arguments warning
  with no behavior change.
- Add regression tests for invalid extensions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-project-automation github-project-automation Bot moved this to In Progress 🚧 in Kiota Jul 8, 2026
@gavinbarron gavinbarron enabled auto-merge (squash) July 8, 2026 18:54
@gavinbarron gavinbarron disabled auto-merge July 8, 2026 18:54
@gavinbarron gavinbarron enabled auto-merge (squash) July 8, 2026 18:54
@gavinbarron gavinbarron merged commit 403c75f into main Jul 8, 2026
318 checks passed
@gavinbarron gavinbarron deleted the gavinbarron/fix-description-storage-path-traversal branch July 8, 2026 19:14
@github-project-automation github-project-automation Bot moved this from In Progress 🚧 to Done ✔️ in Kiota Jul 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done ✔️

Development

Successfully merging this pull request may close these issues.

Path traversal via workspace consumer identifiers in DescriptionStorageService

2 participants