WW-5604 Recognize CDI/Weld client proxies in SecurityMemberAccess#1796
Conversation
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…eck, fix javadoc Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR addresses WW-5604 by ensuring Struts’ OGNL allowlist checks work correctly when Struts actions/beans are CDI (Weld) normal-scoped and therefore represented as Weld client proxies. It introduces a CDI-specific ProxyService implementation that can detect and unwrap Weld proxies so SecurityMemberAccess evaluates allowlisting against the underlying target class rather than the proxy class.
Changes:
- Added
CdiProxyService(extendingStrutsProxyService) to recognize and unwrap Weld client proxies. - Registered the CDI plugin’s
ProxyServiceimplementation viastruts-plugin.xmlso it becomes active when the CDI plugin is used. - Added Weld-based tests to verify proxy detection, member classification, and allowlist behavior; added
weld-apias a provided dependency.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| plugins/cdi/src/main/java/org/apache/struts2/cdi/CdiProxyService.java | Adds Weld proxy detection/unwrapping on top of existing Spring/Hibernate proxy handling. |
| plugins/cdi/src/main/resources/struts-plugin.xml | Registers CdiProxyService and selects it via struts.proxyService=cdi. |
| plugins/cdi/pom.xml | Adds weld-api dependency (provided scope) to compile against Weld proxy marker API. |
| plugins/cdi/src/test/java/org/apache/struts2/cdi/CdiProxyServiceTest.java | Verifies proxy detection, proxy-member identification, and target-class resolution using Weld SE. |
| plugins/cdi/src/test/java/org/apache/struts2/ognl/CdiSecurityMemberAccessProxyTest.java | Verifies SecurityMemberAccess allowlist behavior with a real Weld proxy (WW-5604 scenario). |
| plugins/cdi/src/test/java/org/apache/struts2/cdi/ProxiedFooService.java | Adds a normal-scoped CDI bean used to produce a Weld client proxy in tests. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|



Fixes WW-5604
Problem
When CDI (Weld) serves a normal-scoped bean (e.g. an
@ApplicationScoped/@SessionScopedaction), Struts sees a Weld client proxy (MyAction$Proxy$_$$_WeldClientProxy) rather than the real bean.SecurityMemberAccesscallsProxyService#isProxy(target)to decide whether to resolve the real target class (ultimateTargetClass) before evaluating the OGNL member allowlist. The defaultStrutsProxyServicerecognizes only Spring AOP and Hibernate proxies, so a CDI/Weld proxy falls through and the allowlist check runs against the proxy class instead of the real class — breaking legitimate access to allowlisted members on CDI-managed beans.Change
Adds a CDI-plugin-provided
ProxyService,CdiProxyService, that extendsStrutsProxyServiceand adds recognition + unwrapping of Weld client proxies:isProxy,isProxyMember,ultimateTargetClassgain an additive Weld branch (Spring/Hibernate behavior inherited unchanged).org.jboss.weld.proxy.WeldClientProxy, guarded bytry { … } catch (LinkageError ignored)exactly like the existing Spring/Hibernate branches — so a runtime without Weld behaves precisely as before.WeldClientProxy.getMetadata().getContextualInstance().ProxyServiceviastruts.proxyService=cdiin the plugin'sstruts-plugin.xml, mirroring howCdiObjectFactoryoverridesstruts.objectFactory.org.jboss.weld:weld-apiadded atprovidedscope (compile-time only).No core classes (
StrutsProxyService,SecurityMemberAccess,ProxyUtil) are modified.Tests
CdiProxyServiceTest— boots a Weld SE container: a normal-scoped bean is recognized as a proxy,ultimateTargetClassreturns the real class, Weld proxy accessors are flagged as proxy members, plain objects are unaffected.CdiSecurityMemberAccessProxyTest— drivesSecurityMemberAccesswith a real Weld proxy, including the headline scenarioclassInclusion_weldProxy_allowProxyObjectAccess: with the allowlist enabled, the proxy is allowlisted by its real target class, not the proxy class; plus fail-closeddisallowProxyObjectAccess/disallowProxyMemberAccessgating.mvn test -DskipAssembly -pl plugins/cdi→ 11/11 passing.Scope
Weld only (CDI defines no portable proxy API; Weld is the reference implementation the plugin already targets). Other CDI implementations fall back to the inherited Spring/Hibernate behavior via the
LinkageErrorguard, with no regression.🤖 Generated with Claude Code