Skip to content

[UPMERGE] 5.1 -> 2026.x - #3182

Merged
dpfaffenbauer merged 18 commits into
2026.xfrom
upmerge/5.1_2026.x
Aug 24, 2026
Merged

[UPMERGE] 5.1 -> 2026.x#3182
dpfaffenbauer merged 18 commits into
2026.xfrom
upmerge/5.1_2026.x

Conversation

@dpfaffenbauer

@dpfaffenbauer dpfaffenbauer commented Aug 24, 2026

Copy link
Copy Markdown
Member

Upmerge of 5.1 into 2026.x — the final leg of this round.

Remember! The upmerge should always be merged with the Merge pull request button.

⏰ Time-sensitive

The scheduled Upmerge PR workflow (cron 0 2 * * *) does git reset --hard 5.1 on this branch nightly and force-pushes it, which has destroyed a resolution here before. Merge before the next run or this has to be rebuilt.

Refreshed after #3181 merged, so 2026.x now receives the whole chain: 4.15.05.12026.x.

What it carries forward

Security-relevant files, all arriving intact

file role
ResourceBundle/Controller/RedirectUrlValidationTrait.php new — the single validateRedirectUrl() implementation
CoreBundle/Security/ShopUserAuthenticationSuccessHandler.php new — validates the post-login redirect target
CoreBundle/Security/ShopUserAuthenticationFailureHandler.php new — reads the failure path from the request bags directly
CoreBundle/Resources/config/services/handler.yml wires both handlers
CoreBundle/Resources/config/pimcore/security.yml registers both on the shop firewall
FrontendBundle/Controller/{Cart,Customer,Frontend,Register,Security}Controller.php consume the trait instead of trusting _redirect
StorageListBundle/Controller/StorageListController.php same
features/ui/frontend/account/login.feature, Behat/Context/Ui/Frontend/LoginContext.php regression coverage

All three new classes verified present by path on the merged tree; exactly one validateRedirectUrl() definition exists, so nothing landed twice. Both handlers appear in handler.yml and in the firewall config.

Conflicts resolved (79 files)

78 Studio build artifacts5.1 rebuilt its Studio bundles into different content-hash directories than the ones committed on 2026.x. Per convention these are never rebuilt during an upmerge, so all 22 affected bundles had their entire Resources/public/studio/ tree restored verbatim from 2026.x.

1 modify/delete: MessengerBundle/Resources/public/pimcore/js/list.js — this is #3179's second half, the classic ExtJS store field. 2026.x deleted this file, along with all 463 classic ExtJS files, in 720355156f ("remove ExtJS / Classic Admin, bump Pimcore to 2026.1"). Resolved in favour of the 2026.x deletion, consistent with how the newsletter deletion is handled.

That does not lose the fix on 2026.x, which was verified rather than assumed: the Studio replacement MessengerFailedGrid.tsx already reads the corrected key (dataIndex: 'failed_at', key: 'failed_at'), and the backend on the merged tree emits 'failed_at' from both jsonSerialize() and the #[SerializedName('failed_at')] accessor. So the ExtJS half is simply not applicable here — 2026.x gets the backend fix and its own Studio grid consumes it. Zero classic ExtJS files are reintroduced by this merge.

Verification

root replace set equality (auto-merged silently, checked anyway):
  split packages: 66 | replace entries: 66 | missing [] | extra []
  sorted=True, identical to full regeneration=True
studio artifacts differing from 2026.x : 0
build directories per bundle           : 22 checked, 0 deviations
split-package composer invariant       : checked=66 bad=0
newsletter-bundle in any composer.json : 0     (#3166 deletion holds)
DocumentContext / phpstan / extension  : 0 files touched  (#3169 shape holds)
classic admin firewall in security.yml : 0 occurrences
classic ExtJS files on merged tree     : 0
frontend regex on merged tree          : ^/(?!admin|pimcore-studio)[^/]*   (#3164 intact)
root config/packages/security.yaml     : not touched

Net diff against 2026.x is 15 files — #2963's set, plus #3179's backend half and #3180's one-line removal, with #3179's ExtJS half correctly absent:

 features/ui/frontend/account/login.feature         |  7 ++
 .../Behat/Context/Ui/Frontend/LoginContext.php     |  8 ++
 .../Resources/config/pimcore/security.yml          |  2 +
 .../Resources/config/services/handler.yml          |  9 +++
 .../ShopUserAuthenticationFailureHandler.php       | 72 ++++++++++++++++++
 .../ShopUserAuthenticationSuccessHandler.php       | 41 ++++++++++
 .../FrontendBundle/Controller/CartController.php   | 14 +++-
 .../Controller/CustomerController.php              |  8 +-
 .../Controller/FrontendController.php              |  3 +
 .../Controller/RegisterController.php              |  7 +-
 .../Controller/SecurityController.php              | 21 +++++-
 .../Messenger/FailedMessageDetails.php             |  2 +-
 .../assets/pimcore-studio/src/types/index.ts       |  1 -
 .../Controller/RedirectUrlValidationTrait.php      | 87 ++++++++++++++++++++++
 .../Controller/StorageListController.php           | 10 ++-
 15 files changed, 283 insertions(+), 9 deletions(-)

php -l clean on every changed PHP file; composer validate reports only the pre-existing payum/payum warning.

Note on #2974

#2974 (parent product price / createUnmanagedCopy helper) was still open at rebuild time and createUnmanagedCopy is not present on 5.1, so the createDataCopy() conflict it is expected to cause on 2026.x does not arise in this round.

Ordering

#3183 (merged) → #3181 (merged) → this PR. This completes the round.

Copilot AI and others added 14 commits January 29, 2026 11:44
Co-authored-by: dpfaffenbauer <5981845+dpfaffenbauer@users.noreply.github.com>
…haracters

Co-authored-by: dpfaffenbauer <5981845+dpfaffenbauer@users.noreply.github.com>
…duplication

Co-authored-by: dpfaffenbauer <5981845+dpfaffenbauer@users.noreply.github.com>
The "@" rejection tested the whole URL, so a same-host redirect carrying an
"@" in its query or fragment was silently downgraded to the default. It now
looks at the parsed authority only, which also makes the preceding user check
meaningful instead of redundant. Backslashes and control characters are now
rejected for absolute URLs as well, not just for relative ones.

Beyond the "_redirect" parameter, the login form feeds "_target_path" and
"_failure_path" to Symfony, which accepts any value starting with "/" or
"http". Both are now run through the same allow-list, in the controller that
renders the form and in a success/failure handler pair, so a target that is
neither a relative path nor a same-host URL falls back to the configured
default. The success handler covers the Referer as well, which the firewall
uses via use_referer.
Psalm rejects calls into @internal Symfony code. The rejected failure path is
now read through the public Request API, and the redirect the parent handler
produced is validated as well, which also covers a failure path configured as
a nested parameter.
Symfony marks Request::get() as internal as well, which Psalm rejects, so the
parameter is looked up in the attribute, query and request bags instead.
FailedMessageDetails::jsonSerialize() emitted "failedAt" while every consumer -
the classic grid column and the Studio MessengerFailedGrid - reads "failed_at",
and the DTO itself already declares #[SerializedName(\"failed_at\")]. Because
JsonSerializableNormalizer outranks ObjectNormalizer in the framework
serializer, jsonSerialize() decides the payload keys and that attribute never
took effect, so the column was empty for every transport.

Emit "failed_at" instead, which makes the existing attribute true rather than
dead code, and align the classic store field with it. The Studio grid already
reads "failed_at" and needs no change.
The interface declared both failed_at and failedAt for the same value, so
TypeScript accepted either spelling and could not catch the API/UI mismatch
that left the "Failed At" column empty. The payload key is failed_at, so
failedAt describes a field that does not exist.
Messenger: fix empty "Failed At" column by emitting the key the UI reads
Messenger: drop the redundant failedAt field from MessengerFailedMessage
Fix open redirect vulnerabilities in redirect parameter handling
dpfaffenbauer and others added 4 commits August 24, 2026 15:27
# Conflicts:
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/pimcore/js/list.js
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/05e1d48d6efb763898322c92b4a6a8d6/exposeRemote.js
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/05e1d48d6efb763898322c92b4a6a8d6/main.html
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/05e1d48d6efb763898322c92b4a6a8d6/mf-manifest.json
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/05e1d48d6efb763898322c92b4a6a8d6/mf-stats.json
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/05e1d48d6efb763898322c92b4a6a8d6/static/js/879.6f347bc8.js
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/05e1d48d6efb763898322c92b4a6a8d6/static/js/879.6f347bc8.js.LICENSE.txt
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/05e1d48d6efb763898322c92b4a6a8d6/static/js/async/254.73bc4fd6.js.LICENSE.txt
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/05e1d48d6efb763898322c92b4a6a8d6/static/js/async/375.2ec37522.js.LICENSE.txt
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/05e1d48d6efb763898322c92b4a6a8d6/static/js/async/450.62056a1a.js.LICENSE.txt
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/05e1d48d6efb763898322c92b4a6a8d6/static/js/async/460.3e0d222e.js.LICENSE.txt
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/05e1d48d6efb763898322c92b4a6a8d6/static/js/async/51.1d46e9ff.js.LICENSE.txt
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/05e1d48d6efb763898322c92b4a6a8d6/static/js/async/695.d827e311.js.LICENSE.txt
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/05e1d48d6efb763898322c92b4a6a8d6/static/js/async/76.31136685.js.LICENSE.txt
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/05e1d48d6efb763898322c92b4a6a8d6/static/js/async/79.33c522eb.js.LICENSE.txt
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/05e1d48d6efb763898322c92b4a6a8d6/static/js/async/808.5e763f41.js.LICENSE.txt
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/05e1d48d6efb763898322c92b4a6a8d6/static/js/async/920.159aa87a.js.LICENSE.txt
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/05e1d48d6efb763898322c92b4a6a8d6/static/js/async/__federation_expose_default_export.bfd9734e.js
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/05e1d48d6efb763898322c92b4a6a8d6/static/js/async/__federation_expose_default_export.bfd9734e.js.LICENSE.txt
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/05e1d48d6efb763898322c92b4a6a8d6/static/js/main.58e0299a.js.LICENSE.txt
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/34e35ad89346ae6081cc5086a9a71359/exposeRemote.js
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/34e35ad89346ae6081cc5086a9a71359/main.html
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/34e35ad89346ae6081cc5086a9a71359/mf-manifest.json
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/34e35ad89346ae6081cc5086a9a71359/mf-stats.json
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/34e35ad89346ae6081cc5086a9a71359/static/js/879.121d9e2d.js
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/34e35ad89346ae6081cc5086a9a71359/static/js/879.121d9e2d.js.LICENSE.txt
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/34e35ad89346ae6081cc5086a9a71359/static/js/async/174.10c3b224.js
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/34e35ad89346ae6081cc5086a9a71359/static/js/async/254.d61a4fa9.js
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/34e35ad89346ae6081cc5086a9a71359/static/js/async/254.d61a4fa9.js.LICENSE.txt
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/34e35ad89346ae6081cc5086a9a71359/static/js/async/375.70416f83.js
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/34e35ad89346ae6081cc5086a9a71359/static/js/async/375.70416f83.js.LICENSE.txt
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/34e35ad89346ae6081cc5086a9a71359/static/js/async/448.d1b4a9d3.js
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/34e35ad89346ae6081cc5086a9a71359/static/js/async/450.b3b8ad5d.js
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/34e35ad89346ae6081cc5086a9a71359/static/js/async/450.b3b8ad5d.js.LICENSE.txt
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/34e35ad89346ae6081cc5086a9a71359/static/js/async/460.600a3125.js
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/34e35ad89346ae6081cc5086a9a71359/static/js/async/460.600a3125.js.LICENSE.txt
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/34e35ad89346ae6081cc5086a9a71359/static/js/async/51.ad135ad2.js
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/34e35ad89346ae6081cc5086a9a71359/static/js/async/51.ad135ad2.js.LICENSE.txt
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/34e35ad89346ae6081cc5086a9a71359/static/js/async/536.c628657c.js
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/34e35ad89346ae6081cc5086a9a71359/static/js/async/564.e3aedd6c.js
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/34e35ad89346ae6081cc5086a9a71359/static/js/async/63.9e39d82e.js
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/34e35ad89346ae6081cc5086a9a71359/static/js/async/695.f3951c47.js
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/34e35ad89346ae6081cc5086a9a71359/static/js/async/695.f3951c47.js.LICENSE.txt
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/34e35ad89346ae6081cc5086a9a71359/static/js/async/696.17527f5d.js
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/34e35ad89346ae6081cc5086a9a71359/static/js/async/76.9b0a4664.js
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/34e35ad89346ae6081cc5086a9a71359/static/js/async/76.9b0a4664.js.LICENSE.txt
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/34e35ad89346ae6081cc5086a9a71359/static/js/async/79.405d9073.js
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/34e35ad89346ae6081cc5086a9a71359/static/js/async/79.405d9073.js.LICENSE.txt
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/34e35ad89346ae6081cc5086a9a71359/static/js/async/808.7cd63ca4.js
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/34e35ad89346ae6081cc5086a9a71359/static/js/async/808.7cd63ca4.js.LICENSE.txt
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/34e35ad89346ae6081cc5086a9a71359/static/js/async/821.3098003a.js
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/34e35ad89346ae6081cc5086a9a71359/static/js/async/920.6e5f4ec4.js
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/34e35ad89346ae6081cc5086a9a71359/static/js/async/920.6e5f4ec4.js.LICENSE.txt
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/34e35ad89346ae6081cc5086a9a71359/static/js/async/__federation_expose_default_export.2b4419d5.js
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/34e35ad89346ae6081cc5086a9a71359/static/js/async/__federation_expose_default_export.2b4419d5.js.LICENSE.txt
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/34e35ad89346ae6081cc5086a9a71359/static/js/main.9a8dbcae.js
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/34e35ad89346ae6081cc5086a9a71359/static/js/main.9a8dbcae.js.LICENSE.txt
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/34e35ad89346ae6081cc5086a9a71359/static/js/remoteEntry.js
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/a41c3d86be4a44ee48ce975351fa8971/exposeRemote.js
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/a41c3d86be4a44ee48ce975351fa8971/main.html
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/a41c3d86be4a44ee48ce975351fa8971/mf-manifest.json
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/a41c3d86be4a44ee48ce975351fa8971/mf-stats.json
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/a41c3d86be4a44ee48ce975351fa8971/static/js/879.121d9e2d.js
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/a41c3d86be4a44ee48ce975351fa8971/static/js/879.121d9e2d.js.LICENSE.txt
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/a41c3d86be4a44ee48ce975351fa8971/static/js/async/254.d61a4fa9.js.LICENSE.txt
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/a41c3d86be4a44ee48ce975351fa8971/static/js/async/375.70416f83.js.LICENSE.txt
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/a41c3d86be4a44ee48ce975351fa8971/static/js/async/450.b3b8ad5d.js
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/a41c3d86be4a44ee48ce975351fa8971/static/js/async/450.b3b8ad5d.js.LICENSE.txt
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/a41c3d86be4a44ee48ce975351fa8971/static/js/async/460.600a3125.js.LICENSE.txt
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/a41c3d86be4a44ee48ce975351fa8971/static/js/async/51.ad135ad2.js.LICENSE.txt
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/a41c3d86be4a44ee48ce975351fa8971/static/js/async/695.f3951c47.js.LICENSE.txt
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/a41c3d86be4a44ee48ce975351fa8971/static/js/async/76.9b0a4664.js.LICENSE.txt
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/a41c3d86be4a44ee48ce975351fa8971/static/js/async/79.405d9073.js.LICENSE.txt
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/a41c3d86be4a44ee48ce975351fa8971/static/js/async/808.7cd63ca4.js.LICENSE.txt
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/a41c3d86be4a44ee48ce975351fa8971/static/js/async/920.6e5f4ec4.js.LICENSE.txt
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/a41c3d86be4a44ee48ce975351fa8971/static/js/async/__federation_expose_default_export.2b4419d5.js
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/a41c3d86be4a44ee48ce975351fa8971/static/js/async/__federation_expose_default_export.2b4419d5.js.LICENSE.txt
#	src/CoreShop/Bundle/MessengerBundle/Resources/public/studio/a41c3d86be4a44ee48ce975351fa8971/static/js/main.8c4ebfd9.js.LICENSE.txt
#	src/CoreShop/Bundle/OrderBundle/Resources/public/studio/9a08a271fbb6e36e34abafcf75e5c1bb/static/js/async/450.bef1381e.js
@sonarqubecloud

Copy link
Copy Markdown

@dpfaffenbauer
dpfaffenbauer merged commit c8ac8a3 into 2026.x Aug 24, 2026
132 checks passed
@dpfaffenbauer
dpfaffenbauer deleted the upmerge/5.1_2026.x branch August 24, 2026 14:13
@github-actions github-actions Bot locked and limited conversation to collaborators Aug 24, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants