Problem/Motivation
Passing a url with a whitespace at the end used to work with PathValidator, however this commit changes the situation.
As a consequence, sites are blowing up left and right. Browsers have no problems with such URLs, only Symfony does.
Steps to reproduce
- Install Drupal 11.x
- Create a link that is processed by PathValidator
- Create a skeleton custom module
- Add the following code e.g. inside a hook in the .module file (note the extra whitespace at the end of the url)
\Drupal::pathValidator()->getUrlIfValidWithoutAccessCheck('http://example.com/ ')- Observe the resulting WSOD error message stating that white space characters are invalid in a url.
Proposed resolution
Patch PathValidator to catch the trash Symfony throws.
Update symfony/http-foundation so that tests pass (the expected exception is thrown).
Remaining tasks
Backport to 11.0.x and 10.3.x - note that MR !10307 now updates symfony/http-foundation so that tests pass (the expected exception is thrown).
User interface changes
None
Introduced terminology
None
API changes
None
Data model changes
None
Release notes snippet
None
| Comment | File | Size | Author |
|---|---|---|---|
| #52 | 3489329-nr-bot.txt | 91 bytes | needs-review-queue-bot |
Issue fork drupal-3489329
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
alfthecat commentedComment #3
quietone commentedChanges are made on on 11.x (our main development branch) first, and are then back ported as needed according to our policies.
Comment #4
mfb@alfthecat the most obvious cause of this, looking at your view, would be if the product_id has a trailing space or control character. The view creates links with path: /product/{{ product_id }} and this path will be processed by Drupal\Core\Path\PathValidator, which calls
Request::create('/' . $path);which now throws that exception.Comment #5
mfbAdding a remaining tasks item to analyze PathValidator class. On the one hand, it can be safer to throw exceptions for security reasons, as Request::create() now does in its most recent versions. On the other hand, PathValidator is a validator which returns FALSE if the path is not valid - thus it may be expected to catch this new exception and return FALSE.
Comment #7
mfb@alfthecat can you check if MR !10307 resolves your issue? If not, then I guess a full stacktrace of the BadRequestHttpException would be helpful, I was really just guessing/assuming that this was the Request::create() call throwing the exception.
Comment #8
mfbI looked at how some invalid paths are handled with MR !10307 applied, and it appears they are handled correctly, because the invalid path is actually "repaired" by being URL-encoded. Some examples:
Comment #9
maxilein commentedAdding an issue that may be a related symptom.
Comment #10
alfthecat commentedHi @mfb, I'm very happy to report the patch fixes the issue on my end. Thank you very much for the rapid solution.
Comment #11
mfbOk great. I added a test which passes a new line character to PathValidator - I don't know specifically what caused the exception in your case, but I don't think it matters, we just want to ensure it catches a BadRequestException and returns FALSE.
Comment #12
pameeela commentedWe hit this on:
Quickly downgraded
symfony/http-foundationto get the deploy working (it had worked on dev and stage, so of course we only hit it on prod), but we got dev into a broken state so we could confirm the fix later, and this appears to fix it.Comment #14
casey commentedIn our monitoring tool we saw a lot of "Allowed memory size of ... bytes exhausted" errors. These errors were caused due to a infinite loop via DefaultExceptionHtmlSubscriber (and maybe in our case only because we are using menu_trail_by_path module).
The error still occurred after the MR, because the non-ASCII characters in the request path are urlencoded. I've updated the MR to handle both encoded and non-encoded non-ASCII characters.
The attached patch is a snapshot of the latest state for safe usage with composer patches.
Comment #15
casey commentedMaybe related
Comment #16
catch@casey #14 definitely sounds like #3486972: DefaultExceptionHtmlSubscriber should not clone the request for 400/BadRequestException, reviews over there would be great.
Bumping this issue to critical, also reviewed the MR and it looks good to me, so RTBC.
Comment #17
catchAnd tagging beta target because this is a new regression.
Comment #18
longwaveComment #19
mfb@casey re: the infinite loop + out of memory, I also needed to catch the new Request::create() exceptions in a different place, see https://git.drupalcode.org/project/drupal/-/merge_requests/10306
Comment #20
mfbComment #21
ghost of drupal pastAnother example of the problem https://www.smartsheet.com/customers/stegh as you can see here
Learn more online: <a href="https://www.stegh.on.ca/ ">the extra space causes no problems at all in a browser but runningPathValidatorover this blows up because Symfony is garbage^W broke semver in https://github.com/symfony/http-foundation/commit/32310ff3aa8126ede47168... as this is an API incompatible change which shouldn't have been committed to any released branches at all.Comment #22
ghost of drupal pastComment #23
ghost of drupal pastComment #24
ghost of drupal pastComment #25
ghost of drupal pastPlease commit to 10.x too.
Comment #29
larowlanCommitted to 11.x and backported to 10.5.x, 10.4.x and 11.1.x
Removing beta target tag
Setting as Patch to be ported for 11.0.x and 10.3.x
Comment #31
larowlanUpdated the MR for 11.0.x so we can make sure its green before we cherry-pick to production branches
Comment #32
ghost of drupal pastComment #33
pandaski commentedIs there anything I can help with for the 10.3 patch?
Comment #34
larowlan@pandaski review the current MR and mark the issue as RTBC if it looks ok, then we can rebase it for 10.3
Comment #35
larowlanTests fail on 11.0.x, so fixing those would help too @pandaski
Comment #36
pandaski commentedThe patch for 10.3 and 11.0 looks good and resolves the issue locally.
During local testing, I successfully applied the patch from this merge request to 10.3.x and 11.0.x.
https://git.drupalcode.org/project/drupal/-/merge_requests/10307.patch
The patch has resolved the issue in initial local tests.
The recent PHPUnit test error seems similar to issue #18. I’m running local tests to validate it.
Comment #37
pandaski commentedMy local PHPUnit tests ran successfully.
10.3.11-dev
11.0.10-dev
Comment #38
mfbI think what's happening is the test expectations needed to be adjusted because this branch is using an older version of symfony/http-foundation that doesn't actually throw. In other words, this MR wouldn't actually need to be backported to this branch until symfony/http-foundation is updated?
I changed the test expectations for it to pass old with the older version of symfony/http-foundation, but on the other hand, if this branch is still supported, then actually symfony/http-foundation should be updated instead and we should revert the last commit?
Comment #39
praveenpb commentedOne quick question, cant we sanitize the
$pathvariable to remove space instead of handling it with the BadRequestException?For example,
$path = trim($path);resolves the first issue I guess.Comment #40
mfb@praveenpb for a few reasons.. PathValidator is already catching numerous exceptions and returning FALSE, so it clearly makes sense to do so in a new case. There is some fairly complex logic in
Request::create()for deciding which strings are not valid URLs, which also includes the even more complex logic for strings thatparse_url()considers "seriously malformed URLs," so you wouldn't want to try to recreate this logic. It's best to leave it toRequest::create()(andparse_url()) to decide, and catch the exception that it can now throw.(It's actually a little bizarre that
Request::create()didn't previously throw an exception - I guess you could pass any arbitrary string to it and get a request object.)Comment #41
praveenpb commented@mfb Okay, makes sense. Reverting my changes.
Comment #42
praveenpb commented@mfb One more question, for existing paths which has an extra leading or trailing spaces already, this will return FALSE and consider as an invalid url. What would be the impact? Will it break some feature in existing sites?
Comment #43
mfbBy the way, I was trying to grok
parse_url()'s seemingly arbitrary logic for what returns FALSE, and noticed that the PHP docs say "This function may not give correct results for relative or invalid URLs, and the results may not even match common behavior of HTTP clients. If URLs from untrusted input need to be parsed, extra validation is required, e.g. by using filter_var() with the FILTER_VALIDATE_URL filter."So, it might not actually be a good idea for Request::create() to rely on parse_url() for parsing relative URLs, or for Drupal core to rely on Request::create() to parse relative URLs/paths, and some followup might be needed related to this? But so far that seems to be a concern only for weird edge cases (a path with a trailing space or a colon and numbers doesn't seem normal) and could take a while to sort out, so we presumably want this fix either way.
Comment #44
mfb@praveenpb paths can contain spaces (they get URL-encoded when the path string is rendered to a URL string). But I think trailing spaces would be unlikely because a path seems to be trimmed? If there are some paths that are throwing this exception then they would already be broken - this MR wouldn't make them any more broken.
Comment #45
mfbComment #46
thejimbirch commentedI ran into this issue on a menu provided by the domain_menus module. The patch from MR 10307 applied to 10.3 and fixes the issue for me.
Thanks for the work on this! I'd mark it RTBC, but there appears to still be some discussions about the coding.
Comment #47
mfbI'm thinking that it seems like a good idea to update symfony/http-foundation, rather than changing the tests to pass on the older version, because after all, symfony's changes here were security-related. If folks don't feel comfortable with that, we could revert the last two commits in the MR.
Comment #48
samia.wyatt commentedHi all! I am having a similar issue with Views module and symfony/http-foundation. After upgrading to Drupal 10.3.x
In my case, it is a taxonomy view with an image entity reference field
field_imageand a content entity reference fieldfield_park_associationThe
field_image fieldis set to rewrite results with with the following configuration:{{ field_park_association }}The error this configuration is throwing:
Symfony\Component\HttpKernel\Exception\BadRequestHttpException: Invalid URI: A URI must not start nor end with ASCII control characters or spaces. in Symfony\Component\HttpKernel\HttpKernel->handle() (line 83 of /code/vendor/symfony/http-kernel/HttpKernel.php).Currently, Drupal 10.3.10 site
PHP version 8.2
symfony/http-foundation v6.4.16
views 10.3.10
views_ui 10.3.10
Comment #49
mfbBy the way, this merge request added a try/catch BadRequestException for a
$router->match()call.However, I don't believe the Router::match() method should throw a BadRequestException - according to its upstream phpdoc, it should only throw various routing exceptions.
I have a merge request resolving this over at #3491543: symfony/http-foundation Follow up issue for isAdminPath validator (theoretically we could remove catch statements that shouldn't be needed, but I didn't get to that yet).
Comment #51
mfbOpened new merge request !10509 for the 10.3.x branch so folks can test/review it. This includes updating symfony/http-foundation, rather than modifying the test to pass on the older version. But if necessary, we could instead remove the update and modify the test.
Comment #52
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.
Comment #53
carlitus commentedI cannot apply any MR to 10.4.0:
Installing drupal/core (10.4.0): Extracting archive
Applying patches for drupal/core
https://git.drupalcode.org/project/drupal/-/merge_requests/10509.diff (https://www.drupal.org/project/drupal/issues/3489329: symfony/http-foundation commit 32310ff breaks PathValidator)
Could not apply patch! Skipping. The error was: Cannot apply patch https://git.drupalcode.org/project/drupal/-/merge_requests/10509.diff
Installing drupal/core (10.4.0): Extracting archive
- Applying patches for drupal/core
https://git.drupalcode.org/project/drupal/-/merge_requests/10307.diff (https://www.drupal.org/project/drupal/issues/3489329: symfony/http-foundation commit 32310ff breaks PathValidator)
Could not apply patch! Skipping. The error was: Cannot apply patch https://git.drupalcode.org/project/drupal/-/merge_requests/10307.diff
Comment #54
catchI think we should modify the test on 10.3.x (or at least not do it here), or backport the fix without test coverage.
Comment #58
carlitus commentedSorry for the mess I've made trying to integrate the changes into 10.4.x.
Partly because I see that these changes are already in the 10.4.x branch, so nothing needs to be done.
Comment #59
drw commentedHi everyone,
I tried to update the core from 10.3.10 to D10.4.1 but doesn't work, I tried with both MR (10307, 10509) too.
I received the same message on browser:
"Invalid URI: A URI must not start nor end with ASCII control characters or spaces."
and checking with drush ws:
"Symfony\Component\HttpKernel\Exception\BadRequestHttpException: Invalid URI: A URI must not start nor end with ASCII control characters or spaces. in Symfony\Component\HttpKernel\HttpKerne.."
similar to https://www.drupal.org/project/drupal/issues/3486195
Comment #60
oily commentedUpdated the issue summary. Added steps to reproduce and other edits.
Comment #61
oily commentedMinor change to the test comment in the MR.
Comment #67
quietone commentedThanks for the work on fixing this Critical bug.
About this time last year this was set to 11.0.x for backport to 11.0.x and 10.3.x. Since both of those versions are no longer supported this will not be backported to those versions. And the last report of this causing a problem was in Jan of this year so hopefully that has been resolved over the year. It is time to close this as fixed.
I updated credit.