Skip to content

FormPostRedirectStrategy should not emit percent-encoded values into hidden form inputs #19136

Description

@jzheaux

Summary

FormPostRedirectStrategy.sendRedirect(req, res, url) writes each query parameter into a hidden form input:

for (Entry<String, List<String>> entry : uriComponentsBuilder.build().getQueryParams().entrySet()) {
    String name = entry.getKey();
    for (String value : entry.getValue()) {
        ... HtmlUtils.htmlEscape(value) ...
    }
}

UriComponents.getQueryParams() returns values in the percent-encoded form they had in the source URL. On form POST, the browser encodes these again on submit, and so every percent-escape in the original URL becomes doubled and the value is corrupted.

Reproducer

String url = UriComponentsBuilder.fromUriString("https://example.com/cb")
    .queryParam("payload", UriUtils.encode("a+b/c=", StandardCharsets.UTF_8))
    .build(true).toUriString();
// url == https://example.com/cb?payload=a%2Bb%2Fc%3D

redirectStrategy.sendRedirect(req, res, url);

// Actual:   <input name="payload" type="hidden" value="a%2Bb%2Fc%3D" />
// Expected: <input name="payload" type="hidden" value="a+b/c=" />

When the browser submits this form, the receiving server gets payload=a%252Bb%252Fc%253D, decodes once, and reads a%2Bb%2Fc%3D — not the original a+b/c=.

Suggested Fix

Decode each value before HTML-escaping:

for (Entry<String, List<String>> entry : uriComponentsBuilder.build().getQueryParams().entrySet()) {
    String name = UriUtils.decode(entry.getKey(), StandardCharsets.UTF_8);
    for (String raw : entry.getValue()) {
        if (raw == null) {
            continue;
        }
        String value = UriUtils.decode(raw, StandardCharsets.UTF_8);
        ...
    }
}

Activity

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

Metadata

Metadata

Assignees

Labels

in: webAn issue in web modules (web, webmvc)type: bugA general bug

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions