Skip to content

.Net: Harden CloudDrivePlugin defaults and add path validation#13958

Merged
SergeyMenshykh merged 9 commits into
microsoft:mainfrom
SergeyMenshykh:fix/cloud-drive-security
May 8, 2026
Merged

.Net: Harden CloudDrivePlugin defaults and add path validation#13958
SergeyMenshykh merged 9 commits into
microsoft:mainfrom
SergeyMenshykh:fix/cloud-drive-security

Conversation

@SergeyMenshykh
Copy link
Copy Markdown
Member

Description

  • Improve default settings in CloudDrivePlugin
  • Add path validation for share-link operations
  • Improve path canonicalization
  • Add regression tests

Contribution Checklist

  • The code builds clean without any errors or warnings
  • The PR follows the SK Contribution Guidelines
  • The existing tests pass
  • New tests added

SergeyMenshykh and others added 2 commits May 6, 2026 15:25
…th validation

- Change CreateLinkAsync default scope from 'anonymous' to 'organization'
- Add AllowedSharePaths property with deny-all default for share link operations
- Add IsSharePathAllowed validation with normalized prefix matching
- Update ICloudDriveConnector default scope parameter to 'organization'
- Add regression tests for scope, deny-all default, path allow/deny, subdirectories

Fixes: #115112, #115113

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 6, 2026 14:41
@SergeyMenshykh SergeyMenshykh requested a review from a team as a code owner May 6, 2026 14:41
@moonbox3 moonbox3 added the .NET Issue or Pull requests regarding .NET code label May 6, 2026
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

Automated Code Review

Reviewers: 4 | Confidence: 88%

✓ Correctness

The PR adds path validation for share-link operations and hardens defaults. The IsSharePathAllowed method has a path traversal vulnerability: it only normalizes backslashes to forward slashes but does not collapse .. segments. An input like /Documents/../Confidential/secret.docx with AllowedSharePaths = ["/Documents"] would pass the StartsWith check because the extracted directory /Documents/../Confidential/ starts with /Documents/, yet the Graph API would resolve it to /Confidential/secret.docx. The local-path equivalent (IsUploadPathAllowed) is protected because CanonicalizePath calls Path.GetFullPath which resolves traversal, but no analogous normalization exists for remote paths.

✓ Security Reliability

The PR adds path validation for share-link operations and hardens defaults (scope changed from 'anonymous' to 'organization'). However, the new IsSharePathAllowed method has a path traversal vulnerability: it normalizes slashes but does not resolve .. segments, so a path like /Documents/../Confidential/secret.docx would pass validation when only /Documents is allowed, since the string "/Documents/../Confidential/" starts with "/Documents/". The IsUploadPathAllowed path correctly uses Path.GetFullPath() for canonicalization, but the remote-path validator has no equivalent normalization for dot-dot sequences.

✓ Test Coverage

The PR adds good test coverage for the new AllowedSharePaths validation and CanonicalizePath refactoring. Tests cover happy path, deny-by-default, deny outside allowed paths, subdirectory allowance, organization scope verification, UNC-after-env-var-expansion, and traversal-after-env-var-expansion. One notable gap: no test verifies that path traversal segments ('..') in remote share paths are handled by IsSharePathAllowed, which uses only string prefix matching without resolving relative segments.

✗ Design Approach

I found one design-level issue worth requesting changes on: the PR hardens CloudDrivePlugin.CreateLinkAsync correctly by passing "organization" explicitly, but it also changes the public ICloudDriveConnector optional default without changing the concrete OneDriveConnector method default. In C#, optional-parameter defaults are chosen from the static type at the callsite, so this creates two different default behaviors for the same operation depending on whether callers hold the object as ICloudDriveConnector or OneDriveConnector.


Automated review by SergeyMenshykh's agents

Comment thread dotnet/src/Plugins/Plugins.MsGraph/CloudDrivePlugin.cs Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR hardens the .NET MsGraph CloudDrivePlugin by making sharing behavior more restrictive by default, adding allowlist-based validation for share-link creation, and improving local upload path canonicalization (including env-var expansion) with regression tests.

Changes:

  • Add AllowedSharePaths allowlist and enforce it in CreateLinkAsync (deny by default).
  • Change share-link scope defaults to "organization" and add tests covering the new defaults and validation behavior.
  • Centralize local path canonicalization for uploads (expand env vars, block UNC) and add env-var bypass regression tests.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
dotnet/src/Plugins/Plugins.UnitTests/MsGraph/CloudDrivePluginTests.cs Adds/updates tests for share-path allowlisting and env-var expansion hardening.
dotnet/src/Plugins/Plugins.MsGraph/ICloudDriveConnector.cs Changes default scope for share links to "organization".
dotnet/src/Plugins/Plugins.MsGraph/CloudDrivePlugin.cs Introduces AllowedSharePaths, enforces share-path validation, and adds canonicalization for upload paths.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread dotnet/src/Plugins/Plugins.MsGraph/ICloudDriveConnector.cs
Comment thread dotnet/src/Plugins/Plugins.MsGraph/CloudDrivePlugin.cs Outdated
Comment thread dotnet/src/Plugins/Plugins.MsGraph/CloudDrivePlugin.cs Outdated
Comment thread dotnet/src/Plugins/Plugins.MsGraph/CloudDrivePlugin.cs Outdated
- Collapse '..' segments in IsSharePathAllowed via NormalizeRemotePath()
  to prevent traversal bypass (e.g. /Documents/../Confidential/secret.docx)
- Update OneDriveConnector.CreateShareLinkAsync default scope from
  'anonymous' to 'organization' to match ICloudDriveConnector interface
- Reject forward-slash UNC paths (//server/share) in CanonicalizePath,
  both before and after environment variable expansion
- Clarify AllowedSharePaths XML docs: entries are directory prefixes
- Add tests for share path traversal and forward-slash UNC rejection

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The Split(char, StringSplitOptions) overload is not available in
.NET Standard 2.0. Use Split(char[], StringSplitOptions) instead.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…destination

- Add AllowedReadPaths property to gate GetFileContentAsync (remote read)
- Add AllowedUploadDestinationPaths property to gate UploadFileAsync destination
- Refactor IsSharePathAllowed into reusable IsAllowedRemotePath helper
- Update class-level docs to reference all four allow-list properties
- Add regression tests for new validation (deny-by-default, path traversal,
  subdirectory support, connector-not-called assertions)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
SergeyMenshykh and others added 2 commits May 6, 2026 19:19
…destination

- Add AllowedReadPaths property to gate GetFileContentAsync (remote read)
- Add AllowedUploadDestinationPaths property to gate UploadFileAsync destination
- Refactor IsSharePathAllowed into reusable IsAllowedRemotePath helper
- Update class-level docs to reference all four allow-list properties
- Add regression tests for new validation (deny-by-default, path traversal,
  subdirectory support, connector-not-called assertions)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Member

@lokitoth lokitoth left a comment

Choose a reason for hiding this comment

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

We have several places in the codebase where we do this some kind of path normalization / no-escape validation. Should we unify them into some shared set of helpers?

@SergeyMenshykh
Copy link
Copy Markdown
Member Author

We have several places in the codebase where we do this some kind of path normalization / no-escape validation. Should we unify them into some shared set of helpers?

Let me try to extract common normalization and validation bits into sharable utils in the next PR.

@SergeyMenshykh SergeyMenshykh added this pull request to the merge queue May 8, 2026
Merged via the queue into microsoft:main with commit 3dd139b May 8, 2026
18 checks passed
@SergeyMenshykh SergeyMenshykh deleted the fix/cloud-drive-security branch May 8, 2026 11:45
@github-project-automation github-project-automation Bot moved this from In Review to Done in Agent Framework May 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

.NET Issue or Pull requests regarding .NET code

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

6 participants