Skip to content

WW-5604 Recognize CDI/Weld client proxies in SecurityMemberAccess#1796

Merged
lukaszlenart merged 6 commits into
mainfrom
WW-5604-cdi-proxy-detection
Jul 21, 2026
Merged

WW-5604 Recognize CDI/Weld client proxies in SecurityMemberAccess#1796
lukaszlenart merged 6 commits into
mainfrom
WW-5604-cdi-proxy-detection

Conversation

@lukaszlenart

Copy link
Copy Markdown
Member

Fixes WW-5604

Problem

When CDI (Weld) serves a normal-scoped bean (e.g. an @ApplicationScoped / @SessionScoped action), Struts sees a Weld client proxy (MyAction$Proxy$_$$_WeldClientProxy) rather than the real bean. SecurityMemberAccess calls ProxyService#isProxy(target) to decide whether to resolve the real target class (ultimateTargetClass) before evaluating the OGNL member allowlist. The default StrutsProxyService recognizes 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 extends StrutsProxyService and adds recognition + unwrapping of Weld client proxies:

  • isProxy, isProxyMember, ultimateTargetClass gain an additive Weld branch (Spring/Hibernate behavior inherited unchanged).
  • Detection uses the public Weld marker org.jboss.weld.proxy.WeldClientProxy, guarded by try { … } catch (LinkageError ignored) exactly like the existing Spring/Hibernate branches — so a runtime without Weld behaves precisely as before.
  • Unwrapping resolves the real class via WeldClientProxy.getMetadata().getContextualInstance().
  • Registered as the active ProxyService via struts.proxyService=cdi in the plugin's struts-plugin.xml, mirroring how CdiObjectFactory overrides struts.objectFactory.
  • org.jboss.weld:weld-api added at provided scope (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, ultimateTargetClass returns the real class, Weld proxy accessors are flagged as proxy members, plain objects are unaffected.
  • CdiSecurityMemberAccessProxyTest — drives SecurityMemberAccess with a real Weld proxy, including the headline scenario classInclusion_weldProxy_allowProxyObjectAccess: with the allowlist enabled, the proxy is allowlisted by its real target class, not the proxy class; plus fail-closed disallowProxyObjectAccess / disallowProxyMemberAccess gating.

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 LinkageError guard, with no regression.

🤖 Generated with Claude Code

lukaszlenart and others added 3 commits July 20, 2026 14:29
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>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 (extending StrutsProxyService) to recognize and unwrap Weld client proxies.
  • Registered the CDI plugin’s ProxyService implementation via struts-plugin.xml so it becomes active when the CDI plugin is used.
  • Added Weld-based tests to verify proxy detection, member classification, and allowlist behavior; added weld-api as 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.

Comment thread plugins/cdi/pom.xml
lukaszlenart and others added 3 commits July 20, 2026 14:41
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>
@sonarqubecloud

Copy link
Copy Markdown

@lukaszlenart
lukaszlenart merged commit f2c1f50 into main Jul 21, 2026
10 checks passed
@lukaszlenart
lukaszlenart deleted the WW-5604-cdi-proxy-detection branch July 21, 2026 08:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants