Technical Advisory – play-pac4j Authentication rule bypass

Vendor: PAC4j
Vendor URL:
Versions affected: All versions through 3.0.0 (latest at time of writing)
Author: James Chambers <james.chambers[at]nccgroup[dot]trust>
Advisory URL / CVE Identifier: TBD
Risk: High (an attacker can bypass path-based authentication rules)


Regular expressions used for path-based authentication by the play-pac4j library are evaluated against the full URI provided in a user’s HTTP request. If a requested URI matches one of these expressions, the associated authentication rule will be applied. These rules are only intended to validate the path and query string section of a URL. If a request URI contains a scheme and authority section, the requested URI will not match these path-based rules, even if the resolved relative path used for routing does. This may allow an attacker to bypass certain path-based authentication rules.


SecurityFilter path-based authentication rules in the Play application configuration file (e.g. conf/application.conf).


An unauthenticated attacker may be able to access restricted paths in a Play web application, such as an administrator interface.


Consider the following authentication configuration: = [
  {"/admin(?.*)?" = {
    authorizers = "_authenticated_",
    clients = "SAML2Client"
  {".*" = {
    authorizers = "_anonymous_"

A typical HTTP request line has the following form:

GET /admin HTTP/1.1

The resulting request.uri checked by the play-pac4j library will be /admin, which will trigger the SAML2 authentication rule.

However, another valid way to specify URLs on the request line is:


In this case, the request.uri will be, while request.path will be /admin. The authentication rule for /admin(?.*)? will be bypassed, while the application still routes the user to /admin.

Another valid way to perform this bypass in the browser is by adding two extra slashes to the path, such as The request looks like:

GET ///admin HTTP/1.1

This URI is interpreted as having a relative scheme, empty authority, and path of /admin. The value of request.uri will be ///admin, while the value of request.path is /admin.


As a temporary mitigation, use a catch-all, high privilege authentication rule to catch all unrecognized paths. This will ensure that any rule bypass does not result in privilege escalation, as the highest level of privilege will be required for access.

Alternatively, replace all SecurityFilter path-based rules with per-action Secure annotations.

Vendor Communication

2017-07-28 - NCC Group sends initial email to vendor asking for security contact
2017-07-28 - Vendor responds and provides a security related email address
2017-08-01 - NCC Group asks for a PGP public key to send the advisory encrypted
2017-08-01 - Vendor provides a PGP public key
2017-08-16 - NCC Group sends a draft of the advisory to the vendor
2017-08-17 - Vendor acknowledges receipt of advisory
2017-08-18 - Vendor confirms vulnerability and asks whom to credit
2017-08-31 - NCC Group asks for bug discoverer to be credited
2017-09-01 - Vendor notes that disclosure to Google groups list was made already
   and that the name will be added to that disclosure
2017-09-01 - NCC Group thanks the vendor and informs them that public disclosure
   will move forward

Thanks to

Jérôme Leleu

Published date: 18 September 2017