diff --git a/CHANGELOG.md b/CHANGELOG.md index 97131132c..e4e151c32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,21 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [1.95.0](https://github.com/rudderlabs/rudder-config-schema/compare/v1.94.2...v1.95.0) (2024-10-09) + + +### Features + +* add Iubenda support to ga4 destination ([#1691](https://github.com/rudderlabs/rudder-config-schema/issues/1691)) ([2ef7ae4](https://github.com/rudderlabs/rudder-config-schema/commit/2ef7ae497b3bad172024d1eeb54beb223ddf296a)) +* added test cases ([#1659](https://github.com/rudderlabs/rudder-config-schema/issues/1659)) ([6339410](https://github.com/rudderlabs/rudder-config-schema/commit/6339410ecec4f6739df44383b866b82662642ae6)) +* onboard Amazon Audience ([#1667](https://github.com/rudderlabs/rudder-config-schema/issues/1667)) ([d841adf](https://github.com/rudderlabs/rudder-config-schema/commit/d841adfc5103978a6a83412a51a00f87a9b7f28f)) + + +### Bug Fixes + +* add new field for list of props ([#1734](https://github.com/rudderlabs/rudder-config-schema/issues/1734)) ([d45386b](https://github.com/rudderlabs/rudder-config-schema/commit/d45386b4081d0d910b078c073147257842b78772)) +* webhook regex url ([#1743](https://github.com/rudderlabs/rudder-config-schema/issues/174)) ([3435280](https://github.com/rudderlabs/rudder-config-schema/commit/3435280b68b6dbf30bdeddc751143994ad07f3f4)) + ### [1.94.2](https://github.com/rudderlabs/rudder-config-schema/compare/v1.94.1...v1.94.2) (2024-10-04) diff --git a/package-lock.json b/package-lock.json index edba10b1a..da2162394 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "rudder-config-schema", - "version": "1.94.2", + "version": "1.95.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "rudder-config-schema", - "version": "1.94.2", + "version": "1.95.0", "license": "MIT", "dependencies": { "ajv": "^8.12.0", diff --git a/package.json b/package.json index c380fa19a..544808968 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rudder-config-schema", - "version": "1.94.2", + "version": "1.95.0", "description": "", "main": "src/index.ts", "private": true, diff --git a/src/configurations/destinations/amazon_audience/db-config.json b/src/configurations/destinations/amazon_audience/db-config.json new file mode 100644 index 000000000..7ea203fc4 --- /dev/null +++ b/src/configurations/destinations/amazon_audience/db-config.json @@ -0,0 +1,40 @@ +{ + "name": "AMAZON_AUDIENCE", + "displayName": "Amazon Audience", + "config": { + "auth": { "type": "OAuth", "role": "amazon_audience", "rudderScopes": ["delivery"] }, + "transformAtV1": "router", + "excludeKeys": [], + "supportedSourceTypes": ["warehouse"], + "supportedConnectionModes": { + "warehouse": ["cloud"] + }, + "isAudienceSupported": true, + "supportsBlankAudienceCreation": true, + "syncBehaviours": ["mirror"], + "disableJsonMapper": true, + "supportsVisualMapper": true, + "includeKeys": ["oneTrustCookieCategories", "consentManagement"], + "destConfig": { + "defaultConfig": [ + "rudderAccountId", + "audienceId", + "authServer", + "advertiserId", + "externalAudienceId", + "ttl", + "dataSourceCountry", + "enableHash" + ], + "warehouse": [ + "oneTrustCookieCategories", + "connectionMode", + "consentManagement", + "ketchConsentPurposes" + ] + }, + "secretKeys": [], + "supportedMessageTypes": { "cloud": ["record"] } + }, + "options": { "isBeta": true } +} diff --git a/src/configurations/destinations/amazon_audience/schema.json b/src/configurations/destinations/amazon_audience/schema.json new file mode 100644 index 000000000..e06a702c1 --- /dev/null +++ b/src/configurations/destinations/amazon_audience/schema.json @@ -0,0 +1,134 @@ +{ + "configSchema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "required": ["authServer"], + "properties": { + "authServer": { + "type": "string", + "enum": ["North America"], + "default": "North America" + }, + "advertiserId": { + "type": "string", + "pattern": "(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(.{1,150})$" + }, + "externalAudienceId": { + "type": "string", + "pattern": "(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(.{1,50})$" + }, + "ttl": { + "type": "string", + "pattern": "(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^[0-9]\\d*$" + }, + "enableHash": { + "type": "boolean", + "default": false + }, + "dataSourceCountry": { + "type": "array", + "items": { + "type": "object", + "properties": { + "country": { + "type": "string", + "pattern": "(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(.{0,100})$" + } + } + } + }, + "oneTrustCookieCategories": { + "type": "object", + "properties": { + "warehouse": { + "type": "array", + "items": { + "type": "object", + "properties": { + "oneTrustCookieCategory": { + "type": "string", + "pattern": "(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(.{0,100})$" + } + } + } + } + } + }, + "consentManagement": { + "type": "object", + "properties": { + "warehouse": { + "type": "array", + "items": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": ["custom", "ketch", "oneTrust"], + "default": "oneTrust" + }, + "consents": { + "type": "array", + "items": { + "type": "object", + "properties": { + "consent": { + "type": "string", + "pattern": "(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(.{0,100})$" + } + } + } + } + }, + "allOf": [ + { + "if": { + "properties": { + "provider": { + "const": "custom" + } + }, + "required": ["provider"] + }, + "then": { + "properties": { + "resolutionStrategy": { + "type": "string", + "enum": ["and", "or"] + } + }, + "required": ["resolutionStrategy"] + } + } + ] + } + } + } + }, + "ketchConsentPurposes": { + "type": "object", + "properties": { + "warehouse": { + "type": "array", + "items": { + "type": "object", + "properties": { + "purpose": { + "type": "string", + "pattern": "(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(.{0,100})$" + } + } + } + } + } + }, + "connectionMode": { + "type": "object", + "properties": { + "cloud": { "type": "string", "enum": ["cloud"] }, + "warehouse": { "type": "string", "enum": ["cloud"] } + } + } + } + } +} diff --git a/src/configurations/destinations/amazon_audience/ui-config.json b/src/configurations/destinations/amazon_audience/ui-config.json new file mode 100644 index 000000000..86ccce9c6 --- /dev/null +++ b/src/configurations/destinations/amazon_audience/ui-config.json @@ -0,0 +1,299 @@ +{ + "uiConfig": { + "baseTemplate": [ + { + "title": "Initial setup", + "note": "Review how this destination is set up", + "sections": [ + { + "groups": [ + { + "title": "Connection settings", + "note": "Update your connection settings here", + "icon": "settings", + "fields": [ + { + "configKey": "advertiserId", + "type": "nestedSelect", + "label": "Select your Account", + "apiName": "getAmazonAdvertiser", + "placeholder": "Select Advertiser Id details", + "preRequisites": { + "fields": [ + { + "configKey": "rudderAccountId", + "exists": true + } + ] + } + }, + { + "type": "singleSelect", + "label": "Authorization servers", + "note": " Support for more servers will be added soon", + "configKey": "authServer", + "options": [ + { + "name": "North America", + "value": "North America" + } + ], + "default": "North America" + } + ] + } + ] + }, + { + "groups": [ + { + "title": "Connection mode", + "note": [ + "Update how you want to route events from your source to destination. ", + { + "text": "Get help deciding", + "link": "https://www.rudderstack.com/docs/destinations/rudderstack-connection-modes/" + } + ], + "icon": "sliders", + "fields": [] + } + ] + } + ] + }, + { + "title": "Configuration settings", + "note": "Manage the settings for your destination", + "sections": [ + { + "groups": [ + { + "title": "Optional configuration settings", + "note": "Configure advanced destination-specific settings here", + "icon": "settings", + "fields": [ + { + "type": "checkbox", + "label": "Enable user data hashing", + "note": [ + "Enabling this will hash all the user data before sending it to Amazon Audience", + "Do not enable it if you already pass hash data to rudderstack" + ], + "configKey": "enableHash", + "default": false + } + ] + }, + { + "title": "Optional Audience Creation Configuration settings", + "icon": "settings", + "fields": [ + { + "configKey": "externalAudienceId", + "type": "textInput", + "label": "Type External Audience Id to use while creating Audience", + "placeholder": "Default: Rudderstack Audience", + "regex": "(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(.{1,50})$", + "regexErrorMessage": "Invalid External Audience Id", + "default": "Rudderstack Audience" + }, + { + "configKey": "ttl", + "type": "textInput", + "label": "Time To Live", + "placeholder": "Default: 34300800(13 Months)", + "regexErrorMessage": "ttl should be in number", + "regex": "(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^[0-9]\\d*$", + "note": [ + "Refer below link for more info", + { + "text": "Time To live", + "link": "https://advertising.amazon.com/API/docs/en-us/guides/amazon-marketing-cloud/audiences/audience-management-service#:~:text=a%20given%20invocation.-,Note,-The%20time%2Dto" + } + ], + "default": "34300800" + }, + { + "type": "tagInput", + "label": "Data Source Countries", + "configKey": "dataSourceCountry", + "tagKey": "country", + "placeholder": "e.g: US", + "note": [ + "Refer below link for more info", + { + "text": "Data Source Countries", + "link": "https://advertising.amazon.com/API/docs/en-us/guides/amazon-marketing-cloud/audiences/audience-management-service#:~:text=a%20given%20invocation.-,Note,-The%20time%2Dto" + } + ], + "default": [ + { + "country": "US" + } + ] + } + ] + } + ] + }, + { + "title": "Other settings", + "note": "Configure advanced RudderStack features here", + "icon": "otherSettings", + "groups": [ + { + "title": "OneTrust consent settings", + "note": [ + "Enter your OneTrust consent category IDs if you have them configured. The support for category names is deprecated. We recommend using the category IDs instead of the names as IDs are unique and less likely to change over time, making them a more reliable choice.", + { + "text": "Learn more ", + "link": "https://www.rudderstack.com/docs/sources/event-streams/sdks/consent-manager/onetrust/" + }, + "about RudderStack's OneTrust Consent Management feature." + ], + "fields": [ + { + "type": "tagInput", + "label": "OneTrust consent category IDs", + "note": "Input your OneTrust category IDs by pressing 'Enter' after each entry. The support for category names is deprecated. We recommend using the category IDs instead of the names as IDs are unique and less likely to change over time, making them a more reliable choice.", + "configKey": "oneTrustCookieCategories", + "tagKey": "oneTrustCookieCategory", + "placeholder": "e.g: C0001", + "default": [ + { + "oneTrustCookieCategory": "" + } + ], + "preRequisites": { + "featureFlags": [ + { + "configKey": "AMP_enable-gcm", + "value": false + }, + { + "configKey": "AMP_enable-gcm" + } + ], + "featureFlagsCondition": "or" + } + } + ] + } + ] + } + ] + } + ], + "sdkTemplate": { + "title": "Web SDK settings", + "note": "not visible in the ui", + "fields": [] + }, + "consentSettingsTemplate": { + "title": "Consent settings", + "note": "not visible in the ui", + "fields": [ + { + "type": "dynamicCustomForm", + "configKey": "consentManagement", + "default": [], + "rowFields": [ + { + "type": "singleSelect", + "label": "Consent management provider", + "configKey": "provider", + "options": [ + { + "label": "Custom", + "value": "custom" + }, + { + "label": "Ketch", + "value": "ketch" + }, + { + "label": "OneTrust", + "value": "oneTrust" + } + ], + "default": "oneTrust", + "required": true + }, + { + "type": "tagInput", + "label": "Ketch consent purpose IDs", + "note": "Input your Ketch consent purpose IDs by pressing 'Enter' after each entry.", + "configKey": "ketchConsentPurposes", + "tagKey": "purpose", + "placeholder": "e.g: marketing", + "default": [ + { + "purpose": "" + } + ], + "preRequisites": { + "featureFlags": [ + { + "configKey": "AMP_enable-gcm", + "value": false + }, + { + "configKey": "AMP_enable-gcm" + } + ], + "featureFlagsCondition": "or" + } + }, + { + "type": "singleSelect", + "label": "the required consent logic", + "configKey": "resolutionStrategy", + "options": [ + { + "label": "AND", + "value": "and" + }, + { + "label": "OR", + "value": "or" + } + ], + "required": true, + "variant": "badge", + "preRequisites": { + "fields": [ + { + "configKey": "provider", + "value": "custom" + } + ] + } + }, + { + "type": "tagInput", + "label": "Enter consent category ID’s", + "note": "Input your consent category IDs by pressing ‘Enter’ after each entry. The support for category names is deprecated. We recommend using the category IDs instead of the names as IDs are unique and less likely to change over time, making them a more reliable choice.", + "configKey": "consents", + "tagKey": "consent", + "placeholder": "e.g: Marketing", + "default": [ + { + "consent": "" + } + ] + } + ], + "preRequisites": { + "featureFlags": [ + { + "configKey": "AMP_enable-gcm", + "value": true + } + ] + } + } + ] + } + } +} diff --git a/src/configurations/destinations/webhook/schema.json b/src/configurations/destinations/webhook/schema.json index 9fbeb476b..68b0d558b 100644 --- a/src/configurations/destinations/webhook/schema.json +++ b/src/configurations/destinations/webhook/schema.json @@ -517,7 +517,7 @@ }, "webhookUrl": { "type": "string", - "pattern": "(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|(?!.*\\.ngrok\\.io)^(https?):\\/\\/(?!localhost|127\\.0\\.0\\.1|10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|192\\.168\\.\\d{1,3}\\.\\d{1,3}|172\\.(1[6-9]|2[0-9]|3[0-1])\\.\\d{1,3}\\.\\d{1,3}|0\\.0\\.0\\.0|\\[::1\\]|\\[fc[0-9a-fA-F]{2}:.*\\]|\\[fd[0-9a-fA-F]{2}:.*\\]|\\[::ffff:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\]).*([^\\s/$.?#].[^\\s]*)$" + "pattern": "(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(https?:\\/\\/)(?![a-zA-Z0-9-]*\\.ngrok\\.io)(?!localhost|.*\\.localhost)([a-zA-Z0-9-]{1,63}\\.)+[a-zA-Z]{2,}(\\/.*)?$" }, "webhookMethod": { "type": "string", diff --git a/src/configurations/destinations/webhook/ui-config.json b/src/configurations/destinations/webhook/ui-config.json index 9a7448136..d9a8383a7 100644 --- a/src/configurations/destinations/webhook/ui-config.json +++ b/src/configurations/destinations/webhook/ui-config.json @@ -9,7 +9,7 @@ "value": "webhookUrl", "required": true, "placeholder": "http://www.abcd.com", - "regex": "(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|(?!.*\\.ngrok\\.io)^(https?):\\/\\/(?!localhost|127\\.0\\.0\\.1|10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|192\\.168\\.\\d{1,3}\\.\\d{1,3}|172\\.(1[6-9]|2[0-9]|3[0-1])\\.\\d{1,3}\\.\\d{1,3}|0\\.0\\.0\\.0|\\[::1\\]|\\[fc[0-9a-fA-F]{2}:.*\\]|\\[fd[0-9a-fA-F]{2}:.*\\]|\\[::ffff:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\]).*([^\\s/$.?#].[^\\s]*)$" + "regex": "^(https?:\\/\\/)(?![a-zA-Z0-9-]*\\.ngrok\\.io)(?!localhost|.*\\.localhost)([a-zA-Z0-9-]{1,63}\\.)+[a-zA-Z]{2,}(\\/.*)?$" }, { "type": "singleSelect", diff --git a/src/configurations/destinations/x_audience/ui-config.json b/src/configurations/destinations/x_audience/ui-config.json index 2bcd94dc6..eff702d61 100644 --- a/src/configurations/destinations/x_audience/ui-config.json +++ b/src/configurations/destinations/x_audience/ui-config.json @@ -17,6 +17,7 @@ "configKey": "accountId", "type": "nestedSelect", "label": "Select your Account", + "note": "Select Account -> Account Settings -> General -> AccountId", "apiName": "getXAccounts", "placeholder": "Select account details", "preRequisites": { diff --git a/test/data/validation/destinations/amazon_audience.json b/test/data/validation/destinations/amazon_audience.json new file mode 100644 index 000000000..2033585c0 --- /dev/null +++ b/test/data/validation/destinations/amazon_audience.json @@ -0,0 +1,33 @@ +[ + { + "testTitle": "With all required configs", + "config": { + "rudderAccountId": "test-host", + "ttl": "1230", + "enableHash": true, + "dataSourceCountry": [ + { + "country": "US" + }, + { + "country": "CAN" + } + ], + "advertiserId": "test-advertiser-id", + "audienceId": "test-audience-id" + }, + "result": true + }, + { + "testTitle": "With missing accountId", + "config": { + "rudderAccountId": "test-host", + "audienceId": "test-audience-id", + "advertiserId": "" + }, + "result": false, + "err": [ + "advertiserId must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(.{1,150})$\"" + ] + } +] diff --git a/test/data/validation/destinations/webhook.json b/test/data/validation/destinations/webhook.json index 59f98338b..062b3e13a 100644 --- a/test/data/validation/destinations/webhook.json +++ b/test/data/validation/destinations/webhook.json @@ -39,7 +39,10 @@ } ] }, - "result": true + "result": false, + "err": [ + "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(https?:\\/\\/)(?![a-zA-Z0-9-]*\\.ngrok\\.io)(?!localhost|.*\\.localhost)([a-zA-Z0-9-]{1,63}\\.)+[a-zA-Z]{2,}(\\/.*)?$\"" + ] }, { "config": { @@ -62,7 +65,7 @@ }, "result": false, "err": [ - "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|(?!.*\\.ngrok\\.io)^(https?):\\/\\/(?!localhost|127\\.0\\.0\\.1|10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|192\\.168\\.\\d{1,3}\\.\\d{1,3}|172\\.(1[6-9]|2[0-9]|3[0-1])\\.\\d{1,3}\\.\\d{1,3}|0\\.0\\.0\\.0|\\[::1\\]|\\[fc[0-9a-fA-F]{2}:.*\\]|\\[fd[0-9a-fA-F]{2}:.*\\]|\\[::ffff:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\]).*([^\\s/$.?#].[^\\s]*)$\"" + "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(https?:\\/\\/)(?![a-zA-Z0-9-]*\\.ngrok\\.io)(?!localhost|.*\\.localhost)([a-zA-Z0-9-]{1,63}\\.)+[a-zA-Z]{2,}(\\/.*)?$\"" ] }, { @@ -86,7 +89,7 @@ }, "result": false, "err": [ - "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|(?!.*\\.ngrok\\.io)^(https?):\\/\\/(?!localhost|127\\.0\\.0\\.1|10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|192\\.168\\.\\d{1,3}\\.\\d{1,3}|172\\.(1[6-9]|2[0-9]|3[0-1])\\.\\d{1,3}\\.\\d{1,3}|0\\.0\\.0\\.0|\\[::1\\]|\\[fc[0-9a-fA-F]{2}:.*\\]|\\[fd[0-9a-fA-F]{2}:.*\\]|\\[::ffff:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\]).*([^\\s/$.?#].[^\\s]*)$\"" + "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(https?:\\/\\/)(?![a-zA-Z0-9-]*\\.ngrok\\.io)(?!localhost|.*\\.localhost)([a-zA-Z0-9-]{1,63}\\.)+[a-zA-Z]{2,}(\\/.*)?$\"" ] }, { @@ -110,7 +113,7 @@ }, "result": false, "err": [ - "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|(?!.*\\.ngrok\\.io)^(https?):\\/\\/(?!localhost|127\\.0\\.0\\.1|10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|192\\.168\\.\\d{1,3}\\.\\d{1,3}|172\\.(1[6-9]|2[0-9]|3[0-1])\\.\\d{1,3}\\.\\d{1,3}|0\\.0\\.0\\.0|\\[::1\\]|\\[fc[0-9a-fA-F]{2}:.*\\]|\\[fd[0-9a-fA-F]{2}:.*\\]|\\[::ffff:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\]).*([^\\s/$.?#].[^\\s]*)$\"" + "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(https?:\\/\\/)(?![a-zA-Z0-9-]*\\.ngrok\\.io)(?!localhost|.*\\.localhost)([a-zA-Z0-9-]{1,63}\\.)+[a-zA-Z]{2,}(\\/.*)?$\"" ] }, { @@ -134,7 +137,7 @@ }, "result": false, "err": [ - "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|(?!.*\\.ngrok\\.io)^(https?):\\/\\/(?!localhost|127\\.0\\.0\\.1|10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|192\\.168\\.\\d{1,3}\\.\\d{1,3}|172\\.(1[6-9]|2[0-9]|3[0-1])\\.\\d{1,3}\\.\\d{1,3}|0\\.0\\.0\\.0|\\[::1\\]|\\[fc[0-9a-fA-F]{2}:.*\\]|\\[fd[0-9a-fA-F]{2}:.*\\]|\\[::ffff:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\]).*([^\\s/$.?#].[^\\s]*)$\"" + "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(https?:\\/\\/)(?![a-zA-Z0-9-]*\\.ngrok\\.io)(?!localhost|.*\\.localhost)([a-zA-Z0-9-]{1,63}\\.)+[a-zA-Z]{2,}(\\/.*)?$\"" ] }, { @@ -158,7 +161,7 @@ }, "result": false, "err": [ - "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|(?!.*\\.ngrok\\.io)^(https?):\\/\\/(?!localhost|127\\.0\\.0\\.1|10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|192\\.168\\.\\d{1,3}\\.\\d{1,3}|172\\.(1[6-9]|2[0-9]|3[0-1])\\.\\d{1,3}\\.\\d{1,3}|0\\.0\\.0\\.0|\\[::1\\]|\\[fc[0-9a-fA-F]{2}:.*\\]|\\[fd[0-9a-fA-F]{2}:.*\\]|\\[::ffff:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\]).*([^\\s/$.?#].[^\\s]*)$\"" + "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(https?:\\/\\/)(?![a-zA-Z0-9-]*\\.ngrok\\.io)(?!localhost|.*\\.localhost)([a-zA-Z0-9-]{1,63}\\.)+[a-zA-Z]{2,}(\\/.*)?$\"" ] }, { @@ -182,7 +185,7 @@ }, "result": false, "err": [ - "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|(?!.*\\.ngrok\\.io)^(https?):\\/\\/(?!localhost|127\\.0\\.0\\.1|10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|192\\.168\\.\\d{1,3}\\.\\d{1,3}|172\\.(1[6-9]|2[0-9]|3[0-1])\\.\\d{1,3}\\.\\d{1,3}|0\\.0\\.0\\.0|\\[::1\\]|\\[fc[0-9a-fA-F]{2}:.*\\]|\\[fd[0-9a-fA-F]{2}:.*\\]|\\[::ffff:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\]).*([^\\s/$.?#].[^\\s]*)$\"" + "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(https?:\\/\\/)(?![a-zA-Z0-9-]*\\.ngrok\\.io)(?!localhost|.*\\.localhost)([a-zA-Z0-9-]{1,63}\\.)+[a-zA-Z]{2,}(\\/.*)?$\"" ] }, { @@ -239,7 +242,7 @@ }, "result": false, "err": [ - "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|(?!.*\\.ngrok\\.io)^(https?):\\/\\/(?!localhost|127\\.0\\.0\\.1|10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|192\\.168\\.\\d{1,3}\\.\\d{1,3}|172\\.(1[6-9]|2[0-9]|3[0-1])\\.\\d{1,3}\\.\\d{1,3}|0\\.0\\.0\\.0|\\[::1\\]|\\[fc[0-9a-fA-F]{2}:.*\\]|\\[fd[0-9a-fA-F]{2}:.*\\]|\\[::ffff:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\.(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\\]).*([^\\s/$.?#].[^\\s]*)$\"" + "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(https?:\\/\\/)(?![a-zA-Z0-9-]*\\.ngrok\\.io)(?!localhost|.*\\.localhost)([a-zA-Z0-9-]{1,63}\\.)+[a-zA-Z]{2,}(\\/.*)?$\"" ] }, { @@ -657,5 +660,316 @@ "ketchConsentPurposes.web must be array", "ketchConsentPurposes.unity.0 must be object" ] + }, + { + "testTitle": "localhost with port", + "config": { + "webhookUrl": "http://127.1.2.3:8080", + "webhookMethod": "GET" + }, + "result": false, + "err": [ + "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(https?:\\/\\/)(?![a-zA-Z0-9-]*\\.ngrok\\.io)(?!localhost|.*\\.localhost)([a-zA-Z0-9-]{1,63}\\.)+[a-zA-Z]{2,}(\\/.*)?$\"" + ] + }, + { + "testTitle": "ipv4 address with port", + "config": { + "webhookUrl": "http://192.168.1.100:8080", + "webhookMethod": "GET" + }, + "result": false, + "err": [ + "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(https?:\\/\\/)(?![a-zA-Z0-9-]*\\.ngrok\\.io)(?!localhost|.*\\.localhost)([a-zA-Z0-9-]{1,63}\\.)+[a-zA-Z]{2,}(\\/.*)?$\"" + ] + }, + { + "testTitle": "SSRF - Internal IP address", + "config": { + "webhookUrl": "http://0.0.0.0", + "webhookMethod": "GET" + }, + "result": false, + "err": [ + "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(https?:\\/\\/)(?![a-zA-Z0-9-]*\\.ngrok\\.io)(?!localhost|.*\\.localhost)([a-zA-Z0-9-]{1,63}\\.)+[a-zA-Z]{2,}(\\/.*)?$\"" + ] + }, + { + "testTitle": "SSRF - Private IP address", + "config": { + "webhookUrl": "http://192.168.0.1", + "webhookMethod": "GET" + }, + "result": false, + "err": [ + "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(https?:\\/\\/)(?![a-zA-Z0-9-]*\\.ngrok\\.io)(?!localhost|.*\\.localhost)([a-zA-Z0-9-]{1,63}\\.)+[a-zA-Z]{2,}(\\/.*)?$\"" + ] + }, + { + "testTitle": "SSRF - IPv6 loopback", + "config": { + "webhookUrl": "http://[::1]", + "webhookMethod": "GET" + }, + "result": false, + "err": [ + "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(https?:\\/\\/)(?![a-zA-Z0-9-]*\\.ngrok\\.io)(?!localhost|.*\\.localhost)([a-zA-Z0-9-]{1,63}\\.)+[a-zA-Z]{2,}(\\/.*)?$\"" + ] + }, + { + "testTitle": "SSRF - Domain with DNS rebinding", + "config": { + "webhookUrl": "http://spoofed.burpcollaborator.net", + "webhookMethod": "GET" + }, + "result": true + }, + { + "testTitle": "SSRF - URL encoding bypass attempt", + "config": { + "webhookUrl": "http://127.0.0.1%2f", + "webhookMethod": "GET" + }, + "result": false, + "err": [ + "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(https?:\\/\\/)(?![a-zA-Z0-9-]*\\.ngrok\\.io)(?!localhost|.*\\.localhost)([a-zA-Z0-9-]{1,63}\\.)+[a-zA-Z]{2,}(\\/.*)?$\"" + ] + }, + { + "testTitle": "SSRF - Decimal IP representation", + "config": { + "webhookUrl": "http://2130706433", + "webhookMethod": "GET" + }, + "result": false, + "err": [ + "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(https?:\\/\\/)(?![a-zA-Z0-9-]*\\.ngrok\\.io)(?!localhost|.*\\.localhost)([a-zA-Z0-9-]{1,63}\\.)+[a-zA-Z]{2,}(\\/.*)?$\"" + ] + }, + { + "testTitle": "SSRF - Octal IP representation", + "config": { + "webhookUrl": "http://0177.0000.0000.0001", + "webhookMethod": "GET" + }, + "result": false, + "err": [ + "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(https?:\\/\\/)(?![a-zA-Z0-9-]*\\.ngrok\\.io)(?!localhost|.*\\.localhost)([a-zA-Z0-9-]{1,63}\\.)+[a-zA-Z]{2,}(\\/.*)?$\"" + ] + }, + + { + "testTitle": "SSRF - IPv6 mapped IPv4 address", + "config": { + "webhookUrl": "http://[::ffff:192.168.0.1]", + "webhookMethod": "GET" + }, + "result": false, + "err": [ + "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(https?:\\/\\/)(?![a-zA-Z0-9-]*\\.ngrok\\.io)(?!localhost|.*\\.localhost)([a-zA-Z0-9-]{1,63}\\.)+[a-zA-Z]{2,}(\\/.*)?$\"" + ] + }, + { + "testTitle": "SSRF - Hexadecimal IP representation", + "config": { + "webhookUrl": "http://0xC0A80001", + "webhookMethod": "GET" + }, + "result": false, + "err": [ + "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(https?:\\/\\/)(?![a-zA-Z0-9-]*\\.ngrok\\.io)(?!localhost|.*\\.localhost)([a-zA-Z0-9-]{1,63}\\.)+[a-zA-Z]{2,}(\\/.*)?$\"" + ] + }, + { + "testTitle": "SSRF - Mixed encoding", + "config": { + "webhookUrl": "http://127.0.0.1%0d%0aHost:example.com", + "webhookMethod": "GET" + }, + "result": false, + "err": [ + "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(https?:\\/\\/)(?![a-zA-Z0-9-]*\\.ngrok\\.io)(?!localhost|.*\\.localhost)([a-zA-Z0-9-]{1,63}\\.)+[a-zA-Z]{2,}(\\/.*)?$\"" + ] + }, + { + "testTitle": "SSRF - Double encoding", + "config": { + "webhookUrl": "http://127.0.0.1%252f", + "webhookMethod": "GET" + }, + "result": false, + "err": [ + "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(https?:\\/\\/)(?![a-zA-Z0-9-]*\\.ngrok\\.io)(?!localhost|.*\\.localhost)([a-zA-Z0-9-]{1,63}\\.)+[a-zA-Z]{2,}(\\/.*)?$\"" + ] + }, + { + "testTitle": "SSRF - IPv6 compressed", + "config": { + "webhookUrl": "http://[::127.0.0.1]", + "webhookMethod": "GET" + }, + "result": false, + "err": [ + "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(https?:\\/\\/)(?![a-zA-Z0-9-]*\\.ngrok\\.io)(?!localhost|.*\\.localhost)([a-zA-Z0-9-]{1,63}\\.)+[a-zA-Z]{2,}(\\/.*)?$\"" + ] + }, + { + "testTitle": "SSRF - Enclosed alphanumerics", + "config": { + "webhookUrl": "http://⑫⑦.⓪.⓪.①", + "webhookMethod": "GET" + }, + "result": false, + "err": [ + "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(https?:\\/\\/)(?![a-zA-Z0-9-]*\\.ngrok\\.io)(?!localhost|.*\\.localhost)([a-zA-Z0-9-]{1,63}\\.)+[a-zA-Z]{2,}(\\/.*)?$\"" + ] + }, + { + "testTitle": "SSRF - Punycode domain", + "config": { + "webhookUrl": "http://xn--80ak6aa92e.com", + "webhookMethod": "GET" + }, + "result": true + }, + { + "testTitle": "SSRF - URL with credentials", + "config": { + "webhookUrl": "http://user:password@example.com", + "webhookMethod": "GET" + }, + "result": false, + "err": [ + "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(https?:\\/\\/)(?![a-zA-Z0-9-]*\\.ngrok\\.io)(?!localhost|.*\\.localhost)([a-zA-Z0-9-]{1,63}\\.)+[a-zA-Z]{2,}(\\/.*)?$\"" + ] + }, + { + "testTitle": "SSRF - Data URL scheme", + "config": { + "webhookUrl": "data:text/plain;base64,SGVsbG8sIFdvcmxkIQ==", + "webhookMethod": "GET" + }, + "result": false, + "err": [ + "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(https?:\\/\\/)(?![a-zA-Z0-9-]*\\.ngrok\\.io)(?!localhost|.*\\.localhost)([a-zA-Z0-9-]{1,63}\\.)+[a-zA-Z]{2,}(\\/.*)?$\"" + ] + }, + { + "testTitle": "SSRF - Localhost with subdomain", + "config": { + "webhookUrl": "http://subdomain.localhost", + "webhookMethod": "GET" + }, + "result": false, + "err": [ + "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(https?:\\/\\/)(?![a-zA-Z0-9-]*\\.ngrok\\.io)(?!localhost|.*\\.localhost)([a-zA-Z0-9-]{1,63}\\.)+[a-zA-Z]{2,}(\\/.*)?$\"" + ] + }, + { + "testTitle": "SSRF - localhost with dash", + "config": { + "webhookUrl": "http://local-host", + "webhookMethod": "GET" + }, + "result": false, + "err": [ + "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(https?:\\/\\/)(?![a-zA-Z0-9-]*\\.ngrok\\.io)(?!localhost|.*\\.localhost)([a-zA-Z0-9-]{1,63}\\.)+[a-zA-Z]{2,}(\\/.*)?$\"" + ] + }, + { + "testTitle": "SSRF - localhost with numbers", + "config": { + "webhookUrl": "http://127.0.0.1.nip.io", + "webhookMethod": "GET" + }, + "result": true + }, + { + "testTitle": "SSRF - Dotless decimal IP", + "config": { + "webhookUrl": "http://2130706433", + "webhookMethod": "GET" + }, + "result": false, + "err": [ + "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(https?:\\/\\/)(?![a-zA-Z0-9-]*\\.ngrok\\.io)(?!localhost|.*\\.localhost)([a-zA-Z0-9-]{1,63}\\.)+[a-zA-Z]{2,}(\\/.*)?$\"" + ] + }, + { + "testTitle": "SSRF - Dotless hex IP", + "config": { + "webhookUrl": "http://0x7f000001", + "webhookMethod": "GET" + }, + "result": false, + "err": [ + "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(https?:\\/\\/)(?![a-zA-Z0-9-]*\\.ngrok\\.io)(?!localhost|.*\\.localhost)([a-zA-Z0-9-]{1,63}\\.)+[a-zA-Z]{2,}(\\/.*)?$\"" + ] + }, + { + "testTitle": "SSRF - IPv6 localhost", + "config": { + "webhookUrl": "http://[::1]", + "webhookMethod": "GET" + }, + "result": false, + "err": [ + "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(https?:\\/\\/)(?![a-zA-Z0-9-]*\\.ngrok\\.io)(?!localhost|.*\\.localhost)([a-zA-Z0-9-]{1,63}\\.)+[a-zA-Z]{2,}(\\/.*)?$\"" + ] + }, + { + "testTitle": "SSRF - IPv6 localhost with zone identifier", + "config": { + "webhookUrl": "http://[::1%25en0]", + "webhookMethod": "GET" + }, + "result": false, + "err": [ + "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(https?:\\/\\/)(?![a-zA-Z0-9-]*\\.ngrok\\.io)(?!localhost|.*\\.localhost)([a-zA-Z0-9-]{1,63}\\.)+[a-zA-Z]{2,}(\\/.*)?$\"" + ] + }, + { + "testTitle": "SSRF - Malformed IPv6", + "config": { + "webhookUrl": "http://0:0:0:0:0:ffff:127.0.0.1", + "webhookMethod": "GET" + }, + "result": false, + "err": [ + "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(https?:\\/\\/)(?![a-zA-Z0-9-]*\\.ngrok\\.io)(?!localhost|.*\\.localhost)([a-zA-Z0-9-]{1,63}\\.)+[a-zA-Z]{2,}(\\/.*)?$\"" + ] + }, + { + "testTitle": "SSRF - IPv6 with IPv4 address", + "config": { + "webhookUrl": "http://[0:0:0:0:0:ffff:127.0.0.1]", + "webhookMethod": "GET" + }, + "result": false, + "err": [ + "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(https?:\\/\\/)(?![a-zA-Z0-9-]*\\.ngrok\\.io)(?!localhost|.*\\.localhost)([a-zA-Z0-9-]{1,63}\\.)+[a-zA-Z]{2,}(\\/.*)?$\"" + ] + }, + { + "testTitle": "SSRF - Exotic protocols", + "config": { + "webhookUrl": "gopher://example.com/_TCP:80", + "webhookMethod": "GET" + }, + "result": false, + "err": [ + "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(https?:\\/\\/)(?![a-zA-Z0-9-]*\\.ngrok\\.io)(?!localhost|.*\\.localhost)([a-zA-Z0-9-]{1,63}\\.)+[a-zA-Z]{2,}(\\/.*)?$\"" + ] + }, + { + "testTitle": "SSRF - URL fragment", + "config": { + "webhookUrl": "http://example.com#@evil.com/", + "webhookMethod": "GET" + }, + "result": false, + "err": [ + "webhookUrl must match pattern \"(^\\{\\{.*\\|\\|(.*)\\}\\}$)|(^env[.].+)|^(https?:\\/\\/)(?![a-zA-Z0-9-]*\\.ngrok\\.io)(?!localhost|.*\\.localhost)([a-zA-Z0-9-]{1,63}\\.)+[a-zA-Z]{2,}(\\/.*)?$\"" + ] } ]