WW-5713 Fail closed for legacy Tiles OGNL evaluation - #1890
Conversation
|
Thanks for filing the ticket and the PR, and sorry for the slow turnaround. The evaluator part is right, including the two things that are easy to get wrong and that ruled out
So the hardening itself I'm happy with. What I can't take as it stands is the bootstrap change. The
Also None of this is you going off-piste. Getting the constant to What I'd like instead is to decouple the two: keep the container bootstrap exactly where it is today Two loose ends:
Credit is yours in the release notes either way. |
|
Thanks for the detailed review. Your shared-classloader concerns make sense, especially the possibility of one application’s Dispatcher lifecycle or legacy setting affecting another application. I agree that the current DispatcherListener wiring should be removed. Before rewriting it, I propose this approach:
This should preserve the original bootstrap behavior, remove the static cross-application lifecycle dependency, and ensure raw OGNL construction remains reachable only through an explicit application-local opt-in. Would this direction address your concerns before I revise the patch? I’m also happy to prepare the support/struts-6-x-x backport as a separate PR after we settle and merge the main-line design, using plain @deprecated as noted. |
|
Sorry for the delay — yes, that direction addresses all of it. Please go ahead. Resolving the Dispatcher from the current request's Two small things while you're in there:
A separate PR for |
|
Implemented the approved redesign in The normal Tiles bootstrap no longer uses A missing Dispatcher, false or missing flag, or non-servlet request now fails closed with the migration The public boolean constructors remain available for custom initializers. Tiles validation passes with 561/561 tests, including per-webapp isolation, cached resolution, non-servlet handling, construction gating, concurrency, and unchanged The new GitHub Actions runs are awaiting repository approval. |
Summary
The Tiles plugin registers separate
S2:and legacyOGNL:attribute-expression evaluators. The legacy evaluator operates directly against the TilesRequestand does not use the Struts OGNL controls used byS2:.This change keeps
OGNL:registered but makes it fail closed by default. Evaluation throws TilesEvaluationExceptionwith migration guidance and does not parse or evaluate the expression.Applications that temporarily require the existing raw behavior can explicitly set:
Normal Tiles startup no longer uses
DispatcherListener. The no-argument factory registers a lazy configuredOGNL:evaluator. On its first evaluation, the evaluator obtains theDispatcherfrom the current request'sServletContext, readsstruts.tiles.ognl.legacy.enabled, and caches the resulting delegate for that evaluator instance.A false or missing flag, missing
Dispatcher, or non-servletRequestfails closed withEvaluationException. Only an explicittrueconstructs the raw evaluator and installs the globalOgnlRuntimeTilesRequestproperty accessor. Legacy mode preserves the existing behavior and emits one migration warning when first used. Public boolean constructors support custom initializers that need to select disabled or legacy behavior explicitly.The compatibility constant and legacy evaluator are deprecated in Struts 7.4.0 and targeted for removal in Struts 8.0.0.
S2:,I18N:, andEL:remain unchanged.Testing
verifylifecycle (561 tests, all passing), including Apache RAT and JAR packagingS2:evaluationDispatcherListenerintegration and raw evaluator construction remains unreachable until explicittrueis establishedgitbox.apache.orgdownload timeoutsClassification
This is defense-in-depth hardening. No attacker-controlled expression source or concrete vulnerability impact has been demonstrated, and no security advisory is proposed.
Issue: WW-5713