perimeterx-js-core 0.26.2 → 0.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/lib/cjs/activities/HttpActivityClient.js +2 -2
  2. package/lib/cjs/activities/HttpBatchedActivityClient.js +2 -2
  3. package/lib/cjs/activities/utils.js +6 -3
  4. package/lib/cjs/additional_activity_handler/AdditionalActivityHandlerUtils.js +2 -2
  5. package/lib/cjs/config/ConfigurationBase.js +27 -5
  6. package/lib/cjs/config/defaults/DefaultConfigurationParams.js +1 -0
  7. package/lib/cjs/config/remote_config/manager/DefaultRemoteConfigManager.js +2 -2
  8. package/lib/cjs/config/remote_config/service_client/HttpRemoteConfigServiceClient.js +2 -2
  9. package/lib/cjs/config/remote_config/update_parser/DefaultNotifyRemoteConfigUpdateParser.js +2 -2
  10. package/lib/cjs/cors/DefaultCors.js +2 -2
  11. package/lib/cjs/custom_parameters/CustomParametersUtils.js +40 -2
  12. package/lib/cjs/enforcer/EnforcerBase.js +2 -2
  13. package/lib/cjs/flow/Flow.js +10 -6
  14. package/lib/cjs/graphql/DefaultGraphQLParser.js +7 -3
  15. package/lib/cjs/impl/cipher/CryptoCipherUtils.js +19 -9
  16. package/lib/cjs/impl/cipher/CryptoJsCipherUtils.js +2 -2
  17. package/lib/cjs/impl/cipher/SubtleCryptoCipherUtils.js +2 -2
  18. package/lib/cjs/impl/hash/CryptoHashUtils.js +19 -9
  19. package/lib/cjs/impl/hash/SubtleCryptoHashUtils.js +2 -2
  20. package/lib/cjs/impl/hmac/CryptoHmacUtils.js +17 -7
  21. package/lib/cjs/impl/hmac/SubtleCryptoHmacUtils.js +2 -2
  22. package/lib/cjs/impl/http/phin/PhinHttpClient.js +2 -2
  23. package/lib/cjs/impl/http/phin/PhinIncomingResponse.js +2 -2
  24. package/lib/cjs/logger/HttpLogServiceClient.js +2 -2
  25. package/lib/cjs/monitored_request/MonitoredRequestUtils.js +2 -2
  26. package/lib/cjs/phase/impl/AdditionalActivityHandlerPhase.js +2 -2
  27. package/lib/cjs/phase/impl/ClearLogsPhase.js +2 -2
  28. package/lib/cjs/phase/impl/CompositePhase.js +2 -2
  29. package/lib/cjs/phase/impl/CreateBlockResponsePhase.js +2 -2
  30. package/lib/cjs/phase/impl/DecideActionPhase.js +2 -2
  31. package/lib/cjs/phase/impl/EnrichContextFromRequestPhase.js +2 -2
  32. package/lib/cjs/phase/impl/EnrichContextFromResponsePhase.js +21 -2
  33. package/lib/cjs/phase/impl/FilterPhase.js +2 -2
  34. package/lib/cjs/phase/impl/FirstPartyPhase.js +2 -2
  35. package/lib/cjs/phase/impl/IdentifyRemoteConfigNotifyRequestPhase.js +2 -2
  36. package/lib/cjs/phase/impl/IdentifyTelemetryRequestPhase.js +2 -2
  37. package/lib/cjs/phase/impl/ModifyIncomingRequestPhase.js +2 -2
  38. package/lib/cjs/phase/impl/ModifyOutgoingResponsePhase.js +2 -2
  39. package/lib/cjs/phase/impl/ParseTokenPhase.js +2 -2
  40. package/lib/cjs/phase/impl/PreflightPhase.js +2 -2
  41. package/lib/cjs/phase/impl/RiskApiPhase.js +2 -2
  42. package/lib/cjs/phase/impl/SendAsyncActivitiesPhase.js +2 -2
  43. package/lib/cjs/phase/impl/SendLogsPhase.js +2 -2
  44. package/lib/cjs/phase/impl/SendTelemetryActivityPhase.js +2 -2
  45. package/lib/cjs/phase/impl/UpdateRemoteConfigPhase.js +2 -2
  46. package/lib/cjs/products/account_defender/AccountDefender.js +2 -2
  47. package/lib/cjs/products/bot_defender/BotDefender.js +2 -2
  48. package/lib/cjs/products/bot_defender/filter/DefaultBotDefenderFilter.js +2 -2
  49. package/lib/cjs/products/bot_defender/first_party/DefaultBotDefenderFirstParty.js +2 -2
  50. package/lib/cjs/products/credential_intelligence/CredentialIntelligence.js +2 -2
  51. package/lib/cjs/products/credential_intelligence/endpoint/CredentialEndpoint.js +2 -2
  52. package/lib/cjs/products/credential_intelligence/endpoint/CredentialEndpointManager.js +2 -2
  53. package/lib/cjs/products/credential_intelligence/endpoint/extractor/BodyCredentialExtractor.js +2 -2
  54. package/lib/cjs/products/credential_intelligence/endpoint/extractor/CustomCredentialExtractor.js +2 -2
  55. package/lib/cjs/products/credential_intelligence/endpoint/extractor/QueryParamCredentialExtractor.js +2 -2
  56. package/lib/cjs/products/credential_intelligence/endpoint/hash_protocol/MultistepHashProtocol.js +2 -2
  57. package/lib/cjs/products/credential_intelligence/endpoint/hash_protocol/SingleStepAndMultistepHashProtocol.js +2 -2
  58. package/lib/cjs/products/credential_intelligence/endpoint/hash_protocol/SingleStepHashProtocol.js +2 -2
  59. package/lib/cjs/products/credential_intelligence/endpoint/login_successful/BodyLoginSuccessfulParser.js +2 -2
  60. package/lib/cjs/products/credential_intelligence/endpoint/login_successful/CustomLoginSuccessfulParser.js +2 -2
  61. package/lib/cjs/products/credential_intelligence/endpoint/login_successful/HeaderLoginSuccessfulParser.js +2 -2
  62. package/lib/cjs/products/credential_intelligence/endpoint/login_successful/StatusLoginSuccessfulParser.js +2 -2
  63. package/lib/cjs/pxde/DefaultDataEnrichment.js +2 -2
  64. package/lib/cjs/risk_api/client/abstract/RiskApiClientBase.js +2 -2
  65. package/lib/cjs/risk_api/risk_response/PostRiskResponseBase.js +2 -2
  66. package/lib/cjs/risk_api/risk_response/RiskResponseBase.js +2 -2
  67. package/lib/cjs/risk_token/parser/TokenParserBase.js +2 -2
  68. package/lib/cjs/risk_token/token/TokenBase.js +2 -2
  69. package/lib/cjs/risk_token/token/v2/DefaultTokenV2.js +2 -2
  70. package/lib/cjs/risk_token/token/v3/DefaultTokenV3.js +2 -2
  71. package/lib/cjs/sensitive_request/SensitiveRequestUtils.js +2 -2
  72. package/lib/cjs/snippet_injection/snippet_retriever/DefaultSnippetRetriever.js +2 -2
  73. package/lib/cjs/telemetry/DefaultTelemetry.js +2 -2
  74. package/lib/cjs/utils/WaitsUntil.js +2 -2
  75. package/lib/cjs/utils/constants.js +1 -1
  76. package/lib/cjs/utils/timestamp_hmac_header_validator/DefaultTimestampHmacHeaderValidator.js +2 -2
  77. package/lib/cjs/utils/utils.js +2 -2
  78. package/lib/esm/activities/utils.js +5 -2
  79. package/lib/esm/config/ConfigurationBase.js +24 -5
  80. package/lib/esm/config/defaults/DefaultConfigurationParams.js +1 -0
  81. package/lib/esm/custom_parameters/CustomParametersUtils.js +28 -0
  82. package/lib/esm/flow/Flow.js +10 -6
  83. package/lib/esm/graphql/DefaultGraphQLParser.js +5 -1
  84. package/lib/esm/phase/impl/EnrichContextFromResponsePhase.js +5 -0
  85. package/lib/esm/utils/constants.js +1 -1
  86. package/lib/types/activities/utils.d.ts +2 -2
  87. package/lib/types/config/ConfigurationBase.d.ts +3 -1
  88. package/lib/types/config/IConfiguration.d.ts +5 -1
  89. package/lib/types/config/params/CoreConfigurationParams.d.ts +3 -2
  90. package/lib/types/context/interfaces/IContext.d.ts +8 -1
  91. package/lib/types/custom_parameters/CustomParameters.d.ts +20 -1
  92. package/lib/types/custom_parameters/CustomParametersFunction.d.ts +2 -1
  93. package/lib/types/custom_parameters/CustomParametersUtils.d.ts +3 -1
  94. package/lib/types/custom_parameters/index.d.ts +2 -2
  95. package/lib/types/flow/Flow.d.ts +4 -4
  96. package/lib/types/flow/IFlow.d.ts +8 -4
  97. package/lib/types/phase/impl/EnrichContextFromResponsePhase.d.ts +1 -0
  98. package/lib/types/utils/constants.d.ts +1 -1
  99. package/package.json +4 -3
@@ -9,8 +9,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  var __generator = (this && this.__generator) || function (thisArg, body) {
12
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
13
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
14
  function verb(n) { return function (v) { return step([n, v]); }; }
15
15
  function step(op) {
16
16
  if (f) throw new TypeError("Generator is already executing.");
@@ -9,8 +9,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  var __generator = (this && this.__generator) || function (thisArg, body) {
12
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
13
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
14
  function verb(n) { return function (v) { return step([n, v]); }; }
15
15
  function step(op) {
16
16
  if (f) throw new TypeError("Generator is already executing.");
@@ -9,8 +9,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  var __generator = (this && this.__generator) || function (thisArg, body) {
12
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
13
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
14
  function verb(n) { return function (v) { return step([n, v]); }; }
15
15
  function step(op) {
16
16
  if (f) throw new TypeError("Generator is already executing.");
@@ -9,8 +9,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  var __generator = (this && this.__generator) || function (thisArg, body) {
12
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
13
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
14
  function verb(n) { return function (v) { return step([n, v]); }; }
15
15
  function step(op) {
16
16
  if (f) throw new TypeError("Generator is already executing.");
@@ -14,4 +14,4 @@ exports.PUSH_DATA_FEATURE_HEADER_NAME = 'x-px-feature';
14
14
  exports.EMAIL_ADDRESS_REGEX = /^[a-zA-Z0-9_+&*-]+(?:\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\.)+[a-zA-Z]{2,7}$/;
15
15
  exports.URL_REGEX = /^(https?:)\/\/(([^@\s:\/]+):?([^@\s\/]*)@)?(([^:\/?#]*)(?:\:([0-9]+))?)(\/?[^?#]*)(\?[^#]*|)(#.*|)$/;
16
16
  exports.REGEX_STRUCTURE = /^\/(.+?)\/([gimsuyvd]*)$/;
17
- exports.CORE_MODULE_VERSION = 'JS Core 0.26.2';
17
+ exports.CORE_MODULE_VERSION = 'JS Core 0.28.0';
@@ -9,8 +9,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  var __generator = (this && this.__generator) || function (thisArg, body) {
12
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
13
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
14
  function verb(n) { return function (v) { return step([n, v]); }; }
15
15
  function step(op) {
16
16
  if (f) throw new TypeError("Generator is already executing.");
@@ -9,8 +9,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  var __generator = (this && this.__generator) || function (thisArg, body) {
12
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
13
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
14
  function verb(n) { return function (v) { return step([n, v]); }; }
15
15
  function step(op) {
16
16
  if (f) throw new TypeError("Generator is already executing.");
@@ -70,7 +70,7 @@ export const createCommonActivityDetails = (config, context) => {
70
70
  addProductDataToDetails(details, context.productData);
71
71
  addServerDataToDetails(details, context.serverData);
72
72
  addTlsDataToDetails(details, context.tlsData);
73
- addCustomParametersToDetails(details, context.customParameters ?? null);
73
+ addCustomParametersToDetails(details, context.customParameters ?? null, context.responseCustomParameters ?? null);
74
74
  return details;
75
75
  };
76
76
  export const addRootContextDataToDetails = (details, context) => {
@@ -104,10 +104,13 @@ export const addConfigDataToDetails = (details, config) => {
104
104
  details.remote_config_version = config.remoteConfigVersion;
105
105
  }
106
106
  };
107
- export const addCustomParametersToDetails = (details, customParameters) => {
107
+ export const addCustomParametersToDetails = (details, customParameters, responseCustomParameters) => {
108
108
  if (customParameters) {
109
109
  Object.assign(details, customParameters);
110
110
  }
111
+ if (responseCustomParameters) {
112
+ Object.assign(details, responseCustomParameters);
113
+ }
111
114
  };
112
115
  export const addProductDataToDetails = (details, productData) => {
113
116
  if (productData.ad) {
@@ -1,6 +1,6 @@
1
1
  import { defaultConfigurationParams } from './defaults/index.js';
2
2
  import { DefaultLogger, LoggerSeverity } from '../logger/index.js';
3
- import { CORE_MODULE_VERSION, EnforcerConfigurationError, getCollectorDomain, getScoreApiDomain, isNullOrUndefined, isValidEnumValue, ModuleMode, } from '../utils/index.js';
3
+ import { convertRegexStringToRegex, CORE_MODULE_VERSION, EnforcerConfigurationError, getCollectorDomain, getScoreApiDomain, isNullOrUndefined, isValidEnumValue, ModuleMode, } from '../utils/index.js';
4
4
  import { RemoteConfigUtils } from './remote_config/index.js';
5
5
  import { TokenVersion } from '../risk_token/index.js';
6
6
  /**
@@ -46,9 +46,8 @@ export class ConfigurationBase {
46
46
  });
47
47
  }
48
48
  getValidConfigValue(params, defaultParams, key) {
49
- const paramsValue = params[key];
50
- if (!isNullOrUndefined(paramsValue) && this.isValidConfigValue(params, defaultParams, key)) {
51
- return paramsValue;
49
+ if (!isNullOrUndefined(params[key]) && this.isValidConfigValue(params, defaultParams, key)) {
50
+ return this.normalizeConfigurationValue(params, key);
52
51
  }
53
52
  else {
54
53
  return this.getDefaultConfigurationValue(params, defaultParams, key);
@@ -84,6 +83,23 @@ export class ConfigurationBase {
84
83
  return defaultParams[key];
85
84
  }
86
85
  }
86
+ normalizeConfigurationValue(params, key) {
87
+ switch (key) {
88
+ case 'px_filter_by_extension':
89
+ return params[key].map((ext) => (ext.startsWith('.') ? ext : `.${ext}`));
90
+ case 'px_sensitive_routes':
91
+ case 'px_monitored_routes':
92
+ case 'px_enforced_routes':
93
+ case 'px_graphql_routes':
94
+ case 'px_filter_by_route':
95
+ case 'px_filter_by_user_agent':
96
+ case 'px_graphql_keywords':
97
+ case 'px_sensitive_graphql_operation_names':
98
+ return params[key].map((pattern) => typeof pattern === 'string' ? (convertRegexStringToRegex(pattern) ?? pattern) : pattern);
99
+ default:
100
+ return params[key];
101
+ }
102
+ }
87
103
  createInternalLogger(params) {
88
104
  return new DefaultLogger(params.px_logger_severity, false, this.logger?.getLogs());
89
105
  }
@@ -148,7 +164,7 @@ export class ConfigurationBase {
148
164
  return this.configParams.px_custom_is_enforced_request;
149
165
  }
150
166
  get filteredExtensions() {
151
- return this.configParams.px_filter_by_extension?.map((ext) => (ext.startsWith('.') ? ext : `.${ext}`));
167
+ return this.configParams.px_filter_by_extension;
152
168
  }
153
169
  get filteredHttpMethods() {
154
170
  return this.configParams.px_filter_by_http_method;
@@ -273,6 +289,9 @@ export class ConfigurationBase {
273
289
  get enrichCustomParameters() {
274
290
  return this.configParams.px_enrich_custom_parameters;
275
291
  }
292
+ get enrichResponseCustomParameters() {
293
+ return this.configParams.px_enrich_response_custom_parameters;
294
+ }
276
295
  get additionalActivityHandler() {
277
296
  return this.configParams.px_additional_activity_handler;
278
297
  }
@@ -113,6 +113,7 @@ export const defaultConfigurationParams = () => ({
113
113
  px_sensitive_graphql_operation_names: [],
114
114
  px_sensitive_graphql_operation_types: [],
115
115
  px_enrich_custom_parameters: null,
116
+ px_enrich_response_custom_parameters: null,
116
117
  px_jwt_cookie_name: '',
117
118
  px_jwt_cookie_user_id_field_name: '',
118
119
  px_jwt_cookie_additional_field_names: [],
@@ -13,6 +13,22 @@ export var CustomParametersUtils;
13
13
  }
14
14
  return null;
15
15
  };
16
+ CustomParametersUtils.createResponseCustomParameters = async (config, context) => {
17
+ if (config.enrichResponseCustomParameters && typeof config.enrichResponseCustomParameters === 'function') {
18
+ try {
19
+ if (!context.response) {
20
+ context.logger.debug('no response available for response custom parameters');
21
+ return null;
22
+ }
23
+ const parameters = await config.enrichResponseCustomParameters(config.getActiveConfig(), context.response.getUnderlyingResponse());
24
+ return CustomParametersUtils.normalizeResponseCustomParams(parameters);
25
+ }
26
+ catch (e) {
27
+ context.logger.error(`unable to enrich response custom params: ${e}`);
28
+ }
29
+ }
30
+ return null;
31
+ };
16
32
  CustomParametersUtils.normalizeCustomParams = (customParameters) => {
17
33
  const normalizedParams = {};
18
34
  if (customParameters && typeof customParameters === 'object') {
@@ -29,4 +45,16 @@ export var CustomParametersUtils;
29
45
  }
30
46
  return Object.keys(normalizedParams).length === 0 ? null : normalizedParams;
31
47
  };
48
+ CustomParametersUtils.normalizeResponseCustomParams = (customParameters) => {
49
+ const normalizedParams = {};
50
+ if (customParameters && typeof customParameters === 'object') {
51
+ const paramKeyRegex = /^custom_param(1[1-9]|20)$/;
52
+ Object.entries(customParameters).forEach(([param, value]) => {
53
+ if (param.match(paramKeyRegex) && value !== '') {
54
+ normalizedParams[param] = value;
55
+ }
56
+ });
57
+ }
58
+ return Object.keys(normalizedParams).length === 0 ? null : normalizedParams;
59
+ };
32
60
  })(CustomParametersUtils || (CustomParametersUtils = {}));
@@ -7,45 +7,49 @@ export class Flow {
7
7
  insert(phase, options) {
8
8
  if (!options) {
9
9
  this.phases.push(phase);
10
- return;
10
+ return this;
11
11
  }
12
12
  if (options.before) {
13
13
  const index = this.getIndexOfPhase(options.before);
14
14
  if (index === -1) {
15
- return;
15
+ return this;
16
16
  }
17
17
  this.phases.splice(index, 0, phase);
18
18
  }
19
19
  if (options.after) {
20
20
  const index = this.getIndexOfPhase(options.after);
21
21
  if (index === -1) {
22
- return;
22
+ return this;
23
23
  }
24
24
  this.phases.splice(index + 1, 0, phase);
25
25
  }
26
+ return this;
26
27
  }
27
28
  remove(name) {
28
29
  const index = this.getIndexOfPhase(name);
29
30
  if (index === -1) {
30
- return;
31
+ return this;
31
32
  }
32
33
  this.phases.splice(index, 1);
34
+ return this;
33
35
  }
34
36
  replace(name, phase) {
35
37
  const index = this.getIndexOfPhase(name);
36
38
  if (index === -1) {
37
- return;
39
+ return this;
38
40
  }
39
41
  this.phases.splice(index, 1, phase);
42
+ return this;
40
43
  }
41
44
  move(name, to) {
42
45
  const index = this.getIndexOfPhase(name);
43
46
  if (index === -1) {
44
- return;
47
+ return this;
45
48
  }
46
49
  const phase = this.phases[index];
47
50
  this.phases.splice(index, 1);
48
51
  this.insert(phase, to);
52
+ return this;
49
53
  }
50
54
  getIndexOfPhase(name) {
51
55
  return this.phases.findIndex((existingPhase) => existingPhase.constructor.name === name);
@@ -147,11 +147,15 @@ export class DefaultGraphQLParser {
147
147
  }
148
148
  }
149
149
  getQueryKeywordsFromArray(query, context) {
150
+ if (!query) {
151
+ context.logger.debug(`empty query, unable to extract graphql keywords`);
152
+ return [];
153
+ }
150
154
  let keywords = [];
151
155
  try {
152
156
  this.config.graphqlKeywords.forEach((keyword) => {
153
157
  const pattern = this.toGlobalRegExp(keyword);
154
- let matchGroup = query?.match(pattern);
158
+ let matchGroup = query.match(pattern);
155
159
  if (!matchGroup) {
156
160
  return;
157
161
  }
@@ -1,4 +1,5 @@
1
1
  import { isNullOrUndefined } from '../../utils/index.js';
2
+ import { CustomParametersUtils } from '../../custom_parameters/index.js';
2
3
  /**
3
4
  * `EnrichContextFromResponsePhase` enriches the context with response data. Each product's `enrichContextFromResponse`
4
5
  * method is called since every product may use the response data differently.
@@ -13,6 +14,7 @@ export class EnrichContextFromResponsePhase {
13
14
  async execute(context) {
14
15
  context.logger.debug('enrich context from response phase');
15
16
  await this.addProductDataToContext(context);
17
+ await this.addResponseCustomParametersToContext(context);
16
18
  return { done: false };
17
19
  }
18
20
  async addProductDataToContext(context) {
@@ -23,4 +25,7 @@ export class EnrichContextFromResponsePhase {
23
25
  }
24
26
  }));
25
27
  }
28
+ async addResponseCustomParametersToContext(context) {
29
+ context.responseCustomParameters = await CustomParametersUtils.createResponseCustomParameters(this.config, context);
30
+ }
26
31
  }
@@ -11,4 +11,4 @@ export const PUSH_DATA_FEATURE_HEADER_NAME = 'x-px-feature';
11
11
  export const EMAIL_ADDRESS_REGEX = /^[a-zA-Z0-9_+&*-]+(?:\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\.)+[a-zA-Z]{2,7}$/;
12
12
  export const URL_REGEX = /^(https?:)\/\/(([^@\s:\/]+):?([^@\s\/]*)@)?(([^:\/?#]*)(?:\:([0-9]+))?)(\/?[^?#]*)(\?[^#]*|)(#.*|)$/;
13
13
  export const REGEX_STRUCTURE = /^\/(.+?)\/([gimsuyvd]*)$/;
14
- export const CORE_MODULE_VERSION = 'JS Core 0.26.2';
14
+ export const CORE_MODULE_VERSION = 'JS Core 0.28.0';
@@ -4,7 +4,7 @@ import { IConfiguration } from '../config';
4
4
  import { ProductData } from '../products';
5
5
  import { ActivityType } from './ActivityType';
6
6
  import { AdditionalS2SActivityDetails, AsyncActivity, AsyncActivityCommonDetails, AsyncActivityDetails, BlockActivityDetails, CommonActivityDetails, HeaderEntry, PageRequestedActivityDetails } from './model';
7
- import { CustomParameters } from '../custom_parameters';
7
+ import { CustomParameters, ResponseCustomParameters } from '../custom_parameters';
8
8
  /**
9
9
  * Creates an async activity object based on the provided parameters.
10
10
  * @param activityType - The activity type to create.
@@ -26,7 +26,7 @@ export declare const createCommonActivityDetails: <Req, Res, Added, Removed>(con
26
26
  export declare const addRootContextDataToDetails: <Req, Res>(details: CommonActivityDetails, context: ReadonlyContext<Req, Res>) => void;
27
27
  export declare function redactCookieSecret(secret: string): string;
28
28
  export declare const addConfigDataToDetails: <Req, Res, Added, Removed>(details: CommonActivityDetails, config: IConfiguration<Req, Res, Added, Removed>) => void;
29
- export declare const addCustomParametersToDetails: (details: CommonActivityDetails, customParameters: CustomParameters | null) => void;
29
+ export declare const addCustomParametersToDetails: (details: CommonActivityDetails, customParameters: CustomParameters | null, responseCustomParameters: ResponseCustomParameters | null) => void;
30
30
  export declare const addProductDataToDetails: (details: CommonActivityDetails, productData: DeepReadonly<ProductData>) => void;
31
31
  export declare const addTlsDataToDetails: (details: CommonActivityDetails, tlsData: DeepReadonly<TlsData>) => void;
32
32
  export declare const addServerDataToDetails: (details: CommonActivityDetails, serverData: DeepReadonly<ServerData>) => void;
@@ -1,6 +1,6 @@
1
1
  import { IConfiguration } from './IConfiguration';
2
2
  import { RemoteConfigurationParams, StaticConfigurationParams, AllConfigurationParams, RequiredAllConfigurationParams, ActiveConfigurationParams, CoreConfigurationParams } from './params';
3
- import { CustomParametersFunction } from '../custom_parameters';
3
+ import { CustomParametersFunction, ResponseCustomParametersFunction } from '../custom_parameters';
4
4
  import { AdditionalActivityHandler } from '../additional_activity_handler';
5
5
  import { ILogger, LoggerSeverity } from '../logger';
6
6
  import { CustomBlockResponseHeadersHandler, CustomPreflightHandler } from '../cors';
@@ -46,6 +46,7 @@ export declare abstract class ConfigurationBase<Req, Res, Added, Removed extends
46
46
  protected getValidConfigValue<K extends keyof RequiredAllConfigurationParams<Req, Res, Added, Removed>, V extends RequiredAllConfigurationParams<Req, Res, Added, Removed>[K]>(params: AllConfigurationParams<Req, Res, Added, Removed>, defaultParams: RequiredAllConfigurationParams<Req, Res, Added, Removed>, key: K): V;
47
47
  protected isValidConfigValue(params: AllConfigurationParams<Req, Res, Added, Removed>, defaultParams: RequiredAllConfigurationParams<Req, Res, Added, Removed>, key: keyof RequiredAllConfigurationParams<Req, Res, Added, Removed>): boolean;
48
48
  protected getDefaultConfigurationValue<K extends keyof RequiredAllConfigurationParams<Req, Res, Added, Removed>, V extends RequiredAllConfigurationParams<Req, Res, Added, Removed>[K]>(params: AllConfigurationParams<Req, Res, Added, Removed>, defaultParams: RequiredAllConfigurationParams<Req, Res, Added, Removed>, key: K): V;
49
+ protected normalizeConfigurationValue<K extends keyof RequiredAllConfigurationParams<Req, Res, Added, Removed>, V extends RequiredAllConfigurationParams<Req, Res, Added, Removed>[K]>(params: AllConfigurationParams<Req, Res, Added, Removed>, key: K): V;
49
50
  protected createInternalLogger(params: RequiredAllConfigurationParams<Req, Res, Added, Removed>): ILogger;
50
51
  setRemoteConfigData(remoteConfigData: RemoteConfigData<Req, Res, Added, Removed>): void;
51
52
  getActiveConfig(): ActiveConfigurationParams<Req, Res, Added, Removed>;
@@ -104,6 +105,7 @@ export declare abstract class ConfigurationBase<Req, Res, Added, Removed extends
104
105
  get sensitiveGraphqlOperationNames(): Array<string | RegExp>;
105
106
  get sensitiveGraphqlOperationTypes(): string[];
106
107
  get enrichCustomParameters(): CustomParametersFunction<Req, Res, Added, Removed> | null;
108
+ get enrichResponseCustomParameters(): ResponseCustomParametersFunction<Req, Res, Added, Removed> | null;
107
109
  get additionalActivityHandler(): AdditionalActivityHandler<Req, Res, Added, Removed> | null;
108
110
  get altBackendCaptchaUrl(): string;
109
111
  get corsSupportEnabled(): boolean;
@@ -1,6 +1,6 @@
1
1
  import { ModuleMode } from '../utils';
2
2
  import { ILogger, LoggerSeverity } from '../logger';
3
- import { CustomParametersFunction } from '../custom_parameters';
3
+ import { CustomParametersFunction, ResponseCustomParametersFunction } from '../custom_parameters';
4
4
  import { AdditionalActivityHandler } from '../additional_activity_handler';
5
5
  import { ActiveConfigurationParams, RemoteConfigurationParams, StaticConfigurationParams } from './params';
6
6
  import { CustomBlockResponseHeadersHandler, CustomPreflightHandler } from '../cors';
@@ -243,6 +243,10 @@ export interface IConfiguration<Req, Res, Added, Removed> {
243
243
  * A function returning CustomParameters that will be added to the enforcer activities.
244
244
  */
245
245
  readonly enrichCustomParameters: CustomParametersFunction<Req, Res, Added, Removed> | null;
246
+ /**
247
+ * A function returning ResponseCustomParameters that will be added to the enforcer activities.
248
+ */
249
+ readonly enrichResponseCustomParameters: ResponseCustomParametersFunction<Req, Res, Added, Removed> | null;
246
250
  /**
247
251
  * A function that will be called after the asynchronous activities are sent to the backend.
248
252
  */
@@ -3,13 +3,13 @@ import { ModuleMode } from '../../utils';
3
3
  import { CredentialEndpointConfiguration, CredentialIntelligenceVersion, CustomLoginSuccessfulCallback, LoginSuccessfulReportingMethod } from '../../products';
4
4
  import { GraphQLOperationType, ExtractGraphQLKeywordsFunction } from '../../graphql';
5
5
  import { AdditionalActivityHandler } from '../../additional_activity_handler';
6
- import { CustomParametersFunction } from '../../custom_parameters';
6
+ import { CustomParametersFunction, ResponseCustomParametersFunction } from '../../custom_parameters';
7
7
  import { CustomBlockResponseHeadersHandler, CustomPreflightHandler } from '../../cors';
8
8
  import { CustomRequestFunction } from '../CustomRequestFunction';
9
9
  import { TokenVersion } from '../../risk_token';
10
10
  import { CustomSnippetFunction } from '../../snippet_injection';
11
11
  /**
12
- * The configuration parameters that can be set only via the static configuration..
12
+ * The configuration parameters that can be set only via the static configuration.
13
13
  */
14
14
  export type StaticConfigurationParamsOnly = {
15
15
  px_app_id: string;
@@ -121,6 +121,7 @@ export type CommonConfigurationParams<Req, Res, Added, Removed> = TokenV3Configu
121
121
  px_secured_pxhd_enabled?: boolean;
122
122
  px_additional_activity_handler?: AdditionalActivityHandler<Req, Res, Added, Removed> | null;
123
123
  px_enrich_custom_parameters?: CustomParametersFunction<Req, Res, Added, Removed> | null;
124
+ px_enrich_response_custom_parameters?: ResponseCustomParametersFunction<Req, Res, Added, Removed> | null;
124
125
  px_login_successful_custom_callback?: CustomLoginSuccessfulCallback<Res> | null;
125
126
  px_cors_custom_preflight_handler?: CustomPreflightHandler<Req> | null;
126
127
  px_cors_create_custom_block_response_headers?: CustomBlockResponseHeadersHandler<Req> | null;
@@ -1,6 +1,6 @@
1
1
  import { VidSource } from '../../utils';
2
2
  import { BlockAction } from '../../blocker';
3
- import { CustomParameters } from '../../custom_parameters';
3
+ import { CustomParameters, ResponseCustomParameters } from '../../custom_parameters';
4
4
  import { PXDE } from '../../pxde';
5
5
  import { TokenOrigin } from '../../risk_token';
6
6
  import { RequestData } from './RequestData';
@@ -109,6 +109,13 @@ export interface IContext<Req, Res> {
109
109
  * custom parameters will be added to the activities sent to the collector.
110
110
  */
111
111
  customParameters?: CustomParameters | null;
112
+ /**
113
+ * An object with 10 additional custom parameters (11-20) that the customer can set and define
114
+ * based on the response from the origin. These custom parameters will be added to all async
115
+ * activities sent to the collector, including page_requested, (simulated) block,
116
+ * and additional_s2s activities.
117
+ */
118
+ responseCustomParameters?: ResponseCustomParameters | null;
112
119
  /**
113
120
  * An array of objects with information about the different GraphQL operations
114
121
  * parsed from the request.
@@ -1,6 +1,8 @@
1
1
  import { IS_HYPESALE_PARAM_NAME } from '../products';
2
2
  /**
3
- * Custom parameters defined by the user and included on all HUMAN backend requests.
3
+ * Custom parameters (1-10) defined by the user that will be added to all activities sent to HUMAN backend,
4
+ * including page_requested, block (and simulated block), and additional_s2s activities.
5
+ * These parameters are extracted from the incoming request.
4
6
  */
5
7
  export type CustomParameters = {
6
8
  custom_param1?: any;
@@ -15,3 +17,20 @@ export type CustomParameters = {
15
17
  custom_param10?: any;
16
18
  [IS_HYPESALE_PARAM_NAME]?: boolean;
17
19
  };
20
+ /**
21
+ * Response-based custom parameters (11-20) defined by the user that will be added to all async activities sent to HUMAN backend,
22
+ * including page_requested, simulated block, and additional_s2s activities.
23
+ * These parameters are extracted from the origin response after it has been received.
24
+ */
25
+ export type ResponseCustomParameters = {
26
+ custom_param11?: any;
27
+ custom_param12?: any;
28
+ custom_param13?: any;
29
+ custom_param14?: any;
30
+ custom_param15?: any;
31
+ custom_param16?: any;
32
+ custom_param17?: any;
33
+ custom_param18?: any;
34
+ custom_param19?: any;
35
+ custom_param20?: any;
36
+ };
@@ -1,3 +1,4 @@
1
- import { CustomParameters } from './CustomParameters';
1
+ import { CustomParameters, ResponseCustomParameters } from './CustomParameters';
2
2
  import { ActiveConfigurationParams } from '../config';
3
3
  export type CustomParametersFunction<Req, Res, Added, Removed> = (config: ActiveConfigurationParams<Req, Res, Added, Removed>, request: Req) => CustomParameters | Promise<CustomParameters>;
4
+ export type ResponseCustomParametersFunction<Req, Res, Added, Removed> = (config: ActiveConfigurationParams<Req, Res, Added, Removed>, response: Res) => ResponseCustomParameters | Promise<ResponseCustomParameters>;
@@ -1,7 +1,9 @@
1
1
  import { IConfiguration } from '../config';
2
2
  import { ReadonlyContext } from '../context';
3
- import { CustomParameters } from './CustomParameters';
3
+ import { CustomParameters, ResponseCustomParameters } from './CustomParameters';
4
4
  export declare namespace CustomParametersUtils {
5
5
  const createCustomParameters: <Req, Res, Added, Removed>(config: IConfiguration<Req, Res, Added, Removed>, context: ReadonlyContext<Req, Res>) => Promise<CustomParameters | null>;
6
+ const createResponseCustomParameters: <Req, Res, Added, Removed>(config: IConfiguration<Req, Res, Added, Removed>, context: ReadonlyContext<Req, Res>) => Promise<ResponseCustomParameters | null>;
6
7
  const normalizeCustomParams: (customParameters: Record<string, any>) => CustomParameters | null;
8
+ const normalizeResponseCustomParams: (customParameters: Record<string, any>) => ResponseCustomParameters | null;
7
9
  }
@@ -1,3 +1,3 @@
1
- export { CustomParameters } from './CustomParameters';
1
+ export { CustomParameters, ResponseCustomParameters } from './CustomParameters';
2
+ export { CustomParametersFunction, ResponseCustomParametersFunction } from './CustomParametersFunction';
2
3
  export { CustomParametersUtils } from './CustomParametersUtils';
3
- export { CustomParametersFunction } from './CustomParametersFunction';
@@ -4,10 +4,10 @@ import { IFlow, InsertPhaseOptions } from './IFlow';
4
4
  export declare class Flow<Req, Res> implements IFlow<Req, Res> {
5
5
  readonly phases: IPhase<Req, Res>[];
6
6
  constructor(phases: IPhase<Req, Res>[]);
7
- insert(phase: IPhase<Req, Res>, options?: InsertPhaseOptions): void;
8
- remove(name: string): void;
9
- replace(name: string, phase: IPhase<Req, Res>): void;
10
- move(name: string, to: InsertPhaseOptions): void;
7
+ insert(phase: IPhase<Req, Res>, options?: InsertPhaseOptions): IFlow<Req, Res>;
8
+ remove(name: string): IFlow<Req, Res>;
9
+ replace(name: string, phase: IPhase<Req, Res>): IFlow<Req, Res>;
10
+ move(name: string, to: InsertPhaseOptions): IFlow<Req, Res>;
11
11
  protected getIndexOfPhase(name: string): number;
12
12
  execute(context: IContext<Req, Res>): Promise<PhaseResult>;
13
13
  }
@@ -34,24 +34,28 @@ export interface IFlow<Req, Res> extends IPhase<Req, Res> {
34
34
  * Replaces the named phase in the flow with the provided phase. If the named phase is not found, nothing happens.
35
35
  * @param name - The name of the phase to replace. A phase with this name should exist in the flow already.
36
36
  * @param phase - The phase that should replace the named phase.
37
+ * @returns The flow instance itself for chaining.
37
38
  */
38
- replace(name: string, phase: IPhase<Req, Res>): void;
39
+ replace(name: string, phase: IPhase<Req, Res>): IFlow<Req, Res>;
39
40
  /**
40
41
  * Removes the named phase from the flow. If the named phase is not found, does nothing.
41
42
  * @param name - The name of the phase to remove. A phase with this name should exist in the flow already.
43
+ * @returns The flow instance itself for chaining.
42
44
  */
43
- remove(name: string): void;
45
+ remove(name: string): IFlow<Req, Res>;
44
46
  /**
45
47
  * Inserts the provided phase into the flow at the specified position. If no position is specified,
46
48
  * the phase will be added to the very end of the flow.
47
49
  * @param phase - The phase to insert into the flow.
48
50
  * @param options - The options for inserting the phase. If no options are provided, the phase will be added to the end of the flow.
51
+ * @returns The flow instance itself for chaining.
49
52
  */
50
- insert(phase: IPhase<Req, Res>, options?: InsertPhaseOptions): void;
53
+ insert(phase: IPhase<Req, Res>, options?: InsertPhaseOptions): IFlow<Req, Res>;
51
54
  /**
52
55
  * Moves the named phase to the specified position in the flow. If the named phase is not found, nothing happens.
53
56
  * @param name - The name of the phase to move. A phase with this name should exist in the flow already.
54
57
  * @param to - The options for moving the phase. The phase will be moved to the specified position in the flow.
58
+ * @returns The flow instance itself for chaining.
55
59
  */
56
- move(name: string, to: InsertPhaseOptions): void;
60
+ move(name: string, to: InsertPhaseOptions): IFlow<Req, Res>;
57
61
  }
@@ -13,4 +13,5 @@ export declare class EnrichContextFromResponsePhase<Req, Res, Added, Removed> im
13
13
  constructor(config: IConfiguration<Req, Res, Added, Removed>, products: Products<Req, Res>);
14
14
  execute(context: IContext<Req, Res>): Promise<PhaseResult>;
15
15
  protected addProductDataToContext(context: IContext<Req, Res>): Promise<void>;
16
+ protected addResponseCustomParametersToContext(context: IContext<Req, Res>): Promise<void>;
16
17
  }
@@ -11,4 +11,4 @@ export declare const PUSH_DATA_FEATURE_HEADER_NAME = "x-px-feature";
11
11
  export declare const EMAIL_ADDRESS_REGEX: RegExp;
12
12
  export declare const URL_REGEX: RegExp;
13
13
  export declare const REGEX_STRUCTURE: RegExp;
14
- export declare const CORE_MODULE_VERSION = "JS Core 0.26.2";
14
+ export declare const CORE_MODULE_VERSION = "JS Core 0.28.0";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "perimeterx-js-core",
3
- "version": "0.26.2",
3
+ "version": "0.28.0",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "typesVersions": {
@@ -55,6 +55,7 @@
55
55
  "@types/chai-as-promised": "^8.0.2",
56
56
  "@types/crypto-js": "^4.1.1",
57
57
  "@types/mocha": "^10.0.0",
58
+ "@types/node": "^18.19.50 || ^20.6.0 || ^22.0.0",
58
59
  "@types/sinon": "^17.0.1",
59
60
  "@types/uuid": "^10.0.0",
60
61
  "@typescript-eslint/eslint-plugin": "^8.26.0",
@@ -66,11 +67,11 @@
66
67
  "eslint-config-prettier": "^10.0.2",
67
68
  "eslint-plugin-prettier": "^5.2.3",
68
69
  "husky": "^9.1.7",
69
- "lint-staged": "^15.4.3",
70
+ "lint-staged": "^16.0.0",
70
71
  "mocha": "^10.0.0",
71
72
  "nyc": "^17.0.0",
72
73
  "prettier": "^3.5.3",
73
- "sinon": "^18.0.0",
74
+ "sinon": "^20.0.0",
74
75
  "ts-loader": "^9.4.1",
75
76
  "ts-node": "^10.9.1",
76
77
  "tsc-alias": "^1.8.11",