Skip to content

.NET: Fix _CodeValidator os.* allow-list bypass for aliased imports (#7068)#7071

Open
eajajhossain wants to merge 1 commit into
microsoft:mainfrom
eajajhossain:issue-7068
Open

.NET: Fix _CodeValidator os.* allow-list bypass for aliased imports (#7068)#7071
eajajhossain wants to merge 1 commit into
microsoft:mainfrom
eajajhossain:issue-7068

Conversation

@eajajhossain

Copy link
Copy Markdown

The code validator in LocalCodeAct is supposed to only let generated code touch os.environ and os.path — everything else on os should be blocked. But it only checked for the literal name os, so renaming the module got right past it:

import os; os.system("id") # blocked (correct)
import os as x; x.system("id") # NOT blocked (bug)
import os; _o = os; _o.system("id") # NOT blocked (bug)

Same dangerous call, just a different variable name. This is effectively a sandbox escape, and this PR closes the hole so the os.environ/os.path-only rule actually holds.

  • Major changes: Instead of checking for the literal name os, the validator now tracks every name that points at the os module (via import ... as, import os.path, and plain assignments like _o = os) and checks against that set. This mirrors the approach visit_ImportFrom already uses. Changes are in validator.py, plus new regression tests.

  • Impact: Aliased/renamed access to os is now blocked just like direct access. Normal usage (os.environ, os.path, and import os.path as p; p.join(...)) still works, and there are tests to make sure it isn't over-blocked. No public API changes — only the embedded Python script and its tests.

  • Focus for reviewers: The edge cases - that import os.path as p is correctly not treated as an os alias, and that assignment tracking doesn't accidentally block legitimate code.

Related Issue

Fixes #7068

Contribution Checklist

  • The code builds clean without any errors or warnings
  • All unit tests pass, and I have added new tests where possible
  • The PR follows the Contribution Guidelines
  • This PR is linked to an issue and there is no other open PR for this issue (see Related Issue above).
  • This is not a breaking change. If it is a breaking change, add the breaking change label (or add "[BREAKING]" to the title prefix, before or after any language prefix) - a workflow keeps the label and title prefix in sync automatically.

Copilot AI review requested due to automatic review settings July 12, 2026 14:20
@giles17 giles17 added the .NET Usage: [Issues, PRs], Target: .Net label Jul 12, 2026
@github-actions github-actions Bot changed the title Fix _CodeValidator os.* allow-list bypass for aliased imports (#7068) .NET: Fix _CodeValidator os.* allow-list bypass for aliased imports (#7068) Jul 12, 2026

Copilot AI 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.

Pull request overview

This PR hardens the embedded Python _CodeValidator used by .NET LocalCodeAct so the documented os.environ / os.path-only policy is enforced even when the os module is accessed via aliases or simple re-bindings, closing a sandbox-escape class of bypasses.

Changes:

  • Track names bound to the os module (import os as ..., import os.path, and x = os / annotated assigns) and enforce the os attribute allow-list against that alias set.
  • Update visit_Attribute to enforce the allow-list based on alias membership rather than the literal identifier os.
  • Add integration tests to verify disallowed os.* usage is blocked and permitted os.environ/os.path usage still works (including import os.path as p).

Reviewed changes

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

File Description
dotnet/src/Microsoft.Agents.AI.LocalCodeAct/Resources/validator.py Implements os alias tracking (imports + assignments) and applies it to the os attribute allow-list enforcement.
dotnet/tests/Microsoft.Agents.AI.LocalCodeAct.UnitTests/LocalExecuteCodeFunctionIntegrationTests.cs Adds regression coverage for blocked os.* access via aliases/rebindings and ensures allowed os.environ/os.path access remains functional.

Comment on lines +343 to +354
def visit_Assign(self, node: ast.Assign) -> None:
"""Track re-bindings of the ``os`` module (e.g. ``_o = os``).

Assigning an existing ``os`` alias to new names must carry the
``os`` attribute allow-list along, otherwise ``_o = os; _o.system(...)``
would sidestep ``visit_Attribute``.
"""
if isinstance(node.value, ast.Name) and node.value.id in self._os_aliases:
for target in node.targets:
if isinstance(target, ast.Name):
self._os_aliases.add(target.id)
self.generic_visit(node)
Comment on lines +73 to +76
[InlineData("import os as x\nx.system('id')")]
[InlineData("import os\n_o = os\n_o.system('id')")]
[InlineData("import os as x\na = x\nb = a\nb.popen('id')")]
[InlineData("import os.path\nos.system('id')")]
@eajajhossain

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

.NET Usage: [Issues, PRs], Target: .Net

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python: .NET: [Bug]: _CodeValidator does not enforce the documented os.environ/os.path-only policy for aliased imports

3 participants