From 585fccfa917363d6860b8251c8319c658cae1f34 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 31 Aug 2026 00:05:51 +0000 Subject: [PATCH] Fix credential lookup to ignore www. prefix mismatch for nuget.org Closes #3843 The documented `paket config add-token 'https://www.nuget.org' ` example stores the token under the www.nuget.org source, but `paket push` (with no --url) looks up credentials using the default URL https://nuget.org (no www). ConfigFile.getSourceNodes only did an exact string match (after trimming trailing slashes), so the stored token was never found, causing push to fall through to a missing/invalid API key error. This normalizes the www. prefix for source comparisons only (does not change the actual URL used for requests), so tokens/credentials stored for https://www.nuget.org are found when looking up https://nuget.org and vice versa. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/Paket.Core/Versioning/ConfigFile.fs | 17 +++++++++++++++-- .../Paket.Tests/Versioning/ConfigFileSpecs.fs | 18 +++++++++++++++++- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/Paket.Core/Versioning/ConfigFile.fs b/src/Paket.Core/Versioning/ConfigFile.fs index 26b8647b00..33b272d2a9 100644 --- a/src/Paket.Core/Versioning/ConfigFile.fs +++ b/src/Paket.Core/Versioning/ConfigFile.fs @@ -121,11 +121,24 @@ let checkCredentials(url, cred) = true with _ -> false -let getSourceNodes (credentialsNode : XmlNode) (source : string) nodeType = +/// Normalizes a source URL for credential-lookup comparisons only (does not change what URL is +/// actually used for requests). Strips a trailing slash and a "www." host prefix so that e.g. +/// credentials stored for "https://www.nuget.org" are found when looking up "https://nuget.org" +/// and vice versa (see https://github.com/fsprojects/Paket/issues/3843). +let private normalizeSourceForComparison (source : string) = let source = source.TrimEnd([|'/'|]) + let wwwPrefix = "://www." + let idx = source.IndexOf(wwwPrefix, StringComparison.OrdinalIgnoreCase) + if idx >= 0 then + source.Remove(idx + 3, 4) // remove "www." while keeping the leading "://" + else + source + +let getSourceNodes (credentialsNode : XmlNode) (source : string) nodeType = + let source = normalizeSourceForComparison source sprintf "//%s" nodeType |> credentialsNode.SelectNodes |> Seq.cast - |> Seq.filter (fun n -> n.Attributes.["source"].Value.TrimEnd([|'/'|]) = source) + |> Seq.filter (fun n -> normalizeSourceForComparison n.Attributes.["source"].Value = source) |> Seq.toList let private getCredentialsNode = lazy(getConfigNode "credentials" |> returnOrFail) diff --git a/tests/Paket.Tests/Versioning/ConfigFileSpecs.fs b/tests/Paket.Tests/Versioning/ConfigFileSpecs.fs index 147fc33de1..93449d0e52 100644 --- a/tests/Paket.Tests/Versioning/ConfigFileSpecs.fs +++ b/tests/Paket.Tests/Versioning/ConfigFileSpecs.fs @@ -104,4 +104,20 @@ let ``get token from node``() = node.SetAttribute("value", "demotoken") let (Token token) = getAuthFromNode node - token |> shouldEqual "demotoken" \ No newline at end of file + token |> shouldEqual "demotoken" + +[] +let ``get source nodes ignores www prefix mismatch for nuget.org``() = + let doc = sampleDoc() + let node = doc.CreateElement("credential") + node.SetAttribute("source", "https://www.nuget.org") + doc.DocumentElement.AppendChild(node) |> ignore + + // a token stored for https://www.nuget.org (as documented via `paket config add-token`) + // should be found when looking up the default push URL https://nuget.org (no www) + // and vice versa. See https://github.com/fsprojects/Paket/issues/3843 + let nodesWithoutWww = getSourceNodes doc "https://nuget.org" "credential" + let nodesWithWww = getSourceNodes doc "https://www.nuget.org" "credential" + + nodesWithoutWww.Length |> shouldEqual 1 + nodesWithWww.Length |> shouldEqual 1 \ No newline at end of file