Fix path traversal via workspace consumer identifiers in DescriptionStorageService#7920
Merged
gavinbarron merged 2 commits intoJul 8, 2026
Merged
Conversation
…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>
Code Coverage OverviewLanguages: C# C# / code-coverage/dotnetThe 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.
Updated |
- 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>
jingjingjia-ms
approved these changes
Jul 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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/../Victimnormalizes out of the intended.kiota/documents/<consumer>/namespace and can overwrite a sibling consumer''s cached description. Subsequentclient edit/plugin editoperations 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)
DescriptionStorageService: addedValidateConsumerNameand a normalized-containment check inGetDescriptionFilePath(mirrors the existingBaseApiConsumerConfiguration.ValidateOutputPathpattern). Rejects rooted /../ separator names and any resolved path escaping.kiota/documents. ProtectsUpdateDescriptionAsync,GetDescriptionAsync,RemoveDescription.WorkspaceManagementService: 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.WorkspaceConfigurationStorageService: validates client/plugin consumer keys on config load, closing the malicious-workspace.jsonvector.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.Tests— 2161 passed, 0 failed, 2 skipped.dotnet build src/kiota(net8/9/10) — 0 warnings, 0 errors.