@commercetools-frontend/application-config 27.5.1 → 27.5.2

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.
@@ -267,41 +267,59 @@ const substituteFilePathVariablePlaceholder = (valueOfPlaceholder, matchedString
267
267
  const _valueOfPlaceholder$s5 = valueOfPlaceholder.split(':'),
268
268
  _valueOfPlaceholder$s6 = _slicedToArray(_valueOfPlaceholder$s5, 2),
269
269
  filePathOrModule = _valueOfPlaceholder$s6[1];
270
+
271
+ // Security check: Prevent path traversal attacks.
272
+ // Two strategies depending on whether the specifier is a bare module name
273
+ // (e.g. "@scope/pkg/file.svg") or a relative/absolute path (e.g. "./app.svg").
274
+ const isModuleName = !_startsWithInstanceProperty__default["default"](filePathOrModule).call(filePathOrModule, '.') && !_startsWithInstanceProperty__default["default"](filePathOrModule).call(filePathOrModule, '/');
275
+ if (isModuleName) {
276
+ // Bare module specifiers are resolved by require.resolve through
277
+ // node_modules, linked packages, or Yarn PnP — all legitimate locations
278
+ // that may be outside the workspace root (e.g. hoisted deps in CI).
279
+ // We skip the workspace root check for these, but we must block ".."
280
+ // segments in the specifier itself — those are the only way to make
281
+ // require.resolve escape module directories and reach arbitrary files
282
+ // (e.g. "some-pkg/../../../../etc/passwd" resolves through node_modules
283
+ // to /etc/passwd).
284
+ const normalizedSpecifier = path__default$1["default"].posix.normalize(filePathOrModule);
285
+ if (_startsWithInstanceProperty__default["default"](normalizedSpecifier).call(normalizedSpecifier, '..')) {
286
+ throw new Error(`Path traversal in module specifiers is not allowed: ${filePathOrModule}`);
287
+ }
288
+ }
270
289
  const resolvedPath = require.resolve(filePathOrModule, {
271
290
  paths: [loadingOptions.applicationPath]
272
291
  });
273
-
274
- // Security check: Prevent path traversal attacks.
275
- // require.resolve() already provides protection by only resolving modules
276
- // accessible from the applicationPath. However, we add an extra layer to
277
- // prevent access to sensitive system files outside the workspace.
278
292
  const normalizedPath = path__default$1["default"].normalize(resolvedPath);
279
- const applicationPath = path__default$1["default"].normalize(loadingOptions.applicationPath);
293
+ if (!isModuleName) {
294
+ // For relative/absolute paths, verify the resolved path is within the
295
+ // workspace root. require.resolve() already provides some protection by
296
+ // only resolving from applicationPath, but we add an extra layer to
297
+ // prevent access to sensitive system files outside the workspace.
298
+ const applicationPath = path__default$1["default"].normalize(loadingOptions.applicationPath);
280
299
 
281
- // Find workspace root by traversing up from applicationPath until we find
282
- // package.json, pnpm-workspace.yaml, or reach root
283
- let workspaceRoot = applicationPath;
284
- let currentPath = applicationPath;
285
- const rootPath = path__default$1["default"].parse(currentPath).root;
286
- while (currentPath !== rootPath) {
287
- const hasPackageJson = fs__default$1["default"].existsSync(path__default$1["default"].join(currentPath, 'package.json'));
288
- const hasWorkspaceConfig = fs__default$1["default"].existsSync(path__default$1["default"].join(currentPath, 'pnpm-workspace.yaml')) || fs__default$1["default"].existsSync(path__default$1["default"].join(currentPath, 'lerna.json'));
289
- if (hasPackageJson) {
290
- workspaceRoot = currentPath;
291
- if (hasWorkspaceConfig) {
292
- // Found workspace root
293
- break;
300
+ // Find workspace root by traversing up from applicationPath until we find
301
+ // package.json, pnpm-workspace.yaml, or reach root
302
+ let workspaceRoot = applicationPath;
303
+ let currentPath = applicationPath;
304
+ const rootPath = path__default$1["default"].parse(currentPath).root;
305
+ while (currentPath !== rootPath) {
306
+ const hasPackageJson = fs__default$1["default"].existsSync(path__default$1["default"].join(currentPath, 'package.json'));
307
+ const hasWorkspaceConfig = fs__default$1["default"].existsSync(path__default$1["default"].join(currentPath, 'pnpm-workspace.yaml')) || fs__default$1["default"].existsSync(path__default$1["default"].join(currentPath, 'lerna.json'));
308
+ if (hasPackageJson) {
309
+ workspaceRoot = currentPath;
310
+ if (hasWorkspaceConfig) {
311
+ // Found workspace root
312
+ break;
313
+ }
294
314
  }
315
+ currentPath = path__default$1["default"].dirname(currentPath);
316
+ }
317
+ const relativePath = path__default$1["default"].relative(workspaceRoot, normalizedPath);
318
+ // Use path.relative() to avoid string prefix vulnerabilities (e.g., "/app" vs "/app-evil")
319
+ const isSafePath = !_startsWithInstanceProperty__default["default"](relativePath).call(relativePath, '..') && !path__default$1["default"].isAbsolute(relativePath);
320
+ if (!isSafePath) {
321
+ throw new Error(`Access to files outside workspace directory is not allowed: ${filePathOrModule}`);
295
322
  }
296
- currentPath = path__default$1["default"].dirname(currentPath);
297
- }
298
- const relativePath = path__default$1["default"].relative(workspaceRoot, normalizedPath);
299
-
300
- // Path is safe if it's within the workspace root.
301
- // Use path.relative() to avoid string prefix vulnerabilities (e.g., "/app" vs "/app-evil")
302
- const isSafePath = !_startsWithInstanceProperty__default["default"](relativePath).call(relativePath, '..') && !path__default$1["default"].isAbsolute(relativePath);
303
- if (!isSafePath) {
304
- throw new Error(`Access to files outside workspace directory is not allowed: ${filePathOrModule}`);
305
323
  }
306
324
  const content = fs__default$1["default"].readFileSync(normalizedPath, {
307
325
  encoding: 'utf-8'
@@ -267,41 +267,59 @@ const substituteFilePathVariablePlaceholder = (valueOfPlaceholder, matchedString
267
267
  const _valueOfPlaceholder$s5 = valueOfPlaceholder.split(':'),
268
268
  _valueOfPlaceholder$s6 = _slicedToArray(_valueOfPlaceholder$s5, 2),
269
269
  filePathOrModule = _valueOfPlaceholder$s6[1];
270
+
271
+ // Security check: Prevent path traversal attacks.
272
+ // Two strategies depending on whether the specifier is a bare module name
273
+ // (e.g. "@scope/pkg/file.svg") or a relative/absolute path (e.g. "./app.svg").
274
+ const isModuleName = !_startsWithInstanceProperty__default["default"](filePathOrModule).call(filePathOrModule, '.') && !_startsWithInstanceProperty__default["default"](filePathOrModule).call(filePathOrModule, '/');
275
+ if (isModuleName) {
276
+ // Bare module specifiers are resolved by require.resolve through
277
+ // node_modules, linked packages, or Yarn PnP — all legitimate locations
278
+ // that may be outside the workspace root (e.g. hoisted deps in CI).
279
+ // We skip the workspace root check for these, but we must block ".."
280
+ // segments in the specifier itself — those are the only way to make
281
+ // require.resolve escape module directories and reach arbitrary files
282
+ // (e.g. "some-pkg/../../../../etc/passwd" resolves through node_modules
283
+ // to /etc/passwd).
284
+ const normalizedSpecifier = path__default$1["default"].posix.normalize(filePathOrModule);
285
+ if (_startsWithInstanceProperty__default["default"](normalizedSpecifier).call(normalizedSpecifier, '..')) {
286
+ throw new Error(`Path traversal in module specifiers is not allowed: ${filePathOrModule}`);
287
+ }
288
+ }
270
289
  const resolvedPath = require.resolve(filePathOrModule, {
271
290
  paths: [loadingOptions.applicationPath]
272
291
  });
273
-
274
- // Security check: Prevent path traversal attacks.
275
- // require.resolve() already provides protection by only resolving modules
276
- // accessible from the applicationPath. However, we add an extra layer to
277
- // prevent access to sensitive system files outside the workspace.
278
292
  const normalizedPath = path__default$1["default"].normalize(resolvedPath);
279
- const applicationPath = path__default$1["default"].normalize(loadingOptions.applicationPath);
293
+ if (!isModuleName) {
294
+ // For relative/absolute paths, verify the resolved path is within the
295
+ // workspace root. require.resolve() already provides some protection by
296
+ // only resolving from applicationPath, but we add an extra layer to
297
+ // prevent access to sensitive system files outside the workspace.
298
+ const applicationPath = path__default$1["default"].normalize(loadingOptions.applicationPath);
280
299
 
281
- // Find workspace root by traversing up from applicationPath until we find
282
- // package.json, pnpm-workspace.yaml, or reach root
283
- let workspaceRoot = applicationPath;
284
- let currentPath = applicationPath;
285
- const rootPath = path__default$1["default"].parse(currentPath).root;
286
- while (currentPath !== rootPath) {
287
- const hasPackageJson = fs__default$1["default"].existsSync(path__default$1["default"].join(currentPath, 'package.json'));
288
- const hasWorkspaceConfig = fs__default$1["default"].existsSync(path__default$1["default"].join(currentPath, 'pnpm-workspace.yaml')) || fs__default$1["default"].existsSync(path__default$1["default"].join(currentPath, 'lerna.json'));
289
- if (hasPackageJson) {
290
- workspaceRoot = currentPath;
291
- if (hasWorkspaceConfig) {
292
- // Found workspace root
293
- break;
300
+ // Find workspace root by traversing up from applicationPath until we find
301
+ // package.json, pnpm-workspace.yaml, or reach root
302
+ let workspaceRoot = applicationPath;
303
+ let currentPath = applicationPath;
304
+ const rootPath = path__default$1["default"].parse(currentPath).root;
305
+ while (currentPath !== rootPath) {
306
+ const hasPackageJson = fs__default$1["default"].existsSync(path__default$1["default"].join(currentPath, 'package.json'));
307
+ const hasWorkspaceConfig = fs__default$1["default"].existsSync(path__default$1["default"].join(currentPath, 'pnpm-workspace.yaml')) || fs__default$1["default"].existsSync(path__default$1["default"].join(currentPath, 'lerna.json'));
308
+ if (hasPackageJson) {
309
+ workspaceRoot = currentPath;
310
+ if (hasWorkspaceConfig) {
311
+ // Found workspace root
312
+ break;
313
+ }
294
314
  }
315
+ currentPath = path__default$1["default"].dirname(currentPath);
316
+ }
317
+ const relativePath = path__default$1["default"].relative(workspaceRoot, normalizedPath);
318
+ // Use path.relative() to avoid string prefix vulnerabilities (e.g., "/app" vs "/app-evil")
319
+ const isSafePath = !_startsWithInstanceProperty__default["default"](relativePath).call(relativePath, '..') && !path__default$1["default"].isAbsolute(relativePath);
320
+ if (!isSafePath) {
321
+ throw new Error(`Access to files outside workspace directory is not allowed: ${filePathOrModule}`);
295
322
  }
296
- currentPath = path__default$1["default"].dirname(currentPath);
297
- }
298
- const relativePath = path__default$1["default"].relative(workspaceRoot, normalizedPath);
299
-
300
- // Path is safe if it's within the workspace root.
301
- // Use path.relative() to avoid string prefix vulnerabilities (e.g., "/app" vs "/app-evil")
302
- const isSafePath = !_startsWithInstanceProperty__default["default"](relativePath).call(relativePath, '..') && !path__default$1["default"].isAbsolute(relativePath);
303
- if (!isSafePath) {
304
- throw new Error(`Access to files outside workspace directory is not allowed: ${filePathOrModule}`);
305
323
  }
306
324
  const content = fs__default$1["default"].readFileSync(normalizedPath, {
307
325
  encoding: 'utf-8'
@@ -231,41 +231,59 @@ const substituteFilePathVariablePlaceholder = (valueOfPlaceholder, matchedString
231
231
  const _valueOfPlaceholder$s5 = valueOfPlaceholder.split(':'),
232
232
  _valueOfPlaceholder$s6 = _slicedToArray(_valueOfPlaceholder$s5, 2),
233
233
  filePathOrModule = _valueOfPlaceholder$s6[1];
234
+
235
+ // Security check: Prevent path traversal attacks.
236
+ // Two strategies depending on whether the specifier is a bare module name
237
+ // (e.g. "@scope/pkg/file.svg") or a relative/absolute path (e.g. "./app.svg").
238
+ const isModuleName = !_startsWithInstanceProperty(filePathOrModule).call(filePathOrModule, '.') && !_startsWithInstanceProperty(filePathOrModule).call(filePathOrModule, '/');
239
+ if (isModuleName) {
240
+ // Bare module specifiers are resolved by require.resolve through
241
+ // node_modules, linked packages, or Yarn PnP — all legitimate locations
242
+ // that may be outside the workspace root (e.g. hoisted deps in CI).
243
+ // We skip the workspace root check for these, but we must block ".."
244
+ // segments in the specifier itself — those are the only way to make
245
+ // require.resolve escape module directories and reach arbitrary files
246
+ // (e.g. "some-pkg/../../../../etc/passwd" resolves through node_modules
247
+ // to /etc/passwd).
248
+ const normalizedSpecifier = path$1.posix.normalize(filePathOrModule);
249
+ if (_startsWithInstanceProperty(normalizedSpecifier).call(normalizedSpecifier, '..')) {
250
+ throw new Error(`Path traversal in module specifiers is not allowed: ${filePathOrModule}`);
251
+ }
252
+ }
234
253
  const resolvedPath = require.resolve(filePathOrModule, {
235
254
  paths: [loadingOptions.applicationPath]
236
255
  });
237
-
238
- // Security check: Prevent path traversal attacks.
239
- // require.resolve() already provides protection by only resolving modules
240
- // accessible from the applicationPath. However, we add an extra layer to
241
- // prevent access to sensitive system files outside the workspace.
242
256
  const normalizedPath = path$1.normalize(resolvedPath);
243
- const applicationPath = path$1.normalize(loadingOptions.applicationPath);
257
+ if (!isModuleName) {
258
+ // For relative/absolute paths, verify the resolved path is within the
259
+ // workspace root. require.resolve() already provides some protection by
260
+ // only resolving from applicationPath, but we add an extra layer to
261
+ // prevent access to sensitive system files outside the workspace.
262
+ const applicationPath = path$1.normalize(loadingOptions.applicationPath);
244
263
 
245
- // Find workspace root by traversing up from applicationPath until we find
246
- // package.json, pnpm-workspace.yaml, or reach root
247
- let workspaceRoot = applicationPath;
248
- let currentPath = applicationPath;
249
- const rootPath = path$1.parse(currentPath).root;
250
- while (currentPath !== rootPath) {
251
- const hasPackageJson = fs$1.existsSync(path$1.join(currentPath, 'package.json'));
252
- const hasWorkspaceConfig = fs$1.existsSync(path$1.join(currentPath, 'pnpm-workspace.yaml')) || fs$1.existsSync(path$1.join(currentPath, 'lerna.json'));
253
- if (hasPackageJson) {
254
- workspaceRoot = currentPath;
255
- if (hasWorkspaceConfig) {
256
- // Found workspace root
257
- break;
264
+ // Find workspace root by traversing up from applicationPath until we find
265
+ // package.json, pnpm-workspace.yaml, or reach root
266
+ let workspaceRoot = applicationPath;
267
+ let currentPath = applicationPath;
268
+ const rootPath = path$1.parse(currentPath).root;
269
+ while (currentPath !== rootPath) {
270
+ const hasPackageJson = fs$1.existsSync(path$1.join(currentPath, 'package.json'));
271
+ const hasWorkspaceConfig = fs$1.existsSync(path$1.join(currentPath, 'pnpm-workspace.yaml')) || fs$1.existsSync(path$1.join(currentPath, 'lerna.json'));
272
+ if (hasPackageJson) {
273
+ workspaceRoot = currentPath;
274
+ if (hasWorkspaceConfig) {
275
+ // Found workspace root
276
+ break;
277
+ }
258
278
  }
279
+ currentPath = path$1.dirname(currentPath);
280
+ }
281
+ const relativePath = path$1.relative(workspaceRoot, normalizedPath);
282
+ // Use path.relative() to avoid string prefix vulnerabilities (e.g., "/app" vs "/app-evil")
283
+ const isSafePath = !_startsWithInstanceProperty(relativePath).call(relativePath, '..') && !path$1.isAbsolute(relativePath);
284
+ if (!isSafePath) {
285
+ throw new Error(`Access to files outside workspace directory is not allowed: ${filePathOrModule}`);
259
286
  }
260
- currentPath = path$1.dirname(currentPath);
261
- }
262
- const relativePath = path$1.relative(workspaceRoot, normalizedPath);
263
-
264
- // Path is safe if it's within the workspace root.
265
- // Use path.relative() to avoid string prefix vulnerabilities (e.g., "/app" vs "/app-evil")
266
- const isSafePath = !_startsWithInstanceProperty(relativePath).call(relativePath, '..') && !path$1.isAbsolute(relativePath);
267
- if (!isSafePath) {
268
- throw new Error(`Access to files outside workspace directory is not allowed: ${filePathOrModule}`);
269
287
  }
270
288
  const content = fs$1.readFileSync(normalizedPath, {
271
289
  encoding: 'utf-8'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@commercetools-frontend/application-config",
3
- "version": "27.5.1",
3
+ "version": "27.5.2",
4
4
  "description": "Configuration utilities for building Custom Applications",
5
5
  "bugs": "https://github.com/commercetools/merchant-center-application-kit/issues",
6
6
  "repository": {
@@ -45,7 +45,7 @@
45
45
  "@babel/register": "^7.22.15",
46
46
  "@babel/runtime": "^7.22.15",
47
47
  "@babel/runtime-corejs3": "^7.22.15",
48
- "@commercetools-frontend/constants": "27.5.1",
48
+ "@commercetools-frontend/constants": "27.5.2",
49
49
  "@types/lodash": "^4.14.198",
50
50
  "@types/react": "^19.0.3",
51
51
  "ajv": "8.18.0",
@@ -60,7 +60,7 @@
60
60
  "devDependencies": {
61
61
  "@types/jsdom": "^21.1.2",
62
62
  "json-schema-to-typescript": "15.0.4",
63
- "@commercetools-frontend/assets": "27.5.1"
63
+ "@commercetools-frontend/assets": "27.5.2"
64
64
  },
65
65
  "engines": {
66
66
  "node": "18.x || 20.x || >=22.0.0"