diff --git a/.github/workflows/fuzzer.yaml b/.github/workflows/fuzzer.yaml
new file mode 100644
index 00000000..1a074f50
--- /dev/null
+++ b/.github/workflows/fuzzer.yaml
@@ -0,0 +1,152 @@
+name: Fuzzing Test
+
+on:
+ pull_request
+
+jobs:
+
+ extract_version:
+ runs-on: ubuntu-latest
+ name: Extract release version
+ outputs:
+ supported-features: ${{ steps.version.outputs.value }}
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: 'latest'
+ - name: Get package version
+ id: version
+ run: echo "value=$(node -p -e "require('./px_metadata.json').version")" >> "$GITHUB_OUTPUT"
+
+
+ Fuzzing:
+ name: "Fuzzing Test"
+ env:
+ MOCK_COLLECTOR_IMAGE_TAG: 1.3.6
+ FUZZER_TAG: 1.0.3
+ SAMPLE_SITE_IMAGE_TAG: 1.0.0
+ ENFORCER_TAG: ${{ needs.extract_version.outputs.version }}
+
+ strategy:
+ matrix:
+ mode: [ "url", "first_party", "headers", "cookies", "user_agent" ]
+
+ runs-on: ubuntu-latest
+ timeout-minutes: 60
+ needs:
+ - extract_version
+
+ steps:
+
+ - name: Checkout Repo
+ uses: actions/checkout@v4
+
+ - name: Set up Docker
+ uses: docker/setup-buildx-action@v3
+
+ - name: Build local cluster
+ run: ./ci_files/build_cluster.sh
+
+ - name: Build Enforcer Docker image
+ run: |
+ docker build . -t localhost:5001/java-enforcer-sample-site:$SAMPLE_SITE_IMAGE_TAG && \
+ docker push localhost:5001/java-enforcer-sample-site:$SAMPLE_SITE_IMAGE_TAG
+
+ - uses: azure/setup-helm@v3
+ with:
+ version: '3.14.2'
+
+ - name: Clone helm charts repo - mock-collector
+ uses: actions/checkout@v4
+ with:
+ repository: PerimeterX/connect-helm-charts
+ token: ${{ secrets.CONNECT_PULL_TOKEN }}
+ ref: mock-collector-0.1.1
+ path: ./deploy_charts/mock-collector
+
+ - name: Clone helm charts repo - fuzzer
+ uses: actions/checkout@v4
+ with:
+ repository: PerimeterX/connect-helm-charts
+ token: ${{ secrets.CONNECT_PULL_TOKEN }}
+ ref: fuzzer-0.2.0
+ path: ./deploy_charts/fuzzer
+
+ - name: Clone helm charts repo - sample-site
+ uses: actions/checkout@v4
+ with:
+ repository: PerimeterX/connect-helm-charts
+ token: ${{ secrets.CONNECT_PULL_TOKEN }}
+ ref: sample-site-0.5.0
+ path: ./deploy_charts/sample-site
+
+ - name: Set up Google Cloud SDK
+ id: 'auth'
+ uses: 'google-github-actions/auth@v2'
+ with:
+ credentials_json: '${{ secrets.GCR_SA_KEY }}'
+
+ - name: Configure Docker credentials
+ run: |
+ gcloud auth configure-docker gcr.io
+
+ - name: pull mock collector image
+ run: |
+ docker pull gcr.io/px-docker-repo/connecteam/mock-collector:$MOCK_COLLECTOR_IMAGE_TAG && \
+ docker tag gcr.io/px-docker-repo/connecteam/mock-collector:$MOCK_COLLECTOR_IMAGE_TAG localhost:5001/mock-collector:$MOCK_COLLECTOR_IMAGE_TAG && \
+ docker push localhost:5001/mock-collector:$MOCK_COLLECTOR_IMAGE_TAG
+
+ - name: deploy mock collector
+ run: |
+ helm install mock-collector ./deploy_charts/mock-collector/charts/mock-collector \
+ --set image.repository=localhost:5001/mock-collector \
+ --set image.tag=$MOCK_COLLECTOR_IMAGE_TAG \
+ --set imagePullPolicy=Always --wait
+
+ - name: set secrets in enforcer config
+ run: |
+ cat ./ci_files/enforcer-config.json |\
+ jq '.px_app_id="${{ secrets.PX_APP_ID }}"' |\
+ jq '.px_cookie_secret="${{ secrets.TEST_COOKIE_SECRET }}"' |\
+ jq '.px_auth_token="${{ secrets.PX_AUTH_TOKEN }}"' > /tmp/enforcer-config.json
+
+ - name: log enforcer config
+ run: cat /tmp/enforcer-config.json
+
+ - name: deploy java enforcer
+ run: |
+ helm install java-enforcer ./deploy_charts/sample-site/charts/sample-site \
+ -f ./ci_files/enforcer-values.yaml \
+ --set image.name=localhost:5001/java-enforcer-sample-site \
+ --set image.tag=$SAMPLE_SITE_IMAGE_TAG \
+ --set-file enforcerConfig.content=/tmp/enforcer-config.json \
+ --wait
+
+ - name: pull fuzzer image
+ run: |
+ docker pull gcr.io/px-docker-repo/connecteam/connect-enforcer-fuzzer:$FUZZER_TAG && \
+ docker tag gcr.io/px-docker-repo/connecteam/connect-enforcer-fuzzer:$FUZZER_TAG localhost:5001/connect-enforcer-fuzzer:$FUZZER_TAG && \
+ docker push localhost:5001/connect-enforcer-fuzzer:$FUZZER_TAG
+
+ - name: run fuzzer
+ run: |
+ helm install fuzzer ./deploy_charts/fuzzer/charts/fuzzer \
+ --set image.repository=localhost:5001/connect-enforcer-fuzzer \
+ --set image.tag=$FUZZER_TAG \
+ --set appId=$PX_APP_ID \
+ --set mode=$FUZZ_MODE \
+ --set siteURL=$SITE_URL \
+ --wait \
+ --timeout 60m0s \
+ --wait-for-jobs
+ env:
+ FUZZ_MODE: ${{ matrix.mode }}
+ PX_APP_ID: ${{ secrets.PX_APP_ID }}
+ SITE_URL: "http://java-enforcer-sample-site:3000"
+
+ - name: get tests results
+ if: ${{ always() }}
+ run: kubectl logs job/fuzzer-enforcer-fuzzer
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c5ace89a..8c719b8f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
# Change Log
+## [v6.13.0](https://github.com/PerimeterX/perimeterx-java-sdk/compare/6.13.0...HEAD) (2024-04-27)
+- Added vid Validation for _pxvid extraction
+- Added Enforcer Fuzzer as part of the CI process
+- Updated log4j artifact version
+- Removed `/examples` directory
+
## [v6.12.0](https://github.com/PerimeterX/perimeterx-java-sdk/compare/6.12.0...HEAD) (2024-02-25)
- Added Dockerfile for web application example.
- Bugfix - Sensitive headers are now case-insensitive.
diff --git a/README.md b/README.md
index 6e65477a..b71c5e81 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
# [PerimeterX](http://www.perimeterx.com) Java SDK
-> Latest stable version: [v6.12.0](https://search.maven.org/#artifactdetails%7Ccom.perimeterx%7Cperimeterx-sdk%7C6.12.0%7Cjar)
+> Latest stable version: [v6.13.0](https://search.maven.org/#artifactdetails%7Ccom.perimeterx%7Cperimeterx-sdk%7C6.13.0%7Cjar)
## Table of Contents
diff --git a/examples/pom.xml b/examples/pom.xml
deleted file mode 100644
index 0ba42d4e..00000000
--- a/examples/pom.xml
+++ /dev/null
@@ -1,87 +0,0 @@
-
-
-
- org.springframework.boot
- spring-boot-starter-parent
- 2.2.7.RELEASE
-
- 4.0.0
- jar
- examples
-
-
-
-
- org.springframework.boot
- spring-boot-starter-web
- 2.2.7.RELEASE
-
-
-
- com.perimeterx
- perimeterx-sdk
- 6.9.5
-
-
-
- commons-io
- commons-io
- 2.8.0
-
-
-
- com.fasterxml.jackson.core
- jackson-databind
- 2.11.4
-
-
-
- org.apache.tomcat.embed
- tomcat-embed-core
- 10.0.5
-
-
-
- junit
- junit
- 4.13.2
-
-
-
- org.codehaus.plexus
- plexus-utils
- 3.3.0
-
-
-
- org.springframework
- spring-web
- 5.3.6
-
-
-
- org.apache.httpcomponents
- httpclient
- 4.5.13
-
-
-
- org.yaml
- snakeyaml
- 1.28
-
-
-
-
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
-
-
-
diff --git a/examples/src/main/java/Application.java b/examples/src/main/java/Application.java
deleted file mode 100644
index 070cd160..00000000
--- a/examples/src/main/java/Application.java
+++ /dev/null
@@ -1,13 +0,0 @@
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.context.annotation.ComponentScan;
-
-@SpringBootApplication
-@ComponentScan(basePackages = {"controllers", "filters"})
-public class Application {
-
- public static void main(String[] args) {
- SpringApplication.run(Application.class, args);
- }
-
-}
diff --git a/examples/src/main/java/controllers/ExampleController.java b/examples/src/main/java/controllers/ExampleController.java
deleted file mode 100644
index 8fd2a4ea..00000000
--- a/examples/src/main/java/controllers/ExampleController.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package controllers;
-
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-@RestController
-public class ExampleController {
-
- @RequestMapping("/")
- public String example() {
- return "Hello world";
- }
-
-}
diff --git a/examples/src/main/java/filters/PXFilter.java b/examples/src/main/java/filters/PXFilter.java
deleted file mode 100644
index 205d4979..00000000
--- a/examples/src/main/java/filters/PXFilter.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package filters;
-
-import com.perimeterx.api.PXConfiguration;
-import com.perimeterx.api.PerimeterX;
-import com.perimeterx.models.configuration.ModuleMode;
-import com.perimeterx.models.exceptions.PXException;
-import px.CustomBlockHandler;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpServletResponseWrapper;
-import java.io.IOException;
-
-/**
- * Filter implementation based on PerimeterX SDK
- */
-public class PXFilter implements Filter {
-
- private PerimeterX enforcer;
-
- @Override
- public void init(FilterConfig filterConfig) throws ServletException {
- // Creating filter configuration
- PXConfiguration pxConf = new PXConfiguration.Builder()
- .appId("") // Your PerimeterX application ID
- .cookieKey("") // Should copy from RiskCookie section in https://console.perimeterx.com/botDefender/admin?page=policiesmgmt
- .captchaEnabled(false) // This will trigger captcha validation flow when blocking
- .moduleMode(ModuleMode.BLOCKING)
- .authToken("") // PX Server request auth token to be copied from Token section in https://console.perimeterx.com/botDefender/admin?page=applicationsmgmt
- .build();
- try {
- this.enforcer = new PerimeterX(pxConf);
- // This will set the blocking handler from the default one to the our custom block handler
- // note that when we enable captcha logic we must use a blocking handler that display the appropriate html page with captcha
- // for instance CaptchaBlockHandler that is included in the SDK
- this.enforcer.setBlockHandler(new CustomBlockHandler());
- } catch (Exception e) {
- // Could not init enforcer
- }
- }
-
- @Override
- public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
-
- // The request wrapper enables to read the request multiple times.
- request = new RequestWrapper((HttpServletRequest) request);
-
- // This will apply PerimeterX SDK logic on each request going through this filter
- HttpServletResponse httpRes = (HttpServletResponse) servletResponse;
-
- try {
- PXContext ctx = enforcer.pxVerify(httpReq, new HttpServletResponseWrapper(httpRes));
- if (ctx.isVerified()) {
- filterChain.doFilter(servletRequest, servletResponse);
- }
-
- // This enables to read the response, it should happen after the response was already sent to the client
- response = new ResponseWrapper((HttpServletResponse) response);
- pxFilter.pxPostVerify((ResponseWrapper) response, context);
- } catch (PXException e) {
- // ignoring error for now and passing the request
- filterChain.doFilter(servletRequest, servletResponse);
- }
- }
-
- @Override
- public void destroy() {
- }
-}
diff --git a/examples/src/main/java/px/CustomBlockHandler.java b/examples/src/main/java/px/CustomBlockHandler.java
deleted file mode 100644
index 687603af..00000000
--- a/examples/src/main/java/px/CustomBlockHandler.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package px;
-
-import com.perimeterx.api.blockhandler.BlockHandler;
-import com.perimeterx.models.PXContext;
-import com.perimeterx.models.exceptions.PXException;
-
-import javax.servlet.http.HttpServletResponseWrapper;
-import java.io.IOException;
-
-/**
- * This will implement the BlockHandler interface which can later be set in PerimeterX object initializtion
- */
-public class CustomBlockHandler implements BlockHandler {
-
- /**
- * Simple block handler which set status code to be 403 add one header with score and write to page "You are blocked"
- */
- @Override
- public void handleBlocking(PXContext context, HttpServletResponseWrapper responseWrapper) throws PXException {
- responseWrapper.setHeader("PX-Blocking-Score", String.valueOf(context.getScore()));
- try {
- responseWrapper.setStatus(403);
- responseWrapper.getWriter().print("You are blocked");
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-}
diff --git a/pom.xml b/pom.xml
index 583bdef2..2e174612 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,7 +7,7 @@
PerimeterX JAVA SDK
com.perimeterx
perimeterx-sdk
- 6.12.0
+ 6.13.0
jar
PerimeterX Java SDK
diff --git a/px_metadata.json b/px_metadata.json
index 1172ab20..78e2a0f7 100644
--- a/px_metadata.json
+++ b/px_metadata.json
@@ -1,5 +1,5 @@
{
- "version": "6.12.0",
+ "version": "6.13.0",
"supported_features": [
"advanced_blocking_response",
"bypass_monitor_header",
diff --git a/src/main/java/com/perimeterx/models/PXContext.java b/src/main/java/com/perimeterx/models/PXContext.java
index ece56cff..4073cb55 100644
--- a/src/main/java/com/perimeterx/models/PXContext.java
+++ b/src/main/java/com/perimeterx/models/PXContext.java
@@ -404,8 +404,12 @@ private void setVidAndPxhd(Cookie[] cookies) {
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals("_pxvid") || cookie.getName().equals("pxvid")) {
- this.vid = cookie.getValue();
- this.vidSource = VidSource.VID_COOKIE;
+ if (isValidVid(cookie.getValue())) {
+ this.vid = cookie.getValue();
+ this.vidSource = VidSource.VID_COOKIE;
+ } else {
+ logger.debug("setVidAndPxhd - invalid VID value was extracted");
+ }
}
if (cookie.getName().equals("_pxhd")) {
try {
@@ -548,4 +552,10 @@ public boolean isBreachedAccount() {
public boolean isContainCredentialsIntelligence() {
return this.getLoginData() != null && this.getLoginData().getLoginCredentials() != null;
}
+
+ private boolean isValidVid(String vidCookieValue) {
+ Pattern vidPattern = Pattern.compile("^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", Pattern.CASE_INSENSITIVE);
+ Matcher matcher = vidPattern.matcher(vidCookieValue);
+ return matcher.matches();
+ }
}
diff --git a/web/pom.xml b/web/pom.xml
index df937f8c..46665da7 100644
--- a/web/pom.xml
+++ b/web/pom.xml
@@ -38,10 +38,11 @@
slf4j-log4j12
1.7.25
+
- log4j
- log4j
- 1.2.17
+ org.apache.logging.log4j
+ log4j-core
+ 2.23.1
@@ -64,7 +65,7 @@
8
8
- 6.12.0
+ 6.13.0