Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

HttpClientProxy generator unescapes string query values before escaping them, so %XX in a value loses one level of encoding

Aperta Adatta ai principianti
#14,070 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
74/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
csharp

Direzione di ricerca

Inizia da HttpClientProxySourceGenerator.cs ed esamina il template encodeStringRouteParameters mostrato nell’issue. Verifica se esistono test del generatore che coprono i parametri della stringa di query e i valori contenenti escape percentuali, quindi esegui i test pertinenti. Il lavoro è completato quando i valori stringa della query contenenti %XX raggiungono il server senza modifiche e i test esistenti di generazione del proxy passano.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Summary

When a string parameter of an IAppController interface is bound from the query string, the generated HttpClient proxy unescapes the value before it escapes it:

// HttpClientProxySourceGenerator.cs, encodeStringRouteParameters
{p.Name} = Uri.EscapeDataString(Uri.UnescapeDataString({p.Name} ?? string.Empty));

So any %XX sequence that is part of the value itself is decoded once on the client, and the server receives a different string from the one the caller passed. A value can't carry a literal %26, %2F, %3D or %25.

This matters most for return urls, which routinely carry an encoded query of their own.

Repro (bit-bp 10.6.2, Bit.SourceGenerators 10.6.2)
[Route("api/v1/[controller]/[action]/"), ApiController]
public interface IDemoController : IAppController
{
    [HttpGet("{?returnUrl}")]
    Task<string> Echo(string? returnUrl = null, CancellationToken cancellationToken = default);
}

// Server
[HttpGet]
public Task<string> Echo(string? returnUrl = null, CancellationToken cancellationToken = default) => Task.FromResult(returnUrl ?? "");
var value = "/products?filter=a%26b&page=2"; // the inner page's own query: filter = "a&b"
var echoed = await demoController.Echo(value, cancellationToken);
  • Expected: echoed == "/products?filter=a%26b&page=2".
  • Sent: GET api/v1/Demo/Echo?returnUrl=%2Fproducts%3Ffilter%3Da%26b%26page%3D2. The %26 inside the value has become & before escaping, so it is now indistinguishable from the real &.
  • Received: "/products?filter=a&b&page=2". When the app later navigates there, filter is "a" and a stray b parameter appears.

A simpler case: "page?then=%2Fdashboard" arrives as "page?then=/dashboard". That one happens to work, but the value is no longer the one that was sent.

Where it shows up in the template

SignInPanel and SignUpPage pass returnUrl to IIdentityController.GetExternalSignInUri(provider, returnUrl, ...). A return url with an encoded & (or %25, %2F, ...) in its own query loses one level of encoding on that call. After the external sign-in round trip the user lands on a url whose query is split differently from the one she started on.

Workaround

Callers can escape the value once themselves before calling (Uri.EscapeDataString(value)). The generated code then unescapes it back to the original before escaping it again. But that only works because of this behaviour, and it would silently double-encode if the behaviour changed.

Suggestion

Escape the value as given:

{p.Name} = Uri.EscapeDataString({p.Name} ?? string.Empty);

This is what RFC 6570's {?var} expansion does: % becomes %25. If the UnescapeDataString is there so that callers who pre-encode don't get double encoding, it may be worth documenting that values must be passed raw, since a pre-encoded value and a raw value that contains %XX can't be told apart.

(Seen on 10.6.2. The line is unchanged on develop as of 2026-10-19, commit 26a808a.)

Lingua principale
C#
Stelle
1.4k
Fork
264
Merge medio
13h 15m
PR unite (30g)
344

Preparare l'ambiente

Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di bitfoundation/bitplatform

Tutte le issue di bitfoundation/bitplatform

Issue simili

Altre issue su C#

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.