-
Notifications
You must be signed in to change notification settings - Fork 393
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WICKET-6805] Add Cross-Origin Opener Policy and Cross-Origin Embedder Policy support #442
Conversation
* Initial coop implementation * Fixed typo +reformatting code * Update wicket-core/src/main/java/org/apache/wicket/coop/CoopConfiguration.java Co-authored-by: Sal <[email protected]> * Update wicket-core/src/main/java/org/apache/wicket/coop/CoopConfiguration.java Co-authored-by: Sal <[email protected]> * Updates based on comments on the PR * Initial COEP implementation that doesn't handle report-to and setting up a reporting endpoint * Added javadocs and reformatted code * Fixed typo in javadoc * Updated valid values for COOP, same-origin-allow-popups instead of same-site * Made builder methods public so they can be called from init() in a sample app, added default values for builder fields to avoid null pointer exceptions * making exempted paths a HashSet for faster lookup * Using Set instead of HashSet in the declaration of exemptedPaths + reformatting code * Reformatting code to match Wicket's style * Indentation fix for CoepMode enum * Added tests for each COOP value, inlined url argument for checkHeaders in tests, formatted log statement to include path variable for exempted paths Co-authored-by: Sal <[email protected]>
this.mode = mode; | ||
} | ||
|
||
public static class Builder |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know the Builder pattern is considered best-practice nowadays :)
But since we don't use it in Wicket, we could live without it here for this simple type of configuration, to be more inline with the rest of the code.
@@ -1111,4 +1115,14 @@ public ContentSecurityPolicySettings getCspSettings() | |||
} | |||
return cspSettings; | |||
} | |||
|
|||
public void enableCoop(CoopConfiguration coopConfig) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should add these helpers, WebApplication has enough methods already and adding a listener quite easy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about this idea:
- add the CoopConfiguration and CoepConfiguration as fields in SecuritySettings.
- add third mode
DISABLED
to the existing ones (ENFORCING
andREPORTING
) - in Application#initApplication() add some logic to auto-add the Coop/Coep listener(s) when they are enabled
This way the developer will have to configure the security settings and don't bother how they are applied.
Are you sure two separate listeners are the best solution? COEP is a single header only and to quote [https://web.dev/coop-coep/]: "Use a combination of COOP and COEP HTTP headers to opt a web page into a special cross-origin isolated state." |
Hi @svenmeier! Thanks for your review. :)
Here's our reasoning behind having 2 separate listeners:
You're right in pointing out that enabling COOP and COEP together is the best practice for cross-origin isolation. We thought we would give Wicket users more flexibility if they wanted to enable them separately for any reason. Having a single listener for both COOP and COEP would also achieve the same results, if we provide flexible ways to configure the listener. In that case, while we can provide a single configuration, it might be somewhat confusing to have If you think having a single listener is better from a usability perspective, we can change our implementation to merge COOP and COEP into a single listener and provide two separate config objects and handy constructors for the listener that can receive either |
I'm glad it is not just me finding those acronyms too cryptic. |
return exemptions.contains(path); | ||
} | ||
|
||
public void addCoopHeader(WebResponse resp) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason this method is here ?
The config classes (often called XyzSettings in Wicket) usually are POJOs with getters and setters. IMO such action
method should be in the listener class.
Hi @martin-g , @svenmeier !
We made the changes suggested by @martin-g in the comment above. Now the config objects live in
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the late review - vacation times!
@@ -0,0 +1,108 @@ | |||
/* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It'd have been better to put coep
package under org.apache.wicket.security
parent package but I see that the csp
package is already in the root (o.a.w
) so it would be inconsistent to do this now for coep
and coop
... :-/
@Override | ||
public void onRequestHandlerResolved(RequestCycle cycle, IRequestHandler handler) | ||
{ | ||
HttpServletRequest request = (HttpServletRequest)cycle.getRequest().getContainerRequest(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better check that the container request is HttpServletRequest before casting it.
Otherwise tests using MockWebRequest will have do manually disable these listeners.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We ran into this problem when running the tests in wicket-core and we disabled the listeners in the DummyApplication
for RequestCycleListenerTest
by overriding the init method here since it was only this test case that was causing the problem. We can also revert these changes and add a check for HttpServletRequest
WDYT?
…op and coep, removed CoopConfiguration and CoepConfiguration files
Thanks for the review @martin-g ! I've renamed the request cycle listeners :) Is there anything else we can do to get this merged? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMHO the additions to Application would be better located in WebApplication#internalInit().
CSP is enforced there too.
AFAICT the |
The listeners should always query the configuration anyway - what if the app changes the configuration later on? |
By our design right now, changes made to the configuration after the Are there use cases for changing the policies at runtime? |
It's a matter of consistency, please see how CSPRequestCycleListener does it. We have to take care of naming too: securityInit() is not where 'an application's security is initialized'. |
Hi @svenmeier! We have updated the name of the method now, thanks for the suggestion! We were just wondering if you could elaborate a bit on what the use case is for changing security configurations at runtime. Do you have any cases where a developer would like to change the set of scripts that are allowed to run or the set of endpoints intended to be used cross-origin at runtime? While I agree that consistency is important, I also think it makes sense to programmatically add listeners that depend on user config. IMHO, the current approach has two downsides:
Perhaps Wicket has some good reasons why CSP works the way it does currently! If that isn't the case, do you think this could be a good opportunity to improve performance/security? I think having a config-dependent We could keep consistency by moving the adding of the CSP listener to this proposed new These are principles we've used in other contributions (see Struts' implementation of COOP, CSP and Fetch Metadata) and would really like to know if Wicket has use cases where these principles don't apply, so we'd definitely appreciate some feedback! |
This is a good point! I don't remember it being discussed. And I think it was not considered.
|
Thanks Martin! If you all agree, we could rename the current |
Please move your code into a new WebApplication#validateInit() - don't forget to call super.validateInit(). We can decide later which configurations we want to be frozen after the application was initialized. |
Thanks @svenmeier, @martin-g , @salcho ! I've moved the lines that add the Coop/Coep listeners to |
I've made some minor improvements to the PR. |
Thank you all! We'll be submitting a PR updating Wicket documentation soon! We're super excited to have contributed these features :) |
Thank you, @eozmen410 & @salcho ! |
Hello Wicket devs!
This PR adds Cross-Origin Opener Policy and Cross-Origin Embedder Policy support for Wicket.
COOP is a security mitigation that lets developers isolate their resources against side-channel attacks and information leaks. COEP prevents a document from loading any non-same-origin resources which don't explicitly grant the document permission to be loaded. COOP and COEP are independent mechanisms and they can be enabled, tested and deployed separately. Using COEP and COOP together allows developers to safely use powerful features such as
SharedArrayBuffer
,performance.measureMemory()
, and the JS Self-Profiling API. Both COOP and COEP require adding headers to the response. COOP and COEP are now supported by all major browsers. See https://web.dev/why-coop-coep/ for reference.Here's a summary of all the changes:
We have added 2 new request cycle listeners, the
CoopRequestCycleListener
andCoepRequestCycleListener
to handle adding the headers for the respective security mitigations.The listeners can be configured using the
CoopConfiguration
andCoepConfiguration
classes that use the builder pattern for ease of use by Wicket users.Using
CoopConfiguration
Wicket users will be able to specify the policy they want for COOP (same-origin
,same-origin-allow-popups
orunsafe-none
) and add exempted paths to specify the endpoints for which COOP will not be enabled.Similarly using
CoepConfiguration
Wicket users will be able to add exempted paths for which COEP will be disabled and specify if they want COEP to be enforcing (header set asCross-Origin-Embedder-Policy
) or reporting (header set asCross-Origin-Embedder-Policy-Report-Only
)We have added 2 new methods to the
WebApplication
class to make it convenient for users toenableCoop
andenableCoep
.Here are sample uses of enabling these mechnisms, in the
init()
method of theWebApplication
: