[
https://issues.apache.org/jira/browse/WW-5662?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Lukasz Lenart updated WW-5662:
------------------------------
Fix Version/s: 7.4.0
(was: 7.3.0)
> Core tests run with the OGNL allowlist disabled, hiding a class of regression
> from CI
> -------------------------------------------------------------------------------------
>
> Key: WW-5662
> URL: https://issues.apache.org/jira/browse/WW-5662
> Project: Struts 2
> Issue Type: Improvement
> Reporter: Lukasz Lenart
> Priority: Major
> Fix For: 7.4.0
>
>
> h3. Problem
> {{struts.allowlist.enable}} ships as {{true}}
> ({{core/src/main/resources/org/apache/struts2/default.properties:261}}), but
> every test that
> boots a {{Dispatcher}} through the shared helper gets it forced to {{false}}:
> {code:java}
> // StrutsTestCaseHelper.java:41-44
> public static Dispatcher initDispatcher(ServletContext ctx, Map<String,
> String> params) {
> Map<String, String> finalParams = params != null ? new HashMap<>(params)
> : new HashMap<>();
> finalParams.putIfAbsent(STRUTS_ALLOWLIST_ENABLE, "false");
> ...
> }
> {code}
> The result is that the core suite - 3104 tests - validates the framework
> under a configuration
> that no production deployment uses. Exactly two test classes in the whole
> repository opt back
> in: {{OgnlUtilTest}} and {{LazyParamsAllowlistTest}}.
> Any framework code path that writes to an object via OGNL is therefore
> untested against the
> allowlist. If the target class is not allowlisted, the write is blocked at
> runtime and no core
> test can observe it.
> h3. Concrete incident
> WW-5659 moved lazily resolved interceptor params off the shared interceptor
> singleton and into
> a per-invocation holder ({{UploadPolicy}}). The old write target - the
> interceptor - is
> allowlisted at configuration time via
> {{XmlDocConfigurationProvider.verifyInterceptor}}; the
> new holder was registered nowhere.
> Consequences under the shipped default:
> * {{SecurityMemberAccess}} blocked the setter
> * {{OgnlUtil}} threw {{ReflectionException}}
> * the fail-closed path marked the policy unusable
> * *every file upload was rejected*
> The full core suite passed - 3104 tests, zero failures - because the
> allowlist was off. The
> break was caught by {{it.org.apache.struts2.showcase.DynamicFileUploadTest}}
> (4 of 7 tests
> failing), after it had already failed every "Build and Test" job on the pull
> request. The
> showcase integration tests were the only thing standing between this and a
> release.
> h3. Why the default is off, and why that is not simply reversible
> Turning the flag on for the existing suite would require allowlisting every
> test fixture class
> reachable from an OGNL expression - {{TestBean}}, {{TestBean2}} and many
> others. That is
> presumably why it was disabled wholesale in the first place. A naive flip
> would produce a large
> volume of unrelated failures, so this needs a deliberate approach rather than
> a one-line change.
> h3. Options
> Worth weighing during design; not a settled decision.
> # *A dedicated allowlist-enabled slice.* Keep the default off, and add a test
> base class (or
> surefire execution) that boots with the allowlist enabled, used by any test
> covering a code
> path that writes to a framework-internal object via OGNL. Cheapest, and
> matches what
> {{LazyParamsAllowlistTest}} already does by hand.
> # *Flip the default in {{StrutsTestCaseHelper}} and fix the fallout.* Highest
> value - it makes
> the whole suite exercise the shipped configuration - and the largest
> effort. Could be staged
> package by package.
> # *Treat the showcase integration tests as the canary and extend them.*
> Weakest option: it
> catches breakage late, and only for features the showcase happens to
> demonstrate.
> Option 1 plus a documented convention ("if your change writes via OGNL to a
> framework class,
> add an allowlist-enabled test") would have caught the WW-5659 regression at
> the point it was
> introduced.
> h3. Non-goals
> * Not a change to the shipped {{struts.allowlist.enable}} default, which is
> already {{true}}
> and correct.
> * Not a rewrite of the allowlist mechanism itself.
> h3. References
> * {{StrutsTestCaseHelper.java:41-44}} - where the flag is forced off
> * {{core/src/main/resources/org/apache/struts2/default.properties:261}} - the
> shipped default
> *
> {{core/src/test/java/org/apache/struts2/interceptor/LazyParamsAllowlistTest.java}}
> - the
> pattern a slice could generalise
> * WW-5659 - the regression that motivated this issue
--
This message was sent by Atlassian Jira
(v8.20.10#820010)