@adobe/spacecat-shared-data-access 4.15.0 → 4.15.1

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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## [@adobe/spacecat-shared-data-access-v4.15.1](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-data-access-v4.15.0...@adobe/spacecat-shared-data-access-v4.15.1) (2026-07-29)
2
+
3
+ ### Bug Fixes
4
+
5
+ * validate cdnlogsFilter key against a column allowlist in site config ([#1851](https://github.com/adobe/spacecat-shared/issues/1851)) ([46a0408](https://github.com/adobe/spacecat-shared/commit/46a0408b852fa6f6483fc2ad81c3ce1a8d0c615d)), closes [adobe/spacecat-audit-worker#2826](https://github.com/adobe/spacecat-audit-worker/issues/2826)
6
+
1
7
  ## [@adobe/spacecat-shared-data-access-v4.15.0](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-data-access-v4.14.0...@adobe/spacecat-shared-data-access-v4.15.0) (2026-07-29)
2
8
 
3
9
  ### Features
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/spacecat-shared-data-access",
3
- "version": "4.15.0",
3
+ "version": "4.15.1",
4
4
  "description": "Shared modules of the Spacecat Services - Data Access",
5
5
  "type": "module",
6
6
  "engines": {
@@ -70,6 +70,30 @@ const RESERVED_SCRAPER_HEADER_NAMES = new Set([
70
70
 
71
71
  const LLMO_TAG_PATTERN = /^(market|product|topic):\s?.+/;
72
72
  const AWS_REGION_PATTERN = /^[a-z]{2}(?:-[a-z]+)+-\d+$/i;
73
+
74
+ // Columns on the CDN log tables that a cdnlogsFilter entry is allowed to target.
75
+ // `key` is interpolated (unquoted) into Athena SQL by the audit worker's
76
+ // buildSiteFilters(), so it MUST be constrained to this allowlist to prevent SQL
77
+ // injection (VULN-37491). Keep in sync with ALLOWED_FILTER_KEYS in
78
+ // spacecat-audit-worker/src/utils/cdn-utils.js.
79
+ export const CDN_LOGS_FILTER_KEYS = [
80
+ 'url',
81
+ 'host',
82
+ 'x_forwarded_host',
83
+ 'user_agent',
84
+ 'referer',
85
+ 'cdn_provider',
86
+ ];
87
+
88
+ const CDN_LOGS_FILTER_SCHEMA = Joi.array().items(
89
+ Joi.object({
90
+ // Athena folds column identifiers to lowercase; normalize before matching
91
+ // the allowlist so a stored 'X_forwarded_host' is accepted as the same column.
92
+ key: Joi.string().lowercase().valid(...CDN_LOGS_FILTER_KEYS).required(),
93
+ value: Joi.array().items(Joi.string()).required(),
94
+ type: Joi.string().valid('include', 'exclude').optional(),
95
+ }),
96
+ );
73
97
  const LLMO_TAG = Joi.alternatives()
74
98
  .try(
75
99
  // Tag market, product, topic like this: "market: ch", "product: firefly", "topic: copyright"
@@ -351,13 +375,7 @@ export const configSchema = Joi.object({
351
375
  }),
352
376
  ).optional(),
353
377
  tags: Joi.array().items(Joi.string()).optional(),
354
- cdnlogsFilter: Joi.array().items(
355
- Joi.object({
356
- key: Joi.string().required(),
357
- value: Joi.array().items(Joi.string()).required(),
358
- type: Joi.string().valid('include', 'exclude').optional(),
359
- }),
360
- ).optional(),
378
+ cdnlogsFilter: CDN_LOGS_FILTER_SCHEMA.optional(),
361
379
  countryCodeIgnoreList: Joi.array().items(
362
380
  Joi.string().length(2),
363
381
  ).optional(),
@@ -842,8 +860,17 @@ export const Config = (data = {}) => {
842
860
  };
843
861
 
844
862
  self.updateLlmoCdnlogsFilter = (cdnlogsFilter) => {
863
+ // Reject invalid filter keys at write time (VULN-37491): `key` is
864
+ // interpolated into Athena SQL downstream, so anything off the allowlist
865
+ // must never be persisted. Validate only the filter here to avoid coupling
866
+ // to unrelated required fields elsewhere in the config.
867
+ const { error, value } = CDN_LOGS_FILTER_SCHEMA.validate(cdnlogsFilter);
868
+ if (error) {
869
+ throw new Error(`CDN logs filter validation error: ${error.message}`, { cause: error });
870
+ }
871
+
845
872
  state.llmo = state.llmo || {};
846
- state.llmo.cdnlogsFilter = cdnlogsFilter;
873
+ state.llmo.cdnlogsFilter = value;
847
874
  };
848
875
 
849
876
  self.updateLlmoCountryCodeIgnoreList = (countryCodeIgnoreList) => {