Skip to content

[msbuild] Don't let binding sidecar manifest metadata redirect native reference output paths#25790

Merged
dalexsoto merged 3 commits into
mainfrom
dev/alex/fixsidecar
Jun 24, 2026
Merged

[msbuild] Don't let binding sidecar manifest metadata redirect native reference output paths#25790
dalexsoto merged 3 commits into
mainfrom
dev/alex/fixsidecar

Conversation

@dalexsoto

@dalexsoto dalexsoto commented Jun 23, 2026

Copy link
Copy Markdown
Member

A binding .resources sidecar manifest is passive data that may come from a
restored package, but ResolveNativeReferences copied every manifest element into
item metadata. Build-controlled path/identity metadata such as RelativePath,
ReidentifiedPath or DynamicLibraryId could then flow into the native-library
output path and make InstallNameTool create directories and write files outside
the intended intermediate output directory.

This PR:

  • Filters the metadata copied from a manifest using a block-list of the
    build-controlled path/layout/identity sinks (RelativePath, ReidentifiedPath,
    ComputedRelativePath, DynamicLibraryId, PublishFolderType, TargetDirectory,
    SourceDirectory), warning when one is dropped. Everything else — including
    binding-defined metadata like NoDSymUtil/NoSymbolStrip — is legitimate
    native-reference content and is copied as-is.
  • Skips native references with no name, rejects names containing rooted/..
    traversal segments, and ignores reserved MSBuild metadata names (e.g. FullPath)
    instead of crashing the task.
  • Adds a PathUtils.IsPathContained containment check so a reidentified native
    library can never be written outside the intended output directory, and deletes
    the temporary file if install_name_tool fails.

… reference output paths.

 A binding `.resources` sidecar manifest is passive data that may come from  a
 restored package, but `ResolveNativeReferences`  copied
 every manifest element into item metadata. Path/identity metadata such as
 `RelativePath`, `ReidentifiedPath` or `DynamicLibraryId` could then flow  into the
 reidentified native-library path and make `InstallNameTool` create  directories and
 write files outside the intended intermediate output directory.

 Only copy an allow-list of metadata from the manifest (warning on the  rest), reject
 native reference names containing rooted/`..` traversal segments, and add a
 containment check in `InstallNameTool` so a reidentified library can never  be
 written outside the intended output directory.

 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dalexsoto dalexsoto requested a review from mauroa as a code owner June 23, 2026 20:40
Copilot AI review requested due to automatic review settings June 23, 2026 20:40
@dalexsoto dalexsoto requested a review from rolfbjarne as a code owner June 23, 2026 20:40

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

Hardens the MSBuild native-reference pipeline against untrusted binding sidecar manifests by preventing manifest metadata from influencing output paths and by enforcing output-path containment during dylib reidentification.

Changes:

  • Restricts sidecar-manifest metadata copying in ResolveNativeReferences to an allow-list (warning on ignored keys) and rejects rooted/.. traversal in NativeReference Name.
  • Adds a containment check in InstallNameTool to prevent writing reidentified dylibs outside the intended intermediate directory, and wires the root directory from targets.
  • Adds regression tests covering ignored manifest metadata, traversal rejection, containment logic, and attempted path escapes.

Reviewed changes

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

Show a summary per file
File Description
tests/msbuild/Xamarin.MacDev.Tasks.Tests/TaskTests/ResolveNativeReferencesSidecarTest.cs Adds regression tests ensuring unsafe manifest metadata is ignored and traversal in Name is rejected.
tests/msbuild/Xamarin.MacDev.Tasks.Tests/TaskTests/InstallNameToolTaskTest.cs Adds regression tests for containment checks and refusal to write outside the intended directory (including symlink escape).
msbuild/Xamarin.MacDev.Tasks/Tasks/ResolveNativeReferences.cs Implements allow-listed manifest metadata copying + traversal/rooted validation for sidecar Name.
msbuild/Xamarin.MacDev.Tasks/Tasks/InstallNameTool.cs Adds required IntermediateNativeLibraryDir, containment enforcement, and path canonicalization helpers.
msbuild/Xamarin.MacDev.Tasks/Tasks/CreateBindingResourcePackage.cs Exposes the producer’s manifest attribute list for reuse by the consumer allow-list.
msbuild/Xamarin.Localization.MSBuild/MSBStrings.resx Adds localized warning/error strings for ignored metadata, invalid names, and out-of-root reidentification.
dotnet/targets/Xamarin.Shared.Sdk.targets Passes the intermediate native library root into InstallNameTool.

Comment on lines 348 to +357
foreach (XmlNode referenceNode in document.GetElementsByTagName ("NativeReference")) {
ITaskItem t = new TaskItem (r);
var name = referenceNode.Attributes? ["Name"]?.Value.Trim ('\\', '/') ?? string.Empty;
// The 'Name' is combined with the binding resource package's directory to locate (and
// potentially extract) the native reference, so make sure it can't be used to escape the
// binding resource package using an absolute path or '..' traversal segments.
if (IsUnsafeRelativePath (name)) {
Log.LogError (MSBStrings.E7180 /* The native reference '{0}' in the binding resource package '{1}' is invalid: the name must be a relative path without '..' segments. */, name, r.ItemSpec);
continue;
}
Comment on lines 68 to 72
processes [i] = ExecuteAsync ("xcrun", arguments).ContinueWith ((v) => {
if (v.IsFaulted)
throw v.Exception;
if (v.Status == TaskStatus.RanToCompletion) {
if (v.Status == TaskStatus.RanToCompletion && v.Result.ExitCode == 0) {
File.Delete (target);
Comment on lines +92 to +102
public static bool IsPathContained (string root, string target)
{
if (string.IsNullOrEmpty (root) || string.IsNullOrEmpty (target))
return false;

var canonicalRoot = CanonicalizeForContainment (root);
var canonicalTarget = CanonicalizeForContainment (target);

var rootWithSeparator = canonicalRoot.TrimEnd (Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar;
return canonicalTarget.StartsWith (rootWithSeparator, StringComparison.Ordinal);
}
@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

Comment thread msbuild/Xamarin.MacDev.Tasks/Tasks/InstallNameTool.cs Outdated
@rolfbjarne

Copy link
Copy Markdown
Member

The failing tests look related to these changes.

…view fixes.

 Real bindings carry legitimate native-reference metadata beyond a fixed set
 (e.g. NoDSymUtil, NoSymbolStrip), so filter the manifest with a block-list  of the
 build-controlled path/identity sinks instead of an allow-list - otherwise  that
 metadata is dropped (fixes the BundleStructureTest CI regression).

 Also from review: ignore reserved MSBuild metadata names instead of  crashing the
 task, skip nameless native references, delete the temporary file when
 install_name_tool fails, reject target == root in the containment check,  and move
 IsPathContained into PathUtils.

 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dalexsoto dalexsoto requested a review from rolfbjarne June 24, 2026 14:13
@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

✅ [PR Build #5367b26] Build passed (Detect API changes) ✅

Pipeline on Agent
Hash: 5367b2671ee93106069f3967cda87a5e46c58e68 [PR build]

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

✅ [PR Build #5367b26] Build passed (Build packages) ✅

Pipeline on Agent
Hash: 5367b2671ee93106069f3967cda87a5e46c58e68 [PR build]

@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

✅ API diff for current PR / commit

NET (empty diffs)

✅ API diff vs stable

NET (empty diffs)

ℹ️ Generator diff

Generator Diff: vsdrops (html) vsdrops (raw diff) gist (raw diff) - Please review changes)

Pipeline on Agent
Hash: 5367b2671ee93106069f3967cda87a5e46c58e68 [PR build]

@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

✅ [PR Build #5367b26] Build passed (Build macOS tests) ✅

Pipeline on Agent
Hash: 5367b2671ee93106069f3967cda87a5e46c58e68 [PR build]

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

🚀 [CI Build #5367b26] Test results 🚀

Test results

✅ All tests passed on VSTS: test results.

🎉 All 207 tests passed 🎉

Tests counts

✅ assembly-processing: All 1 tests passed. Html Report (VSDrops) Download
✅ cecil: All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (iOS): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (MacCatalyst): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (macOS): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (Multiple platforms): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (tvOS): All 1 tests passed. Html Report (VSDrops) Download
✅ framework: All 2 tests passed. Html Report (VSDrops) Download
✅ fsharp: All 4 tests passed. Html Report (VSDrops) Download
✅ generator: All 5 tests passed. Html Report (VSDrops) Download
✅ interdependent-binding-projects: All 4 tests passed. Html Report (VSDrops) Download
✅ introspection: All 4 tests passed. Html Report (VSDrops) Download
✅ linker (iOS): All 15 tests passed. Html Report (VSDrops) Download
✅ linker (MacCatalyst): All 15 tests passed. Html Report (VSDrops) Download
✅ linker (macOS): All 21 tests passed. Html Report (VSDrops) Download
✅ linker (tvOS): All 15 tests passed. Html Report (VSDrops) Download
✅ monotouch (iOS): All 20 tests passed. Html Report (VSDrops) Download
✅ monotouch (MacCatalyst): All 19 tests passed. Html Report (VSDrops) Download
✅ monotouch (macOS): All 20 tests passed. Html Report (VSDrops) Download
✅ monotouch (tvOS): All 20 tests passed. Html Report (VSDrops) Download
✅ msbuild: All 2 tests passed. Html Report (VSDrops) Download
✅ sharpie: All 1 tests passed. Html Report (VSDrops) Download
✅ windows: All 3 tests passed. Html Report (VSDrops) Download
✅ xcframework: All 4 tests passed. Html Report (VSDrops) Download
✅ xtro: All 1 tests passed. Html Report (VSDrops) Download

macOS tests

✅ Tests on macOS Monterey (12): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Ventura (13): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Sonoma (14): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Sequoia (15): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Tahoe (26): All 5 tests passed. [attempt 2] Html Report (VSDrops) Download

Linux Build Verification

Linux build succeeded

Pipeline on Agent
Hash: 5367b2671ee93106069f3967cda87a5e46c58e68 [PR build]

@dalexsoto dalexsoto merged commit 6723d38 into main Jun 24, 2026
56 checks passed
@dalexsoto dalexsoto deleted the dev/alex/fixsidecar branch June 24, 2026 16:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants