Skip to content

Hosted NuGet splices the Socket source (and mapping) into a commented-out <packageSources> / <packageSourceMapping> block, so every restore fails NU1100 while scan reports success and its in-run VEX attests not_affected #585

Description

[agent] Found by the scheduled NuGet / dotnet bug-hunt routine (ledger #320).

Summary

The hosted NuGet rewriter finds its splice anchors with regexes that don't skip XML comments. In insert_nuget_source, the <packageSources> open-tag regex matches the first occurrence, and so does the <packageSourceMapping> regex in nuget_mapping_open_end. If a nuget.config has a commented-out <packageSources> block before the real one (common in templates and docs), the Socket <add> lands inside the comment. The new exclusive <packageSourceMapping> is outside the comment, so it routes Newtonsoft.Json to a source that NuGet never reads. Every restore then fails NU1100.

The scan still exits 0 with success and redirected: 1. Its in-run --vex attests not_affected. A re-run reports redirected: 1 again and changes nothing. A later standalone vex sees the problem (patched_ref_invalid: "routes packages to socket-patch-…, which no <packageSources> entry defines") and refuses. remove pkg:nuget/newtonsoft.json@13.0.3 fails with manifest_not_found, so the user can't undo the change with the CLI.

The vendored writer handles both shapes (it blanks comments first). Only hosted is affected.

This is separate from #561, which covers how hosted reads source keys from comments. #561's "Out of scope" note asks for the splice-anchor case to be filed separately if it can match inside a comment. It can. Variant A below has no <add> inside the comment, so #561's key reading isn't involved.

Impact

Repro (Linux, SDK 8.0.131, main 6cd3754)

I used the wiremock patch API and NuGet feed stand-in from crates/socket-patch-cli/tests/e2e_nuget_dotnet_build.rs (Backend::start), with a real nuget.org fixture restore of Newtonsoft.Json 13.0.3.

cat > nuget.config <<'EOF'
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <!-- <packageSources></packageSources> -->
  <packageSources>
    <add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
  </packageSources>
</configuration>
EOF
# app.csproj: net8.0, RestorePackagesWithLockFile=true, PackageReference Newtonsoft.Json 13.0.3
dotnet restore
socket-patch scan --mode hosted --json --yes --api-url $URI --org test-org --api-token x \
  --patch-server-url $URI --vex vex.json --vex-product pkg:nuget/app@1.0.0
# -> rc 0, status success, redirected 1; vex.json: not_affected
rm -rf obj; NUGET_PACKAGES=$(mktemp -d) dotnet restore --locked-mode
# -> error NU1100: Unable to resolve 'Newtonsoft.Json (>= 13.0.3)' for 'net8.0'.
#    PackageSourceMapping is enabled, the following source(s) were not considered: nuget.org.

Resulting nuget.config (variant A):

<configuration>
  <!-- <packageSources>
    <add key="socket-patch-4e4e…" value="http://127.0.0.1:…/patch-registry/nuget/…/index.json" />
    <add key="nuget.org" value="https://api.nuget.org/v3/index.json" /></packageSources> -->
  <packageSources>
    <add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
  </packageSources>
  <packageSourceMapping>
    <packageSource key="socket-patch-4e4e…"><package pattern="Newtonsoft.Json" /></packageSource>
    <packageSource key="nuget.org"><package pattern="*" /></packageSource>
  </packageSourceMapping>
</configuration>

(The seeded nuget.org <add> also lands in the comment. #561's key reader sees no keys in the empty commented region, so it seeds one.)

Variant B input: the real <packageSources> with nuget.org, followed by

  <!--
  <packageSourceMapping>
    <packageSource key="nuget.org"><package pattern="*" /></packageSource>
  </packageSourceMapping>
  -->

Hosted output: the Socket <packageSource> is inserted inside the comment, and no live mapping is authored.

Expected vs actual

  • Expected: hosted mode wires the Socket source and an exclusive exact-id mapping that the next restore honours (README / docs/ecosystems.md NuGet row: "adds a Socket package source plus an exact-id packageSourceMapping, and re-pins contentHash"). If it can't, it refuses rather than reporting success. VEX attests only a patch that will actually be installed (CLI_CONTRACT.md: VEX statements are backed by a wired patch).
  • Actual: the source or mapping is written into a comment. Scan says success, the in-run VEX attests not_affected, and the restore fails NU1100 (variant A) or loses exclusivity (variant B).

Matrix

OS SDK mode variant A (commented <packageSources>) variant B (commented <packageSourceMapping>) control (no comment)
Linux 8.0.131 hosted fail (NU1100), 3× fail (mapping inside comment; restore patched by luck) pass
Linux 8.0.131 vendored pass pass pass
macOS / Windows, SDK 6/9/10 hosted untested (the defect is pure text splicing, OS- and SDK-independent; installing other SDKs is blocked in this sandbox)

v4.0.0 (npm) also reproduces variant A: the Socket <add> lands in the comment, the in-run VEX says not_affected, and the restore fails NU1100. This is not a regression.

Suspect code

  • crates/socket-patch-core/src/patch/redirect/mod.rs:4289 insert_nuget_source: the open_tag regex <packageSources(?:\s[^>]*)?> and the self_closing regex both use .find(config) on unmasked text.
  • crates/socket-patch-core/src/patch/redirect/mod.rs:4346 nuget_mapping_open_end: the same issue for <packageSourceMapping>.
  • nuget_after_last_clear (just below) already blanks <!-- … --> in place. The same masking, applied before these finds, would fix it. Alternatively, move to formats::nuget as Hosted NuGet mapping reads commented-out package sources #561 proposes.
  • In-run VEX trusts the rewrite, while standalone vex (vex/discover/nuget.rs, which uses comment-aware formats::nuget::parse_config) flags patched_ref_invalid.

No probe run: the defect is OS-independent string splicing.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent:triagedbugSomething isn't workingbughuntFound by a scheduled package-manager bug-hunt agentpm:nugetNuGet / dotnetpriority:p3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions