Skip to content

24: Read the two request values the way core wrote them - #38

Open
nikolaystrikhar wants to merge 1 commit into
23-registry-bufferfrom
24-request-values
Open

24: Read the two request values the way core wrote them#38
nikolaystrikhar wants to merge 1 commit into
23-registry-bufferfrom
24-request-values

Conversation

@nikolaystrikhar

Copy link
Copy Markdown
Contributor

What: Conflict\Redirector strips line breaks from query values instead of running sanitize_text_field() over them, and Conflict\Rewriter verifies _error_nonce against the value core actually signed.

Usage:

// Resolving a conflict on this URL now re-renders this search,
// rather than one for "100".
/wp-admin/edit.php?s=100%25ab

Why this way:

The values were already decoded, and sanitizing them destroyed them. wp_parse_str() decodes before the sanitize ran, and _sanitize_text_fields() deletes every %[a-f0-9]{2} match and strips markup. Re-requesting the screen the user asked for is the entire point of the redirect. http_build_query( …, PHP_QUERY_RFC3986 ) is what prevents breakout; the sanitize call only added mangling. Line breaks are stripped on their own, which is the one property a Location header needs.

Core signs the raw basename. wp-admin/plugins.php mints plugin-activation-error_{$plugin} from wp_unslash( $_REQUEST['plugin'] ), so a basename sanitizing altered failed verification and left core's wording on the one screen this feature exists to reword. An explicit is_string() now does the refusing that sanitize_text_field() was doing by accident.

sanitize_text_field() ran over query values wp_parse_str() had already
url-decoded, and it deletes every %[a-f0-9]{2} match and strips markup. So a
conflict resolved on edit.php?s=100%25ab re-rendered the screen searching for
100. The point of the redirect is to re-request what the user asked for, and
http_build_query( …, PHP_QUERY_RFC3986 ) is what actually prevents breakout;
all the sanitize call added was the mangling. Line breaks are stripped on
their own now, which is the one property the Location header needs.

The rewriter verified its nonce against a sanitised basename, but core mints
that nonce from the raw wp_unslash( $_REQUEST['plugin'] ). Any basename
sanitizing alters -- a folder name with a percent sequence, a leading space --
failed verification, and the activation-error screen kept core's wording on
exactly the conflict this feature exists to explain. An explicit is_string()
does the refusing that sanitize_text_field() was incidentally doing.

Also anchors the screen-name regex with \z: PCRE $ matches before a trailing
newline too.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant