[CXF-9227] Fix SecurityManager permission regressions introduced in 4…#3256
[CXF-9227] Fix SecurityManager permission regressions introduced in 4…#3256ffang wants to merge 1 commit into
Conversation
| // context is checked, preserving the confused-deputy guard. | ||
| return AccessController.doPrivileged(new PrivilegedAction<Boolean>() { | ||
| public Boolean run() { | ||
| sm.checkPermission(permission); |
There was a problem hiding this comment.
@ffang I do understand the motivation for this change but I believe it significantly changes the (intended?) security posture and behavior. Essentially, any caller will be granted the permission assuming cxf-core has it, why do we have to change it now? Thanks!
There was a problem hiding this comment.
@reta You're absolutely right — thank you for catching this. Moving sm.checkPermission() inside doPrivileged does weaken the caller-check semantics and is not a good fix.
The root cause of Issues 2 & 3 is that PR #3157's ACCESS_EXTERNAL_SCHEMA="" change routes schema resolution through SchemaLSResourceResolver → ExtendedURIResolver → URIResolver.tryFileSystem() — a code path that was never reached in this context before. When the JAXP schema validator (JDK code) drives that resolution under a SecurityManager, sm.checkPermission(RESOLVE_URI) walks all the way up through the JDK validator frames, which don't hold a CXF-internal permission, causing the failure.
The correct fix is to leave SecurityActions.fileExists() untouched — worth noting that SecurityActions is a package-private class so only CXF's own code in org.apache.cxf.resource can call into it directly(So any caller in your concern is restricted in CXF code, though we still should avoid it). Instead we wrap the resolver.resolve() call in SchemaLSResourceResolver.resolveResource() with AccessController.doPrivileged(). That establishes the boundary at CXF's own code: the sm.checkPermission(RESOLVE_URI) stack walk stops there, finds that CXF's JARs hold the permission, and passes — without granting any privilege to the JAXP/user frames above.
Will push a revised commit shortly.
….1.7
Summary
Fixes three SecurityManager permission regressions introduced in CXF 4.1.7
that break deployments running under a tight SecurityManager policy (reported
by the WildFly team during their 4.1.6 → 4.1.7 upgrade CI checks).
Root Cause
Issue 1 —
NetPermission("getProxySelector")(introduced by #3154)ProxyFactory.getSystemProxy()callsProxySelector.getDefault()withoutdoPrivileged, forcing all callers including user deployments to hold thispermission.
Issues 2 & 3 —
RuntimePermission("org.apache.cxf.permission")andSocketPermission(introduced by #3157)Setting
ACCESS_EXTERNAL_SCHEMA=""onSchemaFactoryroutes all schemaresolution through
SchemaLSResourceResolver→ExtendedURIResolver→URIResolver.tryFileSystem()— a code path never previously reached in thiscontext under a SecurityManager. This exposed two pre-existing gaps:
SecurityActions.fileExists()calledsm.checkPermission()outsidedoPrivileged, walking the full call stack into user deployment code.URIResolver.createInputStream()calledurl.openConnection()withoutdoPrivileged, requiring callers to holdSocketPermission.Fix
ProxyFactory.javaProxySelector.getDefault()indoPrivilegedSecurityActions.javasm.checkPermission()inside thedoPrivilegedblock so the stack walk stops at the CXF privilege boundary (confused-deputy guard preserved)URIResolver.javaurl.openConnection()indoPrivileged