diff --git a/.github/workflows/cd.yaml b/.github/workflows/cd.yaml index 830f54a6..e99e0760 100644 --- a/.github/workflows/cd.yaml +++ b/.github/workflows/cd.yaml @@ -11,11 +11,11 @@ jobs: version: ${{ steps.version.outputs.value }} steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: - node-version: '18.x' + node-version: '22.x' - name: Get package version id: version run: echo "value=$(node -p -e "require('./px_metadata.json').version")" >> "$GITHUB_OUTPUT" @@ -28,7 +28,7 @@ jobs: contents: write steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 - run: gh release create v${{ needs.extract_version.outputs.version }} --generate-notes -t "Version ${{ needs.extract_version.outputs.version }}" env: GITHUB_TOKEN: ${{ github.TOKEN }} @@ -42,7 +42,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Set up JDK 8 uses: actions/setup-java@v3 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b29753ae..c541b8b0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,7 +5,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v5 - name: Set up JDK 8 uses: actions/setup-java@v3 with: diff --git a/.github/workflows/ci_e2e.yaml b/.github/workflows/ci_e2e.yaml index f3e6a9bf..3a8e52e6 100644 --- a/.github/workflows/ci_e2e.yaml +++ b/.github/workflows/ci_e2e.yaml @@ -12,11 +12,11 @@ jobs: supported-features: ${{ steps.supported-features.outputs.value }} steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: - node-version: '20.x' + node-version: '22.x' - name: extract supported features id: supported-features run: echo "value=$(node -p -e "require('./px_metadata.json').supported_features?.join(' or ') || ''")" >> "$GITHUB_OUTPUT" @@ -25,9 +25,9 @@ jobs: CI: name: "E2E tests" env: - MOCK_COLLECTOR_IMAGE_TAG: 1.3.5 + MOCK_COLLECTOR_IMAGE_TAG: 2.0.6 SAMPLE_SITE_IMAGE_TAG: 1.0.0 - ENFORCER_SPEC_TESTS_IMAGE_TAG: 1.8.1 + ENFORCER_SPEC_TESTS_IMAGE_TAG: 1.23.3 runs-on: ubuntu-latest timeout-minutes: 60 @@ -37,7 +37,7 @@ jobs: steps: - name: Checkout Repo - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Set up Docker uses: docker/setup-buildx-action@v3 @@ -50,34 +50,34 @@ jobs: 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 + - uses: azure/setup-helm@v4 with: - version: '3.14.1' + version: '3.19.0' - name: Clone helm charts repo - mock-collector - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: repository: PerimeterX/connect-helm-charts token: ${{ secrets.CONNECT_PULL_TOKEN }} - ref: mock-collector-0.1.1 + ref: mock-collector-0.1.2 path: ./deploy_charts/mock-collector - name: Clone helm charts repo - enforcer-tests - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: repository: PerimeterX/connect-helm-charts token: ${{ secrets.CONNECT_PULL_TOKEN }} - ref: enforcer-spec-tests-0.7.1 + ref: enforcer-spec-tests-0.9.1 path: ./deploy_charts/enforcer-spec-tests - name: Clone helm charts repo - sample-site - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: repository: PerimeterX/connect-helm-charts token: ${{ secrets.CONNECT_PULL_TOKEN }} - ref: sample-site-0.5.0 + ref: sample-site-0.6.1 path: ./deploy_charts/sample-site - name: Set up Google Cloud SDK @@ -101,6 +101,7 @@ jobs: 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 authToken=${{ secrets.PX_AUTH_TOKEN }} \ --set imagePullPolicy=Always --wait - name: set secrets in enforcer config @@ -108,7 +109,8 @@ jobs: 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 + jq '.px_auth_token="${{ secrets.PX_AUTH_TOKEN }}"' |\ + jq '.px_logger_auth_token="${{ secrets.PX_LOGGER_AUTH_TOKEN }}"' > /tmp/enforcer-config.json - name: log enforcer config run: cat /tmp/enforcer-config.json @@ -118,6 +120,9 @@ jobs: 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 appId=${{ secrets.PX_APP_ID }} \ + --set cookieSecret=${{ secrets.TEST_COOKIE_SECRET }} \ + --set authToken=${{ secrets.PX_AUTH_TOKEN }} \ --set image.tag=$SAMPLE_SITE_IMAGE_TAG \ --set-file enforcerConfig.content=/tmp/enforcer-config.json \ --wait @@ -137,6 +142,7 @@ jobs: --set authToken="${{ secrets.PX_AUTH_TOKEN }}" \ --set appId=${{ secrets.PX_APP_ID }} \ --set-file enforcerMetadataContent=./px_metadata.json \ + --set-file enforcerConfigJsonContent=/tmp/enforcer-config.json \ -f ./ci_files/spec-tests-values.yaml \ --wait \ --timeout 60m0s \ @@ -145,3 +151,7 @@ jobs: - name: get tests results if: ${{ always() }} run: kubectl logs job/enforcer-spec-tests + + - name: get enforcer logs + if: ${{ always() }} + run: kubectl logs deployment/java-enforcer-sample-site diff --git a/.github/workflows/ci_verify_version.yaml b/.github/workflows/ci_verify_version.yaml index 9fcd468a..64a18a71 100644 --- a/.github/workflows/ci_verify_version.yaml +++ b/.github/workflows/ci_verify_version.yaml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - ${{ github.base_ref }} - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: ref: ${{ github.base_ref }} @@ -18,7 +18,7 @@ jobs: run: echo "project=$( mvn help:evaluate -Dexpression=project.version -q -DforceStdout )" >> "$GITHUB_OUTPUT" - name: Checkout code - current commit - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Get current SDK versions id: new-version diff --git a/.github/workflows/docs_enforcement.yml b/.github/workflows/docs_enforcement.yml index 213c85c7..22fa0a2c 100644 --- a/.github/workflows/docs_enforcement.yml +++ b/.github/workflows/docs_enforcement.yml @@ -16,12 +16,12 @@ jobs: version: ${{ steps.version.outputs.value }} steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: - node-version: '22' + node-version: '22.x' - name: Get package version id: version diff --git a/.github/workflows/fuzzer.yaml b/.github/workflows/fuzzer.yaml index 4c939349..c703e737 100644 --- a/.github/workflows/fuzzer.yaml +++ b/.github/workflows/fuzzer.yaml @@ -12,11 +12,11 @@ jobs: supported-features: ${{ steps.version.outputs.value }} steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: - node-version: 'latest' + node-version: '22.x' - name: Get package version id: version run: echo "value=$(node -p -e "require('./px_metadata.json').version")" >> "$GITHUB_OUTPUT" @@ -25,8 +25,8 @@ jobs: Fuzzing: name: "Fuzzing Test" env: - MOCK_COLLECTOR_IMAGE_TAG: 1.3.6 - FUZZER_TAG: 1.0.4 + MOCK_COLLECTOR_IMAGE_TAG: 2.0.6 + FUZZER_TAG: 1.1.0 SAMPLE_SITE_IMAGE_TAG: 1.0.0 ENFORCER_TAG: ${{ needs.extract_version.outputs.version }} @@ -42,7 +42,7 @@ jobs: steps: - name: Checkout Repo - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Set up Docker uses: docker/setup-buildx-action@v3 @@ -55,32 +55,32 @@ jobs: 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 + - uses: azure/setup-helm@v4 with: - version: '3.14.2' + version: '3.19.0' - name: Clone helm charts repo - mock-collector - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: repository: PerimeterX/connect-helm-charts token: ${{ secrets.CONNECT_PULL_TOKEN }} - ref: mock-collector-0.1.1 + ref: mock-collector-0.1.2 path: ./deploy_charts/mock-collector - name: Clone helm charts repo - fuzzer - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: repository: PerimeterX/connect-helm-charts token: ${{ secrets.CONNECT_PULL_TOKEN }} - ref: fuzzer-0.2.0 + ref: fuzzer-0.3.1 path: ./deploy_charts/fuzzer - name: Clone helm charts repo - sample-site - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: repository: PerimeterX/connect-helm-charts token: ${{ secrets.CONNECT_PULL_TOKEN }} - ref: sample-site-0.5.0 + ref: sample-site-0.6.1 path: ./deploy_charts/sample-site - name: Set up Google Cloud SDK @@ -104,14 +104,17 @@ jobs: 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 + --set authToken=${{ secrets.PX_AUTH_TOKEN }} \ + --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 + jq '.px_auth_token="${{ secrets.PX_AUTH_TOKEN }}"' |\ + jq '.px_logger_auth_token="${{ secrets.PX_LOGGER_AUTH_TOKEN }}"' > /tmp/enforcer-config.json - name: log enforcer config run: cat /tmp/enforcer-config.json @@ -122,6 +125,9 @@ jobs: -f ./ci_files/enforcer-values.yaml \ --set image.name=localhost:5001/java-enforcer-sample-site \ --set image.tag=$SAMPLE_SITE_IMAGE_TAG \ + --set appId=${{ secrets.PX_APP_ID }} \ + --set cookieSecret=${{ secrets.TEST_COOKIE_SECRET }} \ + --set authToken=${{ secrets.PX_AUTH_TOKEN }} \ --set-file enforcerConfig.content=/tmp/enforcer-config.json \ --wait diff --git a/.gitignore b/.gitignore index d6827f60..de33b11b 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,5 @@ examples/examples.iml .DS_Store .classpath .project -.factorypath \ No newline at end of file +.factorypath +.smarttomcat \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 809ba2ce..db763821 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,16 @@ # Change Log +## [x.x.x] - YYYY-MM-DD +- Added `px_secured_pxhd_enabled` configuration option to enable secure flag on `pxhd` cookie +- Added `is_sensitive_route` to risk api and async activities +- Added `additional_token_info` to risk api and async activities +- Updated telemetry activity to new format (`static_config` and `active_config`; `remote_config` is not supported) +- Updated telemetry activity to include `request_id` +- Updated captcha page template to newest version +- Updated dependencies minor and patch versions (major versions unchanged) +- Changed custom parameters to be of type `Object` instead of `String` to allow more flexibility +- Changed first party block script in captcha template to end with expected `/captcha.js` +- Fixed possible connection leak issue due to unclosed responses in first party and telemetry requests +- Fixed first party fuzzing errors by returning 400 on first party requests with URL length > 1000 characters ## [v6.15.1](https://github.com/PerimeterX/perimeterx-java-sdk/compare/6.15.1...HEAD) (2025-09-08) - Added additional updateReason RISK to Telemetry flow diff --git a/ci_files/enforcer-config.json b/ci_files/enforcer-config.json index 6f3ed977..b085b4f1 100644 --- a/ci_files/enforcer-config.json +++ b/ci_files/enforcer-config.json @@ -19,9 +19,6 @@ "px_custom_first_party_xhr_endpoint": "/custom_first_party_xhr_endpoint", "px_custom_first_party_captcha_endpoint": "/custom_first_party_captcha_endpoint", "px_custom_first_party_prefix": "/custom_first_party_prefix", - "px_filter_by_route": [ - "/filtered_route" - ], "px_monitored_routes": [ "/monitored_route", "/monitored_route/suffix", @@ -116,5 +113,6 @@ ], "px_cors_support_enabled": true, "px_cors_preflight_request_filter_enabled": true, - "px_url_decode_reserved_characters": true + "px_url_decode_reserved_characters": true, + "px_secured_pxhd_enabled": true } \ No newline at end of file diff --git a/ci_files/spec-tests-values.yaml b/ci_files/spec-tests-values.yaml index 2b025ef9..ec158e28 100644 --- a/ci_files/spec-tests-values.yaml +++ b/ci_files/spec-tests-values.yaml @@ -1,3 +1,9 @@ +additionalArgs: + - "--retries" + - "3" + - "--retry-delay" + - "10" + internalMockCollectorURL: "http://mock-collector-mock-collector:3001" siteURL: "http://java-enforcer-sample-site:3000" diff --git a/pom.xml b/pom.xml index e32fe360..69125d25 100644 --- a/pom.xml +++ b/pom.xml @@ -132,19 +132,19 @@ com.fasterxml.jackson.core jackson-databind - 2.11.4 + 2.17.2 com.fasterxml.jackson.core jackson-annotations - 2.10.2 + 2.17.2 commons-io commons-io - 2.8.0 + 2.14.0 @@ -156,7 +156,7 @@ org.apache.commons commons-lang3 - 3.12.0 + 3.18.0 @@ -168,19 +168,19 @@ org.slf4j slf4j-api - 1.7.30 + 1.7.36 org.apache.httpcomponents httpasyncclient - 4.1.4 + 4.1.5 org.apache.httpcomponents httpclient - 4.5.13 + 4.5.14 @@ -207,14 +207,14 @@ org.springframework spring-test - 4.3.1.RELEASE + 4.3.30.RELEASE test org.springframework spring-web - 4.3.1.RELEASE + 4.3.30.RELEASE test @@ -228,7 +228,7 @@ com.google.code.gson gson - 2.8.6 + 2.10.1 compile diff --git a/px_metadata.json b/px_metadata.json index d4dacd1d..fc12507f 100644 --- a/px_metadata.json +++ b/px_metadata.json @@ -2,43 +2,44 @@ "version": "6.15.1", "supported_features": [ "advanced_blocking_response", - "bypass_monitor_header", + "batched_activities", "block_activity", "block_page_captcha", + "block_page_hard_block", "block_page_js_challenge", "block_page_rate_limit", + "bypass_monitor_header", "client_ip_extraction", "cookie_v3", "credentials_intelligence", "css_ref", + "custom_cookie_header", "custom_logo", "custom_parameters", "custom_proxy", "custom_sensitive_request", "enforced_routes", - "logger", + "enforcer_error", "filter_by_extension", "first_party", + "header_based_logger", "js_ref", + "logger", "mobile_support", "module_enable", "module_mode", "monitored_routes", "page_requested_activity", "pxde", - "vid_extraction", + "pxhd", "risk_api", - "custom_cookie_header", + "sensitive_headers", "sensitive_routes", "telemetry_command", - "enforcer_error", - "pxhd", - "batched_activities", - "sensitive_headers", - "block_page_hard_block", - "header_based_logger" + "vid_extraction" ], "excluded_tests": [ + "test_block_activity_ad_block", "test_pxde_extraction_(s2s|unverified|verified)", "test_risk_cookie_valid_cookie_with_user_agent_of_max_length", "test_path_parsing_in_(block|page_requested|risk_api|additional_s2s)\\[with_dots", @@ -48,6 +49,8 @@ "test_block_page_captcha_response_contains_http_reason_phrase", "test_cookie_v3_cookie_decryption_failed_iterations_above_max_allowed_value", "test_cookie_v3_cookie_validation_failed_big_cookie", - "test_client_ip_extraction_order_risk_api" + "test_client_ip_extraction_order_risk_api", + "test_telemetry_command_verify_custom_function_hash", + "test_first_party_timeout" ] } diff --git a/src/main/java/com/perimeterx/api/activities/BufferedActivityHandler.java b/src/main/java/com/perimeterx/api/activities/BufferedActivityHandler.java index fb6c006e..d704f37c 100644 --- a/src/main/java/com/perimeterx/api/activities/BufferedActivityHandler.java +++ b/src/main/java/com/perimeterx/api/activities/BufferedActivityHandler.java @@ -57,7 +57,7 @@ public void handlePageRequestedActivity(PXContext context) throws PXException { @Override public void handleEnforcerTelemetryActivity(PXConfiguration pxConfig, UpdateReason updateReason, PXContext context) { try { - EnforcerTelemetryActivityDetails details = new EnforcerTelemetryActivityDetails(pxConfig, updateReason); + EnforcerTelemetryActivityDetails details = new EnforcerTelemetryActivityDetails(pxConfig, context, updateReason); EnforcerTelemetry enforcerTelemetry = new EnforcerTelemetry("enforcer_telemetry", pxConfig.getAppId(), details); this.client.sendEnforcerTelemetry(enforcerTelemetry, context); } catch (IOException e) { diff --git a/src/main/java/com/perimeterx/api/activities/DefaultActivityHandler.java b/src/main/java/com/perimeterx/api/activities/DefaultActivityHandler.java index 045341d2..53bd4d0b 100644 --- a/src/main/java/com/perimeterx/api/activities/DefaultActivityHandler.java +++ b/src/main/java/com/perimeterx/api/activities/DefaultActivityHandler.java @@ -48,7 +48,7 @@ public void handlePageRequestedActivity(PXContext context) throws PXException { @Override public void handleEnforcerTelemetryActivity(PXConfiguration pxConfiguration, UpdateReason updateReason, PXContext context) { try { - EnforcerTelemetryActivityDetails details = new EnforcerTelemetryActivityDetails(pxConfiguration, updateReason); + EnforcerTelemetryActivityDetails details = new EnforcerTelemetryActivityDetails(pxConfiguration, context, updateReason); EnforcerTelemetry enforcerTelemetry = new EnforcerTelemetry("enforcer_telemetry", pxConfiguration.getAppId(), details); this.client.sendEnforcerTelemetry(enforcerTelemetry, context); } catch (Exception e) { diff --git a/src/main/java/com/perimeterx/api/blockhandler/templates/TemplateFactory.java b/src/main/java/com/perimeterx/api/blockhandler/templates/TemplateFactory.java index 998aa3cf..e626ee97 100644 --- a/src/main/java/com/perimeterx/api/blockhandler/templates/TemplateFactory.java +++ b/src/main/java/com/perimeterx/api/blockhandler/templates/TemplateFactory.java @@ -61,7 +61,7 @@ public static Map getProps(PXContext pxContext, PXConfiguration String hostUrl = pxContext.getCollectorURL(); if (pxConfig.isFirstPartyEnabled() && !pxContext.isMobileToken()) { String prefix = pxConfig.getAppId().substring(2); - blockScript = SLASH + prefix + Constants.FIRST_PARTY_CAPTCHA_PATH + QUESTION_MARK + captchaSrcParams; + blockScript = SLASH + prefix + Constants.FIRST_PARTY_CAPTCHA_PATH + CAPTCHA_FIRST_PARTY_FILE_PATH + QUESTION_MARK + captchaSrcParams; jsClientSrc = SLASH + prefix + Constants.FIRST_PARTY_VENDOR_PATH; hostUrl = SLASH + prefix + Constants.FIRST_PARTY_XHR_PATH; } diff --git a/src/main/java/com/perimeterx/api/proxy/DefaultReverseProxy.java b/src/main/java/com/perimeterx/api/proxy/DefaultReverseProxy.java index 3158ca86..04ee6728 100644 --- a/src/main/java/com/perimeterx/api/proxy/DefaultReverseProxy.java +++ b/src/main/java/com/perimeterx/api/proxy/DefaultReverseProxy.java @@ -106,8 +106,8 @@ public boolean reversePxXhr(HttpServletRequest req, HttpServletResponse res, PXC final String url = pxConfiguration.getCollectorUrl() + path; final String host = pxConfiguration.getCollectorUrl().replaceFirst("https?:\\/\\/", ""); - if (!isValidThirdPartyUrl(url, host, path)) { - context.logger.error("First party XHR URL is inaccurate: " + url + ", rendering default response"); + if (!isValidThirdPartyUrl(url, host, path, context)) { + context.logger.error("first party XHR URL is inaccurate: " + url + ", rendering default response"); predefinedResponseHelper.handlePredefinedResponse(res, predefinedResponse, context); return true; } @@ -134,13 +134,26 @@ private String getPath(HttpServletRequest req) { return isBlank(req.getRequestURI()) ? "" : req.getRequestURI().substring(xhrPrefix.length()); } - private boolean isValidThirdPartyUrl(String rawThirdPartyUrl, String expectedHost, String expectedUrl) { + private boolean isValidThirdPartyUrl(String rawThirdPartyUrl, String expectedHost, String expectedUrl, PXContext context) { try { URL url = new URL(rawThirdPartyUrl); String uri = url.getPath() + (url.getQuery() != null ? url.getQuery() : ""); - return url.getHost().equalsIgnoreCase(expectedHost) && uri.startsWith(expectedUrl); + if (!uri.startsWith(expectedUrl)) { + context.logger.debug("Validating third party URL failed, expected URL does not match the request URL. expectedUrl: " + expectedUrl + ", requestUrl: " + uri); + return false; + } + String host = url.getHost(); + final int port = url.getPort(); + if (port != -1 && port != url.getDefaultPort()) { + host += ":" + port; + } + if (!host.equalsIgnoreCase(expectedHost)) { + context.logger.debug("Validating third party URL failed, expected host does not match the request host. expectedHost: " + expectedHost + ", requestHost: " + host); + return false; + } + return true; } catch (Exception e) { - PerimeterX.globalLogger.error("Failed to parse rawUrl. ", e.getMessage()); + context.logger.error("Failed to parse rawUrl. ", e.getMessage()); } return false; diff --git a/src/main/java/com/perimeterx/api/proxy/RemoteServer.java b/src/main/java/com/perimeterx/api/proxy/RemoteServer.java index dafc32d2..44f810fb 100644 --- a/src/main/java/com/perimeterx/api/proxy/RemoteServer.java +++ b/src/main/java/com/perimeterx/api/proxy/RemoteServer.java @@ -109,9 +109,12 @@ public IPXOutgoingRequest prepareProxyRequest() throws IOException { return requestBuilder.build(); } - public IPXIncomingResponse handleResponse(IPXOutgoingRequest proxyRequest, PXContext context) { + public void handleResponse(IPXOutgoingRequest proxyRequest, PXContext context) { IPXIncomingResponse proxyResponse = null; try { + if (proxyRequest != null && proxyRequest.getUrl().length() > maxUrlLength) { + throw new IllegalArgumentException("URL too long: " + proxyRequest.getUrl().length()); + } // Execute the request proxyResponse = doExecute(proxyRequest); int statusCode = proxyResponse.status().getStatusCode(); @@ -119,7 +122,7 @@ public IPXIncomingResponse handleResponse(IPXOutgoingRequest proxyRequest, PXCon // In failure we can check if we enable predefined request or proxy the original response if (this.isAllowedPredefinedResponse() && statusCode >= HttpStatus.SC_BAD_REQUEST) { predefinedResponseHelper.handlePredefinedResponse(res, predefinedResponse, context); - return proxyResponse; + return; } res.setStatus(statusCode); @@ -139,12 +142,35 @@ public IPXIncomingResponse handleResponse(IPXOutgoingRequest proxyRequest, PXCon copyResponseEntity(proxyResponse); } + } catch (IllegalArgumentException e) { + context.logger.debug("Invalid request in first-party proxy: {}", e.getMessage()); + handleClientError(context); } catch (Exception e) { if (this.isAllowedPredefinedResponse()) { predefinedResponseHelper.handlePredefinedResponse(res, predefinedResponse, context); } + } finally { + if (proxyResponse != null) { + try { + proxyResponse.close(); + } catch (IOException e) { + context.logger.debug("Failed to close proxy response", e); + } + } + } + } + + private void handleClientError(PXContext context) { + try { + res.setStatus(HttpStatus.SC_BAD_REQUEST); + res.setContentType("text/plain"); + res.setCharacterEncoding("UTF-8"); + res.getWriter().print("Bad Request"); + res.getWriter().flush(); + } catch (IOException e) { + context.logger.error("Failed to write error response: {}", e.getMessage()); + res.setStatus(HttpStatus.SC_BAD_REQUEST); } - return proxyResponse; } /** diff --git a/src/main/java/com/perimeterx/api/verificationhandler/DefaultVerificationHandler.java b/src/main/java/com/perimeterx/api/verificationhandler/DefaultVerificationHandler.java index 716dcfee..cdb193f3 100644 --- a/src/main/java/com/perimeterx/api/verificationhandler/DefaultVerificationHandler.java +++ b/src/main/java/com/perimeterx/api/verificationhandler/DefaultVerificationHandler.java @@ -1,13 +1,11 @@ package com.perimeterx.api.verificationhandler; -import com.perimeterx.api.PerimeterX; import com.perimeterx.api.activities.ActivityHandler; import com.perimeterx.api.additionalContext.PXHDSource; import com.perimeterx.api.blockhandler.BlockHandler; import com.perimeterx.models.PXContext; import com.perimeterx.models.configuration.PXConfiguration; import com.perimeterx.models.exceptions.PXException; -import com.perimeterx.utils.logger.IPXLogger; import com.perimeterx.utils.logger.LogReason; import javax.servlet.http.HttpServletResponseWrapper; @@ -96,6 +94,10 @@ private String getPxhdCookie(PXContext context) throws UnsupportedEncodingExcept cookieValue += COOKIE_SEPARATOR + COOKIE_DOMAIN_KEY + context.getPxhdDomain(); } + if (pxConfiguration.isSecuredPxhdEnabled()) { + cookieValue += COOKIE_SEPARATOR + "Secure"; + } + return cookieValue; } diff --git a/src/main/java/com/perimeterx/http/PXHttpClient.java b/src/main/java/com/perimeterx/http/PXHttpClient.java index 93993591..6680fc11 100644 --- a/src/main/java/com/perimeterx/http/PXHttpClient.java +++ b/src/main/java/com/perimeterx/http/PXHttpClient.java @@ -217,14 +217,27 @@ public PXDynamicConfiguration getConfigurationFromServer() { @Override public void sendEnforcerTelemetry(EnforcerTelemetry enforcerTelemetry, PXContext context) throws IOException { - String requestBody = JsonUtils.writer.writeValueAsString(enforcerTelemetry); - if (context!=null){ - context.logger.debug("Sending enforcer telemetry: {}", requestBody); - } else{ - logger.debug("Sending enforcer telemetry: {}", requestBody); + IPXIncomingResponse httpResponse = null; + try { + String requestBody = JsonUtils.writer.writeValueAsString(enforcerTelemetry); + if (context != null) { + context.logger.debug("Sending enforcer telemetry: {}", requestBody); + } else { + logger.debug("Sending enforcer telemetry: {}", requestBody); + } + IPXOutgoingRequest request = buildOutgoingRequest(this.pxConfiguration.getServerURL() + Constants.API_ENFORCER_TELEMETRY, PXHttpMethod.POST, requestBody); + httpResponse = client.send(request); + } catch (Exception e) { + if (context != null) { + context.logger.debug("Sending enforcer telemetry failed. Error: {}", e.getMessage()); + } else { + logger.debug("Sending enforcer telemetry failed. Error: {}", e.getMessage()); + } + } finally { + if (httpResponse != null) { + httpResponse.close(); + } } - IPXOutgoingRequest request = buildOutgoingRequest(this.pxConfiguration.getServerURL() + Constants.API_ENFORCER_TELEMETRY,PXHttpMethod.POST, requestBody); - client.send(request); } private IPXOutgoingRequest buildOutgoingRequest(String url , PXHttpMethod method, String requestBody, BasicHeader... headers) { diff --git a/src/main/java/com/perimeterx/internals/cookie/AbstractPXCookie.java b/src/main/java/com/perimeterx/internals/cookie/AbstractPXCookie.java index d4c40bb8..0899761a 100644 --- a/src/main/java/com/perimeterx/internals/cookie/AbstractPXCookie.java +++ b/src/main/java/com/perimeterx/internals/cookie/AbstractPXCookie.java @@ -186,4 +186,9 @@ public String getUUID() { public String getVID() { return decodedCookie.get("v").asText(); } + + @Override + public String additionalTokenInfo() { + return this.decodedCookie.get("add") != null ? this.decodedCookie.get("add").asText() : null; + } } diff --git a/src/main/java/com/perimeterx/internals/cookie/PXCookie.java b/src/main/java/com/perimeterx/internals/cookie/PXCookie.java index 84d36b5f..3b977af9 100644 --- a/src/main/java/com/perimeterx/internals/cookie/PXCookie.java +++ b/src/main/java/com/perimeterx/internals/cookie/PXCookie.java @@ -23,4 +23,5 @@ public interface PXCookie { boolean isSecured() throws PXException; + String additionalTokenInfo(); } diff --git a/src/main/java/com/perimeterx/models/PXContext.java b/src/main/java/com/perimeterx/models/PXContext.java index 90b7c38c..56b7ddd4 100644 --- a/src/main/java/com/perimeterx/models/PXContext.java +++ b/src/main/java/com/perimeterx/models/PXContext.java @@ -232,6 +232,8 @@ public class PXContext { private String pxhdDomain; private String pxCtsCookie; private long enforcerStartTime; + private boolean isSensitiveRequest; + private String additionalTokenInfo; /** * The cookie key used to decrypt the cookie @@ -289,8 +291,9 @@ private void postInitContext(final HttpServletRequest request, PXConfiguration p this.enforcerErrorReasonInfo = new EnforcerErrorReasonInfo(); this.sensitiveHeaders = pxConfiguration.getSensitiveHeaders(); - String protocolDetails[] = request.getProtocol().split("/"); + String[] protocolDetails = request.getProtocol().split("/"); this.httpVersion = protocolDetails.length > 1 ? protocolDetails[1] : StringUtils.EMPTY; + this.isSensitiveRequest = determineIsSensitiveRequest(); CustomParametersProvider customParametersProvider = pxConfiguration.getCustomParametersProvider(); Function customParametersExtraction = pxConfiguration.getCustomParametersExtraction(); @@ -310,7 +313,12 @@ private IPXLogger getLogger(){ boolean isLoggerHeaderRequest = requestLoggerAuthToken!=null && this.getPxConfiguration().getLoggerAuthToken().equals(requestLoggerAuthToken); return pxConfiguration.getLoggerFactory().getRequestContextLogger(isLoggerHeaderRequest); } + public boolean isSensitiveRequest() { + return this.isSensitiveRequest; + } + + private boolean determineIsSensitiveRequest() { return this.isContainCredentialsIntelligence() || checkSensitiveRoute(pxConfiguration.getSensitiveRoutes(), servletPath) || checkSensitiveRouteRegex(pxConfiguration.getSensitiveRoutesRegex(), servletPath) @@ -453,6 +461,7 @@ public void setOriginalTokenCookie(String originalTokenCookie) { public void setRiskCookie(AbstractPXCookie riskCookie) { this.riskCookie = riskCookie.getDecodedCookie().toString(); + this.additionalTokenInfo = riskCookie.additionalTokenInfo(); } public void setBlockAction(String blockAction) { diff --git a/src/main/java/com/perimeterx/models/activities/CommonActivityDetails.java b/src/main/java/com/perimeterx/models/activities/CommonActivityDetails.java index c5baf184..f268f5de 100644 --- a/src/main/java/com/perimeterx/models/activities/CommonActivityDetails.java +++ b/src/main/java/com/perimeterx/models/activities/CommonActivityDetails.java @@ -50,6 +50,9 @@ public class CommonActivityDetails implements ActivityDetails { @JsonProperty("additional_risk_info") public String additionalRiskInfo; + @JsonProperty("additional_token_info") + public String additionalTokenInfo; + @JsonProperty("user") public String username; @@ -59,6 +62,9 @@ public class CommonActivityDetails implements ActivityDetails { @JsonProperty("cross_tab_session") public String pxCtsCookie; + @JsonProperty("is_sensitive_route") + public Boolean isSensitiveRoute; + public CommonActivityDetails(PXContext context) { final LoginData loginData = context.getLoginData(); @@ -85,6 +91,7 @@ public CommonActivityDetails(PXContext context) { this.riskStartTime = additional.riskStartTime; this.enforcerStartTime = additional.enforcerStartTime; this.pxCtsCookie = additional.pxCtsCookie; - + this.isSensitiveRoute = additional.isSensitiveRoute; + this.additionalTokenInfo = additional.additionalTokenInfo; } } diff --git a/src/main/java/com/perimeterx/models/activities/EnforcerTelemetryActivityDetails.java b/src/main/java/com/perimeterx/models/activities/EnforcerTelemetryActivityDetails.java index 3117a07e..fdda722e 100644 --- a/src/main/java/com/perimeterx/models/activities/EnforcerTelemetryActivityDetails.java +++ b/src/main/java/com/perimeterx/models/activities/EnforcerTelemetryActivityDetails.java @@ -1,13 +1,14 @@ package com.perimeterx.models.activities; import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.gson.Gson; import com.google.gson.JsonIOException; +import com.perimeterx.models.PXContext; import com.perimeterx.models.configuration.PXConfiguration; import com.perimeterx.utils.Constants; import java.net.InetAddress; import java.net.UnknownHostException; +import java.util.UUID; /** * Created by nitzangoldfeder on 29/10/2017. @@ -16,19 +17,27 @@ public class EnforcerTelemetryActivityDetails implements ActivityDetails { @JsonProperty("module_version") private String moduleVersion; + @JsonProperty("enforcer_configs") - private String enforcerConfigs; + private TelemetryConfiguration enforcerConfigs; + @JsonProperty("os_name") private String osName; + @JsonProperty("node_name") private String nodeName; + @JsonProperty("update_reason") private UpdateReason updateReason; - public EnforcerTelemetryActivityDetails(PXConfiguration pxConfiguration, UpdateReason updateReason) { + @JsonProperty("request_id") + private UUID requestId; + + public EnforcerTelemetryActivityDetails(PXConfiguration pxConfiguration, PXContext context, UpdateReason updateReason) { this.moduleVersion = Constants.SDK_VERSION; this.osName = System.getProperty("os.name"); this.updateReason = updateReason; + this.requestId = context.getRequestId(); try { this.nodeName = InetAddress.getLocalHost().getHostName(); } catch (UnknownHostException e) { @@ -36,11 +45,13 @@ public EnforcerTelemetryActivityDetails(PXConfiguration pxConfiguration, UpdateR } try { - Gson gson = new Gson(); - String pxConfigJson = gson.toJson(pxConfiguration.getTelemetryConfig()); - this.enforcerConfigs = pxConfigJson; + PXConfiguration config = pxConfiguration.getTelemetryConfig(); + enforcerConfigs = new TelemetryConfiguration(); + enforcerConfigs.activeConfig = config; + enforcerConfigs.staticConfig = config; + enforcerConfigs.remoteConfig = null; // remote config not supported } catch (JsonIOException e) { - this.enforcerConfigs = "Could not retrieve pxConfiguration"; + enforcerConfigs = null; } } @@ -48,7 +59,7 @@ public String getModuleVersion() { return moduleVersion; } - public String getEnforcerConfigs() { + public TelemetryConfiguration getEnforcerConfigs() { return enforcerConfigs; } @@ -59,4 +70,19 @@ public String getOsName() { public String getNodeName() { return nodeName; } + + public UUID getRequestId() { + return requestId; + } +} + +class TelemetryConfiguration { + @JsonProperty("active_config") + public PXConfiguration activeConfig; + + @JsonProperty("static_config") + public PXConfiguration staticConfig; + + @JsonProperty("remote_config") + public PXConfiguration remoteConfig; } diff --git a/src/main/java/com/perimeterx/models/configuration/ModuleMode.java b/src/main/java/com/perimeterx/models/configuration/ModuleMode.java index ef121579..901b0761 100644 --- a/src/main/java/com/perimeterx/models/configuration/ModuleMode.java +++ b/src/main/java/com/perimeterx/models/configuration/ModuleMode.java @@ -10,13 +10,11 @@ * Created by nitzangoldfeder on 26/06/2017. */ public enum ModuleMode { - MONITOR(0), BLOCKING(1); - private int value; - - private static Map namesMap = new HashMap<>(2); + private final int value; + private static final Map namesMap = new HashMap<>(2); static { namesMap.put(0, MONITOR); namesMap.put(1, BLOCKING); @@ -27,26 +25,12 @@ public static ModuleMode forValue(Integer value) { return namesMap.get(value); } - @JsonValue - public Integer toValue() { - for (Map.Entry entry : namesMap.entrySet()) { - if (entry.getValue() == this) - return entry.getKey(); - } - return 0; - } - - ModuleMode(int value) { - this.value = value; - } - @JsonValue public int getValue() { return this.value; } - @JsonCreator - public void setValue(int value) { + ModuleMode(int value) { this.value = value; } } diff --git a/src/main/java/com/perimeterx/models/configuration/PXConfiguration.java b/src/main/java/com/perimeterx/models/configuration/PXConfiguration.java index 1f0665d1..8bb1baad 100644 --- a/src/main/java/com/perimeterx/models/configuration/PXConfiguration.java +++ b/src/main/java/com/perimeterx/models/configuration/PXConfiguration.java @@ -1,6 +1,7 @@ package com.perimeterx.models.configuration; import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import com.perimeterx.api.PerimeterX; import com.perimeterx.api.additionalContext.credentialsIntelligence.CIProtocol; @@ -48,6 +49,27 @@ @AllArgsConstructor @NoArgsConstructor @Getter +@JsonIgnoreProperties({ + "customParametersProvider", + "blockHandler", + "customLoginResponseValidator", + "credentialsCustomExtractor", + "customIsSensitiveRequest", + "customParametersExtraction", + "filterByCustomFunction", + "loggerFactory", + "telemetryConfig", + "reverseProxyInstance", + "ipxHttpClientInstance", + "ipxhttpClientInstance", + "IPXHttpClientInstance", + "pxClientInstance", + "PXClientInstance", + "pxclientInstance", + "httpClient", + "pxClient", + "pxReverseProxy" +}) public class PXConfiguration { private static LoggerSeverity loggerSeverity = null; @@ -256,6 +278,10 @@ public static void setPxLoggerSeverity(LoggerSeverity severity) { @JsonProperty("px_login_successful_status") private int[] loginResponseValidationStatusCode = {200}; + @Builder.Default + @JsonProperty("px_secured_pxhd_enabled") + private boolean securedPxhdEnabled = false; + @Builder.Default private LoginResponseValidator customLoginResponseValidator = new DefaultCustomLoginResponseValidator(); @@ -312,7 +338,49 @@ public static void setPxLoggerSeverity(LoggerSeverity severity) { * @return Configuration Object clone without cookieKey and authToken **/ public PXConfiguration getTelemetryConfig() { - return this.toBuilder().clearCookieKeys().authToken(null).build(); + + PXConfiguration telemetry = this.toBuilder() + .authToken(this.redactString(this.authToken)) + .clearCookieKeys() + .cookieKeys(this.cookieKeys.stream().map(this::redactString).collect(Collectors.toList())) + .loggerAuthToken(this.redactString(this.loggerAuthToken)) + .sensitiveRoutesRegex(this.stringifyRegexSet(this.sensitiveRoutesRegex)) + // prune non-serializable/runtime members for telemetry clone + .customParametersProvider(null) + .blockHandler(null) + .customLoginResponseValidator(null) + .credentialsCustomExtractor(null) + .customIsSensitiveRequest(null) + .customParametersExtraction(null) + .filterByCustomFunction(null) + .loggerFactory(null) + .httpClient(null) + .pxClient(null) + .pxReverseProxy(null) + .build(); + // ensure transient instances are not serialized + telemetry.pxClientInstance = null; + telemetry.ipxHttpClientInstance = null; + telemetry.reverseProxyInstance = null; + return telemetry; + } + + private Set stringifyRegexSet(Set regexSet) { + if (regexSet == null) { + return null; + } + return regexSet.stream() + .map(r -> r != null && r.startsWith("_REGEXP ") ? r : "_REGEXP /" + r + "/") + .collect(Collectors.toSet()); + } + + private String redactString(String str) { + int trailingChars = 5; + String redactedPrefix = "***REDACTED***"; + if (str == null || str.length() <= trailingChars) { + return redactedPrefix; + } + return redactedPrefix.concat(str.substring(str.length() - trailingChars)); } public void disableModule() { diff --git a/src/main/java/com/perimeterx/models/httpmodels/Additional.java b/src/main/java/com/perimeterx/models/httpmodels/Additional.java index 2c4df51c..46235630 100644 --- a/src/main/java/com/perimeterx/models/httpmodels/Additional.java +++ b/src/main/java/com/perimeterx/models/httpmodels/Additional.java @@ -85,14 +85,22 @@ public class Additional { @JsonProperty("request_id") public UUID requestId; + @JsonProperty("enforcer_start_time") public long enforcerStartTime; + @JsonProperty("risk_start_time") public long riskStartTime; @JsonProperty("cross_tab_session") public String pxCtsCookie; + @JsonProperty("is_sensitive_route") + public Boolean isSensitiveRoute; + + @JsonProperty("additional_token_info") + public String additionalTokenInfo; + public static Additional fromContext(PXContext ctx) { Additional additional = new Additional(); additional.pxCookie = ctx.getRiskCookie(); @@ -114,6 +122,8 @@ public static Additional fromContext(PXContext ctx) { additional.enforcerStartTime = ctx.getEnforcerStartTime(); additional.riskStartTime = new Date().getTime(); additional.pxCtsCookie = ctx.getPxCtsCookie(); + additional.isSensitiveRoute = ctx.isSensitiveRequest(); + additional.additionalTokenInfo = ctx.getAdditionalTokenInfo(); setLoginCredentials(ctx, additional); diff --git a/src/main/java/com/perimeterx/models/risk/CustomParameters.java b/src/main/java/com/perimeterx/models/risk/CustomParameters.java index 6a51cb9c..34e4c993 100644 --- a/src/main/java/com/perimeterx/models/risk/CustomParameters.java +++ b/src/main/java/com/perimeterx/models/risk/CustomParameters.java @@ -6,30 +6,32 @@ /** * Created by nitzangoldfeder on 03/04/2018. */ + +// Note: Parameters are of type Object to allow flexibility in the type of data being sent (e.g., String, Number, Boolean, etc.) @JsonInclude(JsonInclude.Include.NON_NULL) public class CustomParameters { @JsonProperty("custom_param1") - public String customParam1; + public Object customParam1; @JsonProperty("custom_param2") - public String customParam2; + public Object customParam2; @JsonProperty("custom_param3") - public String customParam3; + public Object customParam3; @JsonProperty("custom_param4") - public String customParam4; + public Object customParam4; @JsonProperty("custom_param5") - public String customParam5; + public Object customParam5; @JsonProperty("custom_param6") - public String customParam6; + public Object customParam6; @JsonProperty("custom_param7") - public String customParam7; + public Object customParam7; @JsonProperty("custom_param8") - public String customParam8; + public Object customParam8; @JsonProperty("custom_param9") - public String customParam9; + public Object customParam9; @JsonProperty("custom_param10") - public String customParam10; + public Object customParam10; - public String getCustomParam1() { + public Object getCustomParam1() { return customParam1; } @@ -37,7 +39,7 @@ public void setCustomParam1(String customParam1) { this.customParam1 = customParam1; } - public String getCustomParam2() { + public Object getCustomParam2() { return customParam2; } @@ -45,7 +47,7 @@ public void setCustomParam2(String customParam2) { this.customParam2 = customParam2; } - public String getCustomParam3() { + public Object getCustomParam3() { return customParam3; } @@ -53,7 +55,7 @@ public void setCustomParam3(String customParam3) { this.customParam3 = customParam3; } - public String getCustomParam4() { + public Object getCustomParam4() { return customParam4; } @@ -61,7 +63,7 @@ public void setCustomParam4(String customParam4) { this.customParam4 = customParam4; } - public String getCustomParam5() { + public Object getCustomParam5() { return customParam5; } @@ -69,7 +71,7 @@ public void setCustomParam5(String customParam5) { this.customParam5 = customParam5; } - public String getCustomParam6() { + public Object getCustomParam6() { return customParam6; } @@ -77,7 +79,7 @@ public void setCustomParam6(String customParam6) { this.customParam6 = customParam6; } - public String getCustomParam7() { + public Object getCustomParam7() { return customParam7; } @@ -85,7 +87,7 @@ public void setCustomParam7(String customParam7) { this.customParam7 = customParam7; } - public String getCustomParam8() { + public Object getCustomParam8() { return customParam8; } @@ -93,7 +95,7 @@ public void setCustomParam8(String customParam8) { this.customParam8 = customParam8; } - public String getCustomParam9() { + public Object getCustomParam9() { return customParam9; } @@ -101,7 +103,7 @@ public void setCustomParam9(String customParam9) { this.customParam9 = customParam9; } - public String getCustomParam10() { + public Object getCustomParam10() { return customParam10; } diff --git a/src/main/java/com/perimeterx/utils/logger/LoggerFactory.java b/src/main/java/com/perimeterx/utils/logger/LoggerFactory.java index 42b400c3..26ed9eb3 100644 --- a/src/main/java/com/perimeterx/utils/logger/LoggerFactory.java +++ b/src/main/java/com/perimeterx/utils/logger/LoggerFactory.java @@ -9,7 +9,7 @@ public IPXLogger getRequestContextLogger(boolean isMemoryEnabled) { if (pxLoggerSeverity == null) { return new Slf4JLogger(isMemoryEnabled); } else { - return new ConsoleLogger(pxLoggerSeverity,isMemoryEnabled); + return new ConsoleLogger(pxLoggerSeverity, isMemoryEnabled); } } public IPXLogger getRequestContextLogger() { diff --git a/src/main/resources/com/perimeterx/api/blockhandler/templates/captcha_template.mustache b/src/main/resources/com/perimeterx/api/blockhandler/templates/captcha_template.mustache index 4a1503bf..bd4aade7 100644 --- a/src/main/resources/com/perimeterx/api/blockhandler/templates/captcha_template.mustache +++ b/src/main/resources/com/perimeterx/api/blockhandler/templates/captcha_template.mustache @@ -10,70 +10,71 @@ {{/cssRef}} - -{{#jsRef}} - -{{/jsRef}} + function isContentLoaded() { + return !!document.querySelector('div,span'); + } + window._pxOnError = function () { + var style = document.createElement('style'); + style.innerText = '@import url(https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap);body{background-color:#fafbfc}.px-captcha-error-container{position:fixed;height:340px;background-color:#fff;font-family:Roboto,sans-serif}.px-captcha-error-header{color:#f0f1f2;font-size:29px;margin:67px 0 33px;font-weight:500;line-height:.83;text-align:center}.px-captcha-error-message{color:#f0f1f2;font-size:18px;margin:0 0 29px;line-height:1.33;text-align:center}.px-captcha-error-button{text-align:center;line-height:48px;width:253px;margin:auto;border-radius:50px;border:solid 1px #f0f1f2;font-size:20px;color:#f0f1f2}.px-captcha-error-wrapper{margin:18px 0 0}div.px-captcha-error{margin:auto;text-align:center;width:400px;height:30px;font-size:12px;background-color:#fcf0f2;color:#ce0e2d}img.px-captcha-error{margin:6px 8px -2px 0}.px-captcha-error-refid{border-top:solid 1px #f0eeee;height:27px;margin:13px 0 0;border-radius:0 0 3px 3px;background-color:#fafbfc;font-size:10px;line-height:2.5;text-align:center;color:#b1b5b8}@media (min-width:620px){.px-captcha-error-container{width:530px;top:50%;left:50%;margin-top:-170px;margin-left:-265px;border-radius:3px;box-shadow:0 2px 9px -1px rgba(0,0,0,.13)}}@media (min-width:481px) and (max-width:620px){.px-captcha-error-container{width:85%;top:50%;left:50%;margin-top:-170px;margin-left:-42.5%;border-radius:3px;box-shadow:0 2px 9px -1px rgba(0,0,0,.13)}}@media (max-width:480px){body{background-color:#fff}.px-captcha-error-header{color:#f0f1f2;font-size:29px;margin:55px 0 33px}.px-captcha-error-container{width:530px;top:50%;left:50%;margin-top:-170px;margin-left:-265px}.px-captcha-error-refid{position:fixed;width:100%;left:0;bottom:0;border-radius:0;font-size:14px;line-height:2}}@media (max-width:390px){div.px-captcha-error{font-size:10px}.px-captcha-error-refid{font-size:11px;line-height:2.5}}'; + document.head.appendChild(style); + var div = document.createElement('div'); + div.className = 'px-captcha-error-container'; + div.innerHTML = '
Before we continue...
Press & Hold to confirm you are
a human (and not a bot).
Press & Hold
Please check your internet connection' + (window._pxMobile ? '' : ' or disable your ad-blocker') + '.
Reference ID ' + window._pxUuid + '
'; + document.body.appendChild(div); + if (window._pxMobile) { + setTimeout(function() { + location.href = '/px/captcha_close?status=-1'; + }, 5000); + } + }; + + {{#jsRef}} + + {{/jsRef}} diff --git a/web/pom.xml b/web/pom.xml index 404ffa14..a0585a32 100644 --- a/web/pom.xml +++ b/web/pom.xml @@ -31,7 +31,7 @@ org.slf4j slf4j-api - 1.7.25 + 1.7.36 org.slf4j diff --git a/web/src/main/java/com/web/Config.java b/web/src/main/java/com/web/Config.java index 1d7333f6..462b3a05 100644 --- a/web/src/main/java/com/web/Config.java +++ b/web/src/main/java/com/web/Config.java @@ -6,6 +6,7 @@ import com.perimeterx.models.configuration.PXConfiguration; import com.perimeterx.models.configuration.credentialsIntelligenceconfig.CILoginMap; import com.perimeterx.models.risk.CustomParameters; +import com.perimeterx.utils.logger.LoggerSeverity; import org.json.JSONArray; import org.json.JSONObject; @@ -153,6 +154,12 @@ public PXConfiguration getPxConfiguration() { case "px_login_successful_status": builder.loginResponseValidationStatusCode(extractStatusCode(key)); break; + case "px_logger_severity": + this.setLoggerSeverity(enforcerConfig.getString(key)); + break; + case "px_secured_pxhd_enabled": + builder.securedPxhdEnabled(enforcerConfig.getBoolean(key)); + break; case "px_user_agent_max_length": case "px_risk_cookie_max_length": case "px_risk_cookie_max_iterations": @@ -168,16 +175,35 @@ public PXConfiguration getPxConfiguration() { CustomParameters customParameters = new CustomParameters(); customParameters.customParam1 = "test1"; customParameters.customParam2 = "test2"; - customParameters.customParam3 = "3"; - customParameters.customParam4 = "4"; - customParameters.customParam5 = "5"; - customParameters.customParam6 = "6"; + customParameters.customParam3 = 3; + customParameters.customParam4 = 4; + customParameters.customParam5 = 5; + customParameters.customParam6 = 6; + customParameters.customParam7 = req.getRequestURI(); return customParameters; }); + builder.customIsSensitiveRequest((req -> { + return req.getRequestURI().startsWith("/sensitive") && req.getMethod().equals("POST"); + })); + return builder.build(); } + private void setLoggerSeverity(String severity) { + switch (severity) { + case "debug": + PXConfiguration.setPxLoggerSeverity(LoggerSeverity.DEBUG); + break; + case "error": + PXConfiguration.setPxLoggerSeverity(LoggerSeverity.ERROR); + break; + case "none": + PXConfiguration.setPxLoggerSeverity(LoggerSeverity.NONE); + break; + } + } + private int[] extractStatusCode(String key) { final JSONArray jsonField = enforcerConfig.getJSONArray(key); final int[] statusCode = new int[jsonField.length()];