Skip to content

fix(WPF): deny WPF Behaviors namespaces in untrusted homepage XAML - #3049

Open
lhx077 wants to merge 1 commit into
devfrom
codex/propose-fix-for-wpf-behaviors-vulnerability
Open

lhx077 wants to merge 1 commit into
devfrom
codex/propose-fix-for-wpf-behaviors-vulnerability

Conversation

@lhx077

@lhx077 lhx077 commented Jun 6, 2026 •

Copy link
Copy Markdown
Member

Motivation

  • The project added Microsoft.Xaml.Behaviors.Wpf and a TriggerAction-derived animation action (RunAnimationAction), which expands the XAML surface and enables generic behavior actions that can invoke methods from untrusted homepage XAML.
  • Prevent attacker-supplied homepage markup from referencing behavior types (e.g., CallMethodAction/ChangePropertyAction) that could enable arbitrary method/property invocation.

Description

  • Add a pre-parse namespace denylist in ModBase.GetObjectFromXML(string) that scans the XAML string and throws UnauthorizedAccessException when it contains any of Microsoft.Xaml.Behaviors, Microsoft.Xaml.Behaviors.Core, Microsoft.Xaml.Interactions.Core, or http://schemas.microsoft.com/xaml/behaviors.
  • Preserve the existing compatibility rewrites and the XamlXmlReader-based type/member blacklist and continue to load via XamlReader.Load when checks pass.

Testing

  • Verified the denylist insertion with a local Python presence check that confirms the new namespace checks are present and would trigger the UnauthorizedAccessException path.
  • Ran repository checks including git diff --check to ensure no style/whitespace issues were introduced.
  • Could not run dotnet build 'Plain Craft Launcher 2/Plain Craft Launcher 2.csproj' -c Debug -v:minimal in this environment because dotnet is not installed, so compilation was not validated here.

Codex Task

Summary by Sourcery

错误修复:

  • 当不受信任的主页 XAML 引用 Microsoft.Xaml.Behaviors 或相关行为命名空间时,在解析之前抛出 UnauthorizedAccessException,以防止加载这些 XAML。
Original summary in English

Summary by Sourcery

Bug Fixes:

  • Prevent untrusted homepage XAML from loading when it references Microsoft.Xaml.Behaviors or related behaviors namespaces by throwing an UnauthorizedAccessException before parsing.

@pcl-ce-automation pcl-ce-automation Bot added 🛠️ 等待审查 Pull Request 已完善,等待维护者或负责人进行代码审查 size: S PR 大小评估:小型 and removed codex labels Jun 6, 2026
@sourcery-ai

sourcery-ai Bot commented Jun 6, 2026 •

Copy link
Copy Markdown
Contributor
审阅者指南(在小型 PR 上折叠)

审阅者指南

在 ModBase.GetObjectFromXML 中添加预解析 XAML 命名空间拒绝列表(denylist),用于在不可信的主页 XAML 中阻止不安全的 WPF Behaviors 命名空间,同时保留现有的兼容性重写和基于 XamlXmlReader 的检查。

更新后的 ModBase.GetObjectFromXML XAML 安全检查顺序图

sequenceDiagram
    participant HomepageLoader
    participant ModBase
    participant XamlReader

    HomepageLoader->>ModBase: GetObjectFromXML(str)
    ModBase->>ModBase: Apply compatibility Replace calls
    ModBase->>ModBase: Scan for blockedXamlNamespace
    alt blocked namespace found
        ModBase-->>HomepageLoader: throw UnauthorizedAccessException
    else no blocked namespace
        ModBase->>XamlReader: Load(stream)
        XamlReader-->>ModBase: object
        ModBase-->>HomepageLoader: object
    end
Loading

文件级更改

变更 详情 文件
添加预解析拒绝列表,在不可信的主页 XAML 中阻止不安全的 WPF Behaviors 命名空间,一旦遇到则抛出 UnauthorizedAccessException。
  • 在 XAML 解析之前插入一个 foreach 循环,遍历一个硬编码的被阻止 WPF Behaviors 命名空间和架构(schema)URL 列表。
  • 对原始 XAML 文本针对每个被阻止命名空间执行不区分大小写的字符串检查。
  • 当发现被阻止命名空间时,抛出带有本地化错误消息的 UnauthorizedAccessException,中止后续处理和解析。
Plain Craft Launcher 2/Modules/Base/ModBase.cs

提示与命令

与 Sourcery 交互

  • 触发新的代码审阅: 在 pull request 中评论 @sourcery-ai review。
  • 继续讨论: 直接回复 Sourcery 的审阅评论。
  • 从审阅评论生成 GitHub issue: 在某条审阅评论下回复,要求 Sourcery 基于该评论创建 issue。你也可以直接回复 @sourcery-ai issue 来从该评论创建 issue。
  • 生成 pull request 标题: 在 pull request 标题中任意位置写上 @sourcery-ai,即可随时生成标题。你也可以在 pull request 中评论 @sourcery-ai title 来(重新)生成标题。
  • 生成 pull request 摘要: 在 pull request 正文的任意位置写上 @sourcery-ai summary,即可在你想要的位置生成 PR 摘要。你也可以在 pull request 中评论 @sourcery-ai summary 来在任何时候(重新)生成摘要。
  • 生成审阅者指南: 在 pull request 中评论 @sourcery-ai guide,即可在任何时候(重新)生成审阅者指南。
  • 批量解决所有 Sourcery 评论: 在 pull request 中评论 @sourcery-ai resolve 来将所有 Sourcery 评论标记为已解决。如果你已经处理完所有评论且不想再看到它们,这会很有用。
  • 忽略所有 Sourcery 审阅: 在 pull request 中评论 @sourcery-ai dismiss 来忽略所有现有的 Sourcery 审阅。尤其适用于你想从头开始一次新的审阅——别忘了评论 @sourcery-ai review 来触发新的审阅!

自定义你的体验

访问你的 控制面板 来:

  • 启用或禁用审阅功能,如 Sourcery 生成的 pull request 摘要、审阅者指南等。
  • 更改审阅使用的语言。
  • 添加、删除或编辑自定义审阅指令。
  • 调整其他审阅设置。

获取帮助

Original review guide in English
Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Adds a pre-parse XAML namespace denylist in ModBase.GetObjectFromXML to block unsafe WPF Behaviors namespaces in untrusted homepage XAML while preserving existing compatibility rewrites and XamlXmlReader-based checks.

Sequence diagram for updated ModBase.GetObjectFromXML XAML security checks

sequenceDiagram
    participant HomepageLoader
    participant ModBase
    participant XamlReader

    HomepageLoader->>ModBase: GetObjectFromXML(str)
    ModBase->>ModBase: Apply compatibility Replace calls
    ModBase->>ModBase: Scan for blockedXamlNamespace
    alt blocked namespace found
        ModBase-->>HomepageLoader: throw UnauthorizedAccessException
    else no blocked namespace
        ModBase->>XamlReader: Load(stream)
        XamlReader-->>ModBase: object
        ModBase-->>HomepageLoader: object
    end
Loading

File-Level Changes

Change Details Files
Add a pre-parse denylist that blocks unsafe WPF Behaviors namespaces in untrusted homepage XAML and throws UnauthorizedAccessException when encountered.
  • Insert a foreach loop before XAML parsing that iterates over a hard-coded list of blocked WPF Behaviors namespaces and schema URLs.
  • Perform case-insensitive string checks against the raw XAML for each blocked namespace.
  • Throw UnauthorizedAccessException with a localized error message when a blocked namespace is found, aborting further processing and parsing.
Plain Craft Launcher 2/Modules/Base/ModBase.cs

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai 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.

Hey - 我在这里给出一些高层面的反馈:

  • string.Contains(blockedXamlNamespace, StringComparison.OrdinalIgnoreCase) 这个重载在较旧的 .NET Framework 目标中不可用;为避免潜在的编译问题,建议改用 IndexOf(blockedXamlNamespace, StringComparison.OrdinalIgnoreCase) >= 0。
  • 被阻止的 XAML 命名空间列表在每次调用 GetObjectFromXML 时都会被重新分配;这是一个热点路径,建议将该列表移动到一个静态 readonly 字段中,以避免重复的数组分配。
给 AI Agent 的提示
Please address the comments from this code review:

## Overall Comments
- The `string.Contains(blockedXamlNamespace, StringComparison.OrdinalIgnoreCase)` overload is not available on older .NET Framework targets; consider using `IndexOf(blockedXamlNamespace, StringComparison.OrdinalIgnoreCase) >= 0` instead to avoid potential compilation issues.
- The blocked XAML namespace list is reallocated on every `GetObjectFromXML` call; consider moving it to a static readonly field to avoid repeated array allocations in this hot path.

Sourcery 对开源项目是免费的——如果你觉得我们的评审有帮助,欢迎分享 ✨
帮我变得更有用!请在每条评论上点 👍 或 👎,我会根据你的反馈来改进后续的评审。
Original comment in English

Hey - I've left some high level feedback:

  • The string.Contains(blockedXamlNamespace, StringComparison.OrdinalIgnoreCase) overload is not available on older .NET Framework targets; consider using IndexOf(blockedXamlNamespace, StringComparison.OrdinalIgnoreCase) >= 0 instead to avoid potential compilation issues.
  • The blocked XAML namespace list is reallocated on every GetObjectFromXML call; consider moving it to a static readonly field to avoid repeated array allocations in this hot path.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The `string.Contains(blockedXamlNamespace, StringComparison.OrdinalIgnoreCase)` overload is not available on older .NET Framework targets; consider using `IndexOf(blockedXamlNamespace, StringComparison.OrdinalIgnoreCase) >= 0` instead to avoid potential compilation issues.
- The blocked XAML namespace list is reallocated on every `GetObjectFromXML` call; consider moving it to a static readonly field to avoid repeated array allocations in this hot path.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@lhx077 lhx077 changed the title fix: deny WPF Behaviors namespaces in untrusted homepage XAML fix(WPF): deny WPF Behaviors namespaces in untrusted homepage XAML Jun 6, 2026
Replace("Property=\"EventData\"", "Property=\"local:CustomEventService.EventData\"");

// 自定义主页 XAML 被视为不受信任内容;禁止引用 WPF Behaviors 中可调用方法/改写属性的通用动作。
foreach (var blockedXamlNamespace in new[]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

i think u can make a static readonly array

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

Labels

size: S PR 大小评估:小型 🛠️ 等待审查 Pull Request 已完善,等待维护者或负责人进行代码审查

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants