@hyperfrontend/project-scope 0.2.2 → 0.2.3
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 +7 -0
- package/_shared/core/fs/guard/index.cjs.js +7 -0
- package/_shared/core/fs/guard/index.esm.js +5 -0
- package/_shared/core/fs/stat/index.cjs.js +3 -2
- package/_shared/core/fs/stat/index.esm.js +3 -2
- package/_shared/core/path/confine/index.cjs.js +22 -0
- package/_shared/core/path/confine/index.esm.js +19 -0
- package/cli/index.cjs.js +5 -1
- package/cli/index.esm.js +5 -1
- package/core/fs/index.cjs.js +12 -2
- package/core/fs/index.esm.js +12 -2
- package/core/index.cjs.js +13 -3
- package/core/index.esm.js +14 -4
- package/core/path/index.cjs.js +4 -2
- package/core/path/index.d.ts +22 -1
- package/core/path/index.d.ts.map +1 -1
- package/core/path/index.esm.js +4 -3
- package/heuristics/dependencies/index.cjs.js +10 -1
- package/heuristics/dependencies/index.esm.js +12 -3
- package/heuristics/entry-points/index.cjs.js +2 -1
- package/heuristics/entry-points/index.esm.js +2 -1
- package/heuristics/framework/index.cjs.js +2 -1
- package/heuristics/framework/index.esm.js +2 -1
- package/heuristics/index.cjs.js +10 -1
- package/heuristics/index.esm.js +12 -3
- package/heuristics/project-type/index.cjs.js +2 -1
- package/heuristics/project-type/index.esm.js +2 -1
- package/index.cjs.js +18 -3
- package/index.esm.js +19 -4
- package/nx/index.cjs.js +3 -2
- package/nx/index.esm.js +3 -2
- package/package.json +1 -1
- package/project/config/index.cjs.js +5 -1
- package/project/config/index.esm.js +5 -1
- package/project/index.cjs.js +5 -1
- package/project/index.esm.js +5 -1
- package/project/package/index.cjs.js +5 -1
- package/project/package/index.esm.js +5 -1
- package/project/root/index.cjs.js +2 -1
- package/project/root/index.esm.js +2 -1
- package/project/traversal/index.cjs.js +2 -1
- package/project/traversal/index.esm.js +2 -1
- package/tech/backend/index.cjs.js +2 -1
- package/tech/backend/index.esm.js +2 -1
- package/tech/build/index.cjs.js +2 -1
- package/tech/build/index.esm.js +2 -1
- package/tech/frontend/index.cjs.js +2 -1
- package/tech/frontend/index.esm.js +2 -1
- package/tech/index.cjs.js +2 -1
- package/tech/index.esm.js +2 -1
- package/tech/legacy/index.cjs.js +2 -1
- package/tech/legacy/index.esm.js +2 -1
- package/tech/linting/index.cjs.js +2 -1
- package/tech/linting/index.esm.js +2 -1
- package/tech/monorepo/index.cjs.js +2 -1
- package/tech/monorepo/index.esm.js +2 -1
- package/tech/testing/index.cjs.js +2 -1
- package/tech/testing/index.esm.js +2 -1
- package/tech/types/index.cjs.js +2 -1
- package/tech/types/index.esm.js +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.2.3](https://github.com/AndrewRedican/hyperfrontend/compare/5f116abb8ba6355dfb283fa03b7481e5eb029480...7fb26b6a30c007cd0392f1fc973265c3d25e16dd) - 2026-06-28
|
|
6
|
+
|
|
7
|
+
### Bug Fixes
|
|
8
|
+
|
|
9
|
+
- confine import resolution to the project root
|
|
10
|
+
- reject NUL-byte paths in fs primitives
|
|
11
|
+
|
|
5
12
|
## [0.2.2](https://github.com/AndrewRedican/hyperfrontend/compare/d96fee4d4d3a70178c8a01e5f2e2ae675fa23f37...466c0388c4cd516b9c704214140b4df1004098e6) - 2026-06-23
|
|
6
13
|
|
|
7
14
|
### Other
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const { isSafePath } = require('../guard/index.cjs.js');
|
|
3
4
|
const node_fs = require('node:fs');
|
|
4
5
|
|
|
5
6
|
function getFileStat(filePath, followSymlinks = true) {
|
|
6
|
-
if (!node_fs.existsSync(filePath)) {
|
|
7
|
+
if (!isSafePath(filePath) || !node_fs.existsSync(filePath)) {
|
|
7
8
|
return null;
|
|
8
9
|
}
|
|
9
10
|
try {
|
|
@@ -36,7 +37,7 @@ function isSymlink(linkPath) {
|
|
|
36
37
|
return stats?.isSymlink ?? false;
|
|
37
38
|
}
|
|
38
39
|
function exists(filePath) {
|
|
39
|
-
return node_fs.existsSync(filePath);
|
|
40
|
+
return isSafePath(filePath) && node_fs.existsSync(filePath);
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
exports.getFileStat = getFileStat;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { isSafePath } from '../guard/index.esm.js';
|
|
1
2
|
import { existsSync, statSync, lstatSync } from 'node:fs';
|
|
2
3
|
|
|
3
4
|
function getFileStat(filePath, followSymlinks = true) {
|
|
4
|
-
if (!existsSync(filePath)) {
|
|
5
|
+
if (!isSafePath(filePath) || !existsSync(filePath)) {
|
|
5
6
|
return null;
|
|
6
7
|
}
|
|
7
8
|
try {
|
|
@@ -34,7 +35,7 @@ function isSymlink(linkPath) {
|
|
|
34
35
|
return stats?.isSymlink ?? false;
|
|
35
36
|
}
|
|
36
37
|
function exists(filePath) {
|
|
37
|
-
return existsSync(filePath);
|
|
38
|
+
return isSafePath(filePath) && existsSync(filePath);
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
export { getFileStat, isFile, isDirectory, isSymlink, exists };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { removeTrailingSlash, normalizePath } = require('../normalize/index.cjs.js');
|
|
4
|
+
const node_path = require('node:path');
|
|
5
|
+
const node_fs = require('node:fs');
|
|
6
|
+
|
|
7
|
+
function contains(root, path) {
|
|
8
|
+
const base = removeTrailingSlash(root);
|
|
9
|
+
return path === base || path.startsWith(`${base}/`);
|
|
10
|
+
}
|
|
11
|
+
function isWithinRoot(root, candidate) {
|
|
12
|
+
if (!contains(normalizePath(node_path.resolve(root)), normalizePath(node_path.resolve(candidate)))) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
if (!node_fs.existsSync(candidate)) {
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
return contains(normalizePath(node_fs.realpathSync(root)), normalizePath(node_fs.realpathSync(candidate)));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
exports.contains = contains;
|
|
22
|
+
exports.isWithinRoot = isWithinRoot;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { removeTrailingSlash, normalizePath } from '../normalize/index.esm.js';
|
|
2
|
+
import { existsSync, realpathSync } from 'node:fs';
|
|
3
|
+
import { resolve } from 'node:path';
|
|
4
|
+
|
|
5
|
+
function contains(root, path) {
|
|
6
|
+
const base = removeTrailingSlash(root);
|
|
7
|
+
return path === base || path.startsWith(`${base}/`);
|
|
8
|
+
}
|
|
9
|
+
function isWithinRoot(root, candidate) {
|
|
10
|
+
if (!contains(normalizePath(resolve(root)), normalizePath(resolve(candidate)))) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
if (!existsSync(candidate)) {
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
return contains(normalizePath(realpathSync(root)), normalizePath(realpathSync(candidate)));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export { contains, isWithinRoot };
|
package/cli/index.cjs.js
CHANGED
|
@@ -14,6 +14,7 @@ const index_cjs_js$6 = require('../_dependencies/@hyperfrontend/immutable-api-ut
|
|
|
14
14
|
const index_cjs_js$7 = require('../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/map/index.cjs.js');
|
|
15
15
|
const index_cjs_js$8 = require('../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/math/index.cjs.js');
|
|
16
16
|
const index_cjs_js$9 = require('../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/number/index.cjs.js');
|
|
17
|
+
const { isSafePath } = require('../_shared/core/fs/guard/index.cjs.js');
|
|
17
18
|
const { getFileStat, isDirectory, exists } = require('../_shared/core/fs/stat/index.cjs.js');
|
|
18
19
|
const { join } = require('../_shared/core/path/join/index.cjs.js');
|
|
19
20
|
const { createConfigError } = require('../_shared/core/errors/structured-errors/index.cjs.js');
|
|
@@ -233,6 +234,9 @@ function createFileSystemError(message, code, context) {
|
|
|
233
234
|
* ```
|
|
234
235
|
*/
|
|
235
236
|
function readFileContent(filePath, encoding = 'utf-8') {
|
|
237
|
+
if (!isSafePath(filePath)) {
|
|
238
|
+
throw createFileSystemError(`Unsafe file path: ${filePath}`, 'FS_READ_ERROR', { path: filePath, operation: 'read' });
|
|
239
|
+
}
|
|
236
240
|
if (!node_fs.existsSync(filePath)) {
|
|
237
241
|
fsLogger.debug('File not found', { path: filePath });
|
|
238
242
|
throw createFileSystemError(`File not found: ${filePath}`, 'FS_NOT_FOUND', { path: filePath, operation: 'read' });
|
|
@@ -261,7 +265,7 @@ function readFileContent(filePath, encoding = 'utf-8') {
|
|
|
261
265
|
* ```
|
|
262
266
|
*/
|
|
263
267
|
function readFileIfExists(filePath, encoding = 'utf-8') {
|
|
264
|
-
if (!node_fs.existsSync(filePath)) {
|
|
268
|
+
if (!isSafePath(filePath) || !node_fs.existsSync(filePath)) {
|
|
265
269
|
return null;
|
|
266
270
|
}
|
|
267
271
|
try {
|
package/cli/index.esm.js
CHANGED
|
@@ -12,6 +12,7 @@ import { createError } from '../_dependencies/@hyperfrontend/immutable-api-utils
|
|
|
12
12
|
import { createMap } from '../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/map/index.esm.js';
|
|
13
13
|
import { min, round } from '../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/math/index.esm.js';
|
|
14
14
|
import { parseInt, parseFloat } from '../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/number/index.esm.js';
|
|
15
|
+
import { isSafePath } from '../_shared/core/fs/guard/index.esm.js';
|
|
15
16
|
import { getFileStat, isDirectory, exists } from '../_shared/core/fs/stat/index.esm.js';
|
|
16
17
|
import { join } from '../_shared/core/path/join/index.esm.js';
|
|
17
18
|
import { createConfigError } from '../_shared/core/errors/structured-errors/index.esm.js';
|
|
@@ -231,6 +232,9 @@ function createFileSystemError(message, code, context) {
|
|
|
231
232
|
* ```
|
|
232
233
|
*/
|
|
233
234
|
function readFileContent(filePath, encoding = 'utf-8') {
|
|
235
|
+
if (!isSafePath(filePath)) {
|
|
236
|
+
throw createFileSystemError(`Unsafe file path: ${filePath}`, 'FS_READ_ERROR', { path: filePath, operation: 'read' });
|
|
237
|
+
}
|
|
234
238
|
if (!existsSync(filePath)) {
|
|
235
239
|
fsLogger.debug('File not found', { path: filePath });
|
|
236
240
|
throw createFileSystemError(`File not found: ${filePath}`, 'FS_NOT_FOUND', { path: filePath, operation: 'read' });
|
|
@@ -259,7 +263,7 @@ function readFileContent(filePath, encoding = 'utf-8') {
|
|
|
259
263
|
* ```
|
|
260
264
|
*/
|
|
261
265
|
function readFileIfExists(filePath, encoding = 'utf-8') {
|
|
262
|
-
if (!existsSync(filePath)) {
|
|
266
|
+
if (!isSafePath(filePath) || !existsSync(filePath)) {
|
|
263
267
|
return null;
|
|
264
268
|
}
|
|
265
269
|
try {
|
package/core/fs/index.cjs.js
CHANGED
|
@@ -9,6 +9,7 @@ const index_cjs_js$2 = require('../../_dependencies/@hyperfrontend/immutable-api
|
|
|
9
9
|
const index_cjs_js = require('../../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/set/index.cjs.js');
|
|
10
10
|
const index_cjs_js$1 = require('../../_dependencies/@hyperfrontend/logging/index.cjs.js');
|
|
11
11
|
const index_cjs_js$6 = require('../../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/error/index.cjs.js');
|
|
12
|
+
const { isSafePath } = require('../../_shared/core/fs/guard/index.cjs.js');
|
|
12
13
|
const { getFileStat, isFile, isDirectory, isSymlink, exists } = require('../../_shared/core/fs/stat/index.cjs.js');
|
|
13
14
|
const { join } = require('../../_shared/core/path/join/index.cjs.js');
|
|
14
15
|
|
|
@@ -197,6 +198,9 @@ function createFileSystemError(message, code, context) {
|
|
|
197
198
|
* ```
|
|
198
199
|
*/
|
|
199
200
|
function readFileContent(filePath, encoding = 'utf-8') {
|
|
201
|
+
if (!isSafePath(filePath)) {
|
|
202
|
+
throw createFileSystemError(`Unsafe file path: ${filePath}`, 'FS_READ_ERROR', { path: filePath, operation: 'read' });
|
|
203
|
+
}
|
|
200
204
|
if (!node_fs.existsSync(filePath)) {
|
|
201
205
|
fsLogger.debug('File not found', { path: filePath });
|
|
202
206
|
throw createFileSystemError(`File not found: ${filePath}`, 'FS_NOT_FOUND', { path: filePath, operation: 'read' });
|
|
@@ -223,6 +227,9 @@ function readFileContent(filePath, encoding = 'utf-8') {
|
|
|
223
227
|
* ```
|
|
224
228
|
*/
|
|
225
229
|
function readFileBuffer(filePath) {
|
|
230
|
+
if (!isSafePath(filePath)) {
|
|
231
|
+
throw createFileSystemError(`Unsafe file path: ${filePath}`, 'FS_READ_ERROR', { path: filePath, operation: 'read' });
|
|
232
|
+
}
|
|
226
233
|
if (!node_fs.existsSync(filePath)) {
|
|
227
234
|
throw createFileSystemError(`File not found: ${filePath}`, 'FS_NOT_FOUND', { path: filePath, operation: 'read' });
|
|
228
235
|
}
|
|
@@ -249,7 +256,7 @@ function readFileBuffer(filePath) {
|
|
|
249
256
|
* ```
|
|
250
257
|
*/
|
|
251
258
|
function readFileIfExists(filePath, encoding = 'utf-8') {
|
|
252
|
-
if (!node_fs.existsSync(filePath)) {
|
|
259
|
+
if (!isSafePath(filePath) || !node_fs.existsSync(filePath)) {
|
|
253
260
|
return null;
|
|
254
261
|
}
|
|
255
262
|
try {
|
|
@@ -281,6 +288,9 @@ function readFileIfExists(filePath, encoding = 'utf-8') {
|
|
|
281
288
|
* ```
|
|
282
289
|
*/
|
|
283
290
|
function readJsonFile(filePath, options) {
|
|
291
|
+
if (!isSafePath(filePath)) {
|
|
292
|
+
throw createFileSystemError(`Unsafe file path: ${filePath}`, 'FS_READ_ERROR', { path: filePath, operation: 'read' });
|
|
293
|
+
}
|
|
284
294
|
if (!node_fs.existsSync(filePath)) {
|
|
285
295
|
if (options && 'default' in options) {
|
|
286
296
|
fsLogger.debug('JSON file not found, using default', { path: filePath });
|
|
@@ -320,7 +330,7 @@ function readJsonFile(filePath, options) {
|
|
|
320
330
|
* ```
|
|
321
331
|
*/
|
|
322
332
|
function readJsonFileIfExists(filePath) {
|
|
323
|
-
if (!node_fs.existsSync(filePath)) {
|
|
333
|
+
if (!isSafePath(filePath) || !node_fs.existsSync(filePath)) {
|
|
324
334
|
return null;
|
|
325
335
|
}
|
|
326
336
|
try {
|
package/core/fs/index.esm.js
CHANGED
|
@@ -7,6 +7,7 @@ import { freeze, entries, keys, defineProperties } from '../../_dependencies/@hy
|
|
|
7
7
|
import { createSet } from '../../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/set/index.esm.js';
|
|
8
8
|
import { createLogger } from '../../_dependencies/@hyperfrontend/logging/index.esm.js';
|
|
9
9
|
import { createError } from '../../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/error/index.esm.js';
|
|
10
|
+
import { isSafePath } from '../../_shared/core/fs/guard/index.esm.js';
|
|
10
11
|
import { getFileStat, isFile, isDirectory, isSymlink, exists } from '../../_shared/core/fs/stat/index.esm.js';
|
|
11
12
|
import { join } from '../../_shared/core/path/join/index.esm.js';
|
|
12
13
|
|
|
@@ -195,6 +196,9 @@ function createFileSystemError(message, code, context) {
|
|
|
195
196
|
* ```
|
|
196
197
|
*/
|
|
197
198
|
function readFileContent(filePath, encoding = 'utf-8') {
|
|
199
|
+
if (!isSafePath(filePath)) {
|
|
200
|
+
throw createFileSystemError(`Unsafe file path: ${filePath}`, 'FS_READ_ERROR', { path: filePath, operation: 'read' });
|
|
201
|
+
}
|
|
198
202
|
if (!existsSync(filePath)) {
|
|
199
203
|
fsLogger.debug('File not found', { path: filePath });
|
|
200
204
|
throw createFileSystemError(`File not found: ${filePath}`, 'FS_NOT_FOUND', { path: filePath, operation: 'read' });
|
|
@@ -221,6 +225,9 @@ function readFileContent(filePath, encoding = 'utf-8') {
|
|
|
221
225
|
* ```
|
|
222
226
|
*/
|
|
223
227
|
function readFileBuffer(filePath) {
|
|
228
|
+
if (!isSafePath(filePath)) {
|
|
229
|
+
throw createFileSystemError(`Unsafe file path: ${filePath}`, 'FS_READ_ERROR', { path: filePath, operation: 'read' });
|
|
230
|
+
}
|
|
224
231
|
if (!existsSync(filePath)) {
|
|
225
232
|
throw createFileSystemError(`File not found: ${filePath}`, 'FS_NOT_FOUND', { path: filePath, operation: 'read' });
|
|
226
233
|
}
|
|
@@ -247,7 +254,7 @@ function readFileBuffer(filePath) {
|
|
|
247
254
|
* ```
|
|
248
255
|
*/
|
|
249
256
|
function readFileIfExists(filePath, encoding = 'utf-8') {
|
|
250
|
-
if (!existsSync(filePath)) {
|
|
257
|
+
if (!isSafePath(filePath) || !existsSync(filePath)) {
|
|
251
258
|
return null;
|
|
252
259
|
}
|
|
253
260
|
try {
|
|
@@ -279,6 +286,9 @@ function readFileIfExists(filePath, encoding = 'utf-8') {
|
|
|
279
286
|
* ```
|
|
280
287
|
*/
|
|
281
288
|
function readJsonFile(filePath, options) {
|
|
289
|
+
if (!isSafePath(filePath)) {
|
|
290
|
+
throw createFileSystemError(`Unsafe file path: ${filePath}`, 'FS_READ_ERROR', { path: filePath, operation: 'read' });
|
|
291
|
+
}
|
|
282
292
|
if (!existsSync(filePath)) {
|
|
283
293
|
if (options && 'default' in options) {
|
|
284
294
|
fsLogger.debug('JSON file not found, using default', { path: filePath });
|
|
@@ -318,7 +328,7 @@ function readJsonFile(filePath, options) {
|
|
|
318
328
|
* ```
|
|
319
329
|
*/
|
|
320
330
|
function readJsonFileIfExists(filePath) {
|
|
321
|
-
if (!existsSync(filePath)) {
|
|
331
|
+
if (!isSafePath(filePath) || !existsSync(filePath)) {
|
|
322
332
|
return null;
|
|
323
333
|
}
|
|
324
334
|
try {
|
package/core/index.cjs.js
CHANGED
|
@@ -12,9 +12,10 @@ const index_cjs_js$7 = require('../_dependencies/@hyperfrontend/immutable-api-ut
|
|
|
12
12
|
const node_fs = require('node:fs');
|
|
13
13
|
const node_path = require('node:path');
|
|
14
14
|
const node_os = require('node:os');
|
|
15
|
+
const { isSafePath } = require('../_shared/core/fs/guard/index.cjs.js');
|
|
15
16
|
const { getFileStat, isFile, isDirectory, isSymlink, exists } = require('../_shared/core/fs/stat/index.cjs.js');
|
|
16
|
-
const { join, joinPosix } = require('../_shared/core/path/join/index.cjs.js');
|
|
17
17
|
const { normalizePath, normalizeToForwardSlashes, normalizeToNative, removeTrailingSlash, ensureTrailingSlash } = require('../_shared/core/path/normalize/index.cjs.js');
|
|
18
|
+
const { join, joinPosix } = require('../_shared/core/path/join/index.cjs.js');
|
|
18
19
|
const { resolvePath, resolveFromWorkspace, resolveRealPath, relativePath, joinPath, isAbsolute, offsetFromRoot } = require('../_shared/core/path/resolve/index.cjs.js');
|
|
19
20
|
const { pathSegments, getBasename, getDirname, getExtension, getFileNameWithoutExtension, parsePath } = require('../_shared/core/path/segments/index.cjs.js');
|
|
20
21
|
const { createStructuredError, createConfigError, createFsError, createParseError, createValidationError } = require('../_shared/core/errors/structured-errors/index.cjs.js');
|
|
@@ -512,6 +513,9 @@ function createFileSystemError(message, code, context) {
|
|
|
512
513
|
* ```
|
|
513
514
|
*/
|
|
514
515
|
function readFileContent(filePath, encoding = 'utf-8') {
|
|
516
|
+
if (!isSafePath(filePath)) {
|
|
517
|
+
throw createFileSystemError(`Unsafe file path: ${filePath}`, 'FS_READ_ERROR', { path: filePath, operation: 'read' });
|
|
518
|
+
}
|
|
515
519
|
if (!node_fs.existsSync(filePath)) {
|
|
516
520
|
fsLogger.debug('File not found', { path: filePath });
|
|
517
521
|
throw createFileSystemError(`File not found: ${filePath}`, 'FS_NOT_FOUND', { path: filePath, operation: 'read' });
|
|
@@ -538,6 +542,9 @@ function readFileContent(filePath, encoding = 'utf-8') {
|
|
|
538
542
|
* ```
|
|
539
543
|
*/
|
|
540
544
|
function readFileBuffer(filePath) {
|
|
545
|
+
if (!isSafePath(filePath)) {
|
|
546
|
+
throw createFileSystemError(`Unsafe file path: ${filePath}`, 'FS_READ_ERROR', { path: filePath, operation: 'read' });
|
|
547
|
+
}
|
|
541
548
|
if (!node_fs.existsSync(filePath)) {
|
|
542
549
|
throw createFileSystemError(`File not found: ${filePath}`, 'FS_NOT_FOUND', { path: filePath, operation: 'read' });
|
|
543
550
|
}
|
|
@@ -564,7 +571,7 @@ function readFileBuffer(filePath) {
|
|
|
564
571
|
* ```
|
|
565
572
|
*/
|
|
566
573
|
function readFileIfExists(filePath, encoding = 'utf-8') {
|
|
567
|
-
if (!node_fs.existsSync(filePath)) {
|
|
574
|
+
if (!isSafePath(filePath) || !node_fs.existsSync(filePath)) {
|
|
568
575
|
return null;
|
|
569
576
|
}
|
|
570
577
|
try {
|
|
@@ -596,6 +603,9 @@ function readFileIfExists(filePath, encoding = 'utf-8') {
|
|
|
596
603
|
* ```
|
|
597
604
|
*/
|
|
598
605
|
function readJsonFile(filePath, options) {
|
|
606
|
+
if (!isSafePath(filePath)) {
|
|
607
|
+
throw createFileSystemError(`Unsafe file path: ${filePath}`, 'FS_READ_ERROR', { path: filePath, operation: 'read' });
|
|
608
|
+
}
|
|
599
609
|
if (!node_fs.existsSync(filePath)) {
|
|
600
610
|
if (options && 'default' in options) {
|
|
601
611
|
fsLogger.debug('JSON file not found, using default', { path: filePath });
|
|
@@ -635,7 +645,7 @@ function readJsonFile(filePath, options) {
|
|
|
635
645
|
* ```
|
|
636
646
|
*/
|
|
637
647
|
function readJsonFileIfExists(filePath) {
|
|
638
|
-
if (!node_fs.existsSync(filePath)) {
|
|
648
|
+
if (!isSafePath(filePath) || !node_fs.existsSync(filePath)) {
|
|
639
649
|
return null;
|
|
640
650
|
}
|
|
641
651
|
try {
|
package/core/index.esm.js
CHANGED
|
@@ -8,11 +8,12 @@ import { stringify, parse } from '../_dependencies/@hyperfrontend/immutable-api-
|
|
|
8
8
|
import { createLogger } from '../_dependencies/@hyperfrontend/logging/index.esm.js';
|
|
9
9
|
import { min } from '../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/math/index.esm.js';
|
|
10
10
|
import { existsSync, readFileSync, statSync, lstatSync, mkdirSync, readdirSync, rmSync, realpathSync, writeFileSync, mkdtempSync, unlinkSync, rmdirSync } from 'node:fs';
|
|
11
|
-
import { join as join$1,
|
|
11
|
+
import { join as join$1, normalize, sep, posix, isAbsolute as isAbsolute$1, relative, resolve, basename, dirname, extname, parse as parse$1 } from 'node:path';
|
|
12
12
|
import { tmpdir, platform, arch } from 'node:os';
|
|
13
|
+
import { isSafePath } from '../_shared/core/fs/guard/index.esm.js';
|
|
13
14
|
import { getFileStat, isFile, isDirectory, isSymlink, exists } from '../_shared/core/fs/stat/index.esm.js';
|
|
14
|
-
import { join, joinPosix } from '../_shared/core/path/join/index.esm.js';
|
|
15
15
|
import { normalizePath, normalizeToForwardSlashes, normalizeToNative, removeTrailingSlash, ensureTrailingSlash } from '../_shared/core/path/normalize/index.esm.js';
|
|
16
|
+
import { join, joinPosix } from '../_shared/core/path/join/index.esm.js';
|
|
16
17
|
import { resolvePath, resolveFromWorkspace, resolveRealPath, relativePath, joinPath, isAbsolute, offsetFromRoot } from '../_shared/core/path/resolve/index.esm.js';
|
|
17
18
|
import { pathSegments, getBasename, getDirname, getExtension, getFileNameWithoutExtension, parsePath } from '../_shared/core/path/segments/index.esm.js';
|
|
18
19
|
import { createStructuredError, createConfigError, createFsError, createParseError, createValidationError } from '../_shared/core/errors/structured-errors/index.esm.js';
|
|
@@ -510,6 +511,9 @@ function createFileSystemError(message, code, context) {
|
|
|
510
511
|
* ```
|
|
511
512
|
*/
|
|
512
513
|
function readFileContent(filePath, encoding = 'utf-8') {
|
|
514
|
+
if (!isSafePath(filePath)) {
|
|
515
|
+
throw createFileSystemError(`Unsafe file path: ${filePath}`, 'FS_READ_ERROR', { path: filePath, operation: 'read' });
|
|
516
|
+
}
|
|
513
517
|
if (!existsSync(filePath)) {
|
|
514
518
|
fsLogger.debug('File not found', { path: filePath });
|
|
515
519
|
throw createFileSystemError(`File not found: ${filePath}`, 'FS_NOT_FOUND', { path: filePath, operation: 'read' });
|
|
@@ -536,6 +540,9 @@ function readFileContent(filePath, encoding = 'utf-8') {
|
|
|
536
540
|
* ```
|
|
537
541
|
*/
|
|
538
542
|
function readFileBuffer(filePath) {
|
|
543
|
+
if (!isSafePath(filePath)) {
|
|
544
|
+
throw createFileSystemError(`Unsafe file path: ${filePath}`, 'FS_READ_ERROR', { path: filePath, operation: 'read' });
|
|
545
|
+
}
|
|
539
546
|
if (!existsSync(filePath)) {
|
|
540
547
|
throw createFileSystemError(`File not found: ${filePath}`, 'FS_NOT_FOUND', { path: filePath, operation: 'read' });
|
|
541
548
|
}
|
|
@@ -562,7 +569,7 @@ function readFileBuffer(filePath) {
|
|
|
562
569
|
* ```
|
|
563
570
|
*/
|
|
564
571
|
function readFileIfExists(filePath, encoding = 'utf-8') {
|
|
565
|
-
if (!existsSync(filePath)) {
|
|
572
|
+
if (!isSafePath(filePath) || !existsSync(filePath)) {
|
|
566
573
|
return null;
|
|
567
574
|
}
|
|
568
575
|
try {
|
|
@@ -594,6 +601,9 @@ function readFileIfExists(filePath, encoding = 'utf-8') {
|
|
|
594
601
|
* ```
|
|
595
602
|
*/
|
|
596
603
|
function readJsonFile(filePath, options) {
|
|
604
|
+
if (!isSafePath(filePath)) {
|
|
605
|
+
throw createFileSystemError(`Unsafe file path: ${filePath}`, 'FS_READ_ERROR', { path: filePath, operation: 'read' });
|
|
606
|
+
}
|
|
597
607
|
if (!existsSync(filePath)) {
|
|
598
608
|
if (options && 'default' in options) {
|
|
599
609
|
fsLogger.debug('JSON file not found, using default', { path: filePath });
|
|
@@ -633,7 +643,7 @@ function readJsonFile(filePath, options) {
|
|
|
633
643
|
* ```
|
|
634
644
|
*/
|
|
635
645
|
function readJsonFileIfExists(filePath) {
|
|
636
|
-
if (!existsSync(filePath)) {
|
|
646
|
+
if (!isSafePath(filePath) || !existsSync(filePath)) {
|
|
637
647
|
return null;
|
|
638
648
|
}
|
|
639
649
|
try {
|
package/core/path/index.cjs.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const node_path = require('node:path');
|
|
4
3
|
const node_fs = require('node:fs');
|
|
5
|
-
const
|
|
4
|
+
const node_path = require('node:path');
|
|
6
5
|
const { normalizePath, normalizeToForwardSlashes, normalizeToNative, removeTrailingSlash, ensureTrailingSlash } = require('../../_shared/core/path/normalize/index.cjs.js');
|
|
6
|
+
const { isWithinRoot } = require('../../_shared/core/path/confine/index.cjs.js');
|
|
7
|
+
const { join, joinPosix } = require('../../_shared/core/path/join/index.cjs.js');
|
|
7
8
|
const { resolvePath, resolveFromWorkspace, resolveRealPath, relativePath, joinPath, isAbsolute, offsetFromRoot } = require('../../_shared/core/path/resolve/index.cjs.js');
|
|
8
9
|
const { pathSegments, getBasename, getDirname, getExtension, getFileNameWithoutExtension, parsePath } = require('../../_shared/core/path/segments/index.cjs.js');
|
|
9
10
|
|
|
@@ -13,6 +14,7 @@ exports.getDirname = getDirname;
|
|
|
13
14
|
exports.getExtension = getExtension;
|
|
14
15
|
exports.getFileNameWithoutExtension = getFileNameWithoutExtension;
|
|
15
16
|
exports.isAbsolute = isAbsolute;
|
|
17
|
+
exports.isWithinRoot = isWithinRoot;
|
|
16
18
|
exports.join = join;
|
|
17
19
|
exports.joinPath = joinPath;
|
|
18
20
|
exports.joinPosix = joinPosix;
|
package/core/path/index.d.ts
CHANGED
|
@@ -99,6 +99,27 @@ declare function getFileNameWithoutExtension(filePath: string): string;
|
|
|
99
99
|
*/
|
|
100
100
|
declare function parsePath(filePath: string): ParsedPath;
|
|
101
101
|
|
|
102
|
+
/**
|
|
103
|
+
* Reports whether `candidate` resolves to a location inside `root`.
|
|
104
|
+
*
|
|
105
|
+
* The lexical check runs first and rejects `..` traversal and absolute escapes
|
|
106
|
+
* with no filesystem access at all, so a hostile path is never stat-ed. Only a
|
|
107
|
+
* path that is already lexically contained is then resolved through symlinks, so
|
|
108
|
+
* an in-tree link cannot tunnel outside the root — and that realpath touches
|
|
109
|
+
* only paths the caller would legitimately read anyway.
|
|
110
|
+
*
|
|
111
|
+
* @param root - The directory the candidate must stay within.
|
|
112
|
+
* @param candidate - The path to validate (resolved relative to the cwd if not absolute).
|
|
113
|
+
* @returns True when the candidate is the root or contained within it.
|
|
114
|
+
*
|
|
115
|
+
* @example Confining a resolved import target
|
|
116
|
+
* ```typescript
|
|
117
|
+
* isWithinRoot('/project', '/project/src/index.ts') // true
|
|
118
|
+
* isWithinRoot('/project', '/project/../etc/passwd') // false
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
declare function isWithinRoot(root: string, candidate: string): boolean;
|
|
122
|
+
|
|
102
123
|
/**
|
|
103
124
|
* Join path segments.
|
|
104
125
|
* Uses platform-specific separators (e.g., / or \).
|
|
@@ -302,5 +323,5 @@ declare function isAbsolute(filePath: string): boolean;
|
|
|
302
323
|
*/
|
|
303
324
|
declare function offsetFromRoot(filePath: string): string;
|
|
304
325
|
|
|
305
|
-
export { ensureTrailingSlash, getBasename, getDirname, getExtension, getFileNameWithoutExtension, isAbsolute, join, joinPath, joinPosix, normalizePath, normalizeToForwardSlashes, normalizeToNative, offsetFromRoot, parsePath, pathSegments, relativePath, removeTrailingSlash, resolveFromWorkspace, resolvePath, resolveRealPath };
|
|
326
|
+
export { ensureTrailingSlash, getBasename, getDirname, getExtension, getFileNameWithoutExtension, isAbsolute, isWithinRoot, join, joinPath, joinPosix, normalizePath, normalizeToForwardSlashes, normalizeToNative, offsetFromRoot, parsePath, pathSegments, relativePath, removeTrailingSlash, resolveFromWorkspace, resolvePath, resolveRealPath };
|
|
306
327
|
export type { ParsedPath };
|
package/core/path/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../../libs/project-scope/src/core/path/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAC5C,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AACxC,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AACnI,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,cAAc,EAAE,YAAY,EAAE,oBAAoB,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAClI,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,2BAA2B,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../../libs/project-scope/src/core/path/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AACxC,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AACxC,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AACnI,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,cAAc,EAAE,YAAY,EAAE,oBAAoB,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAClI,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,2BAA2B,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA"}
|
package/core/path/index.esm.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { join as join$1, posix, normalize, sep, isAbsolute as isAbsolute$1, relative, resolve, basename, dirname, extname, parse } from 'node:path';
|
|
2
1
|
import { existsSync, realpathSync } from 'node:fs';
|
|
3
|
-
import { join,
|
|
2
|
+
import { normalize, sep, resolve, join as join$1, posix, isAbsolute as isAbsolute$1, relative, basename, dirname, extname, parse } from 'node:path';
|
|
4
3
|
import { normalizePath, normalizeToForwardSlashes, normalizeToNative, removeTrailingSlash, ensureTrailingSlash } from '../../_shared/core/path/normalize/index.esm.js';
|
|
4
|
+
import { isWithinRoot } from '../../_shared/core/path/confine/index.esm.js';
|
|
5
|
+
import { join, joinPosix } from '../../_shared/core/path/join/index.esm.js';
|
|
5
6
|
import { resolvePath, resolveFromWorkspace, resolveRealPath, relativePath, joinPath, isAbsolute, offsetFromRoot } from '../../_shared/core/path/resolve/index.esm.js';
|
|
6
7
|
import { pathSegments, getBasename, getDirname, getExtension, getFileNameWithoutExtension, parsePath } from '../../_shared/core/path/segments/index.esm.js';
|
|
7
8
|
|
|
8
|
-
export { ensureTrailingSlash, getBasename, getDirname, getExtension, getFileNameWithoutExtension, isAbsolute, join, joinPath, joinPosix, normalizePath, normalizeToForwardSlashes, normalizeToNative, offsetFromRoot, parsePath, pathSegments, relativePath, removeTrailingSlash, resolveFromWorkspace, resolvePath, resolveRealPath };
|
|
9
|
+
export { ensureTrailingSlash, getBasename, getDirname, getExtension, getFileNameWithoutExtension, isAbsolute, isWithinRoot, join, joinPath, joinPosix, normalizePath, normalizeToForwardSlashes, normalizeToNative, offsetFromRoot, parsePath, pathSegments, relativePath, removeTrailingSlash, resolveFromWorkspace, resolvePath, resolveRealPath };
|
|
@@ -10,7 +10,9 @@ const index_cjs_js$3 = require('../../_dependencies/@hyperfrontend/immutable-api
|
|
|
10
10
|
const index_cjs_js$5 = require('../../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/json/index.cjs.js');
|
|
11
11
|
const index_cjs_js$1 = require('../../_dependencies/@hyperfrontend/logging/index.cjs.js');
|
|
12
12
|
const index_cjs_js$6 = require('../../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/error/index.cjs.js');
|
|
13
|
+
const { isSafePath } = require('../../_shared/core/fs/guard/index.cjs.js');
|
|
13
14
|
const { isFile, isDirectory, exists } = require('../../_shared/core/fs/stat/index.cjs.js');
|
|
15
|
+
const { isWithinRoot } = require('../../_shared/core/path/confine/index.cjs.js');
|
|
14
16
|
|
|
15
17
|
/**
|
|
16
18
|
* Global log level registry.
|
|
@@ -197,6 +199,9 @@ function createFileSystemError(message, code, context) {
|
|
|
197
199
|
* ```
|
|
198
200
|
*/
|
|
199
201
|
function readFileContent(filePath, encoding = 'utf-8') {
|
|
202
|
+
if (!isSafePath(filePath)) {
|
|
203
|
+
throw createFileSystemError(`Unsafe file path: ${filePath}`, 'FS_READ_ERROR', { path: filePath, operation: 'read' });
|
|
204
|
+
}
|
|
200
205
|
if (!node_fs.existsSync(filePath)) {
|
|
201
206
|
fsLogger.debug('File not found', { path: filePath });
|
|
202
207
|
throw createFileSystemError(`File not found: ${filePath}`, 'FS_NOT_FOUND', { path: filePath, operation: 'read' });
|
|
@@ -225,7 +230,7 @@ function readFileContent(filePath, encoding = 'utf-8') {
|
|
|
225
230
|
* ```
|
|
226
231
|
*/
|
|
227
232
|
function readFileIfExists(filePath, encoding = 'utf-8') {
|
|
228
|
-
if (!node_fs.existsSync(filePath)) {
|
|
233
|
+
if (!isSafePath(filePath) || !node_fs.existsSync(filePath)) {
|
|
229
234
|
return null;
|
|
230
235
|
}
|
|
231
236
|
try {
|
|
@@ -434,6 +439,10 @@ function resolveImportPath(importPath, fromFile, projectPath, extensions) {
|
|
|
434
439
|
}
|
|
435
440
|
const fromDir = node_path.dirname(fromFile);
|
|
436
441
|
const absolutePath = node_path.resolve(fromDir, importPath);
|
|
442
|
+
// why: An import string comes from untrusted source code; reject targets that escape the project root before any stat, so a hostile `../../etc/passwd` can't probe the filesystem.
|
|
443
|
+
if (!isWithinRoot(projectPath, absolutePath)) {
|
|
444
|
+
return null;
|
|
445
|
+
}
|
|
437
446
|
if (exists(absolutePath)) {
|
|
438
447
|
if (isFile(absolutePath)) {
|
|
439
448
|
return node_path.relative(projectPath, absolutePath);
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
import { join,
|
|
1
|
+
import { join, normalize, sep, resolve, relative, dirname } from 'node:path';
|
|
2
2
|
import { createMap } from '../../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/map/index.esm.js';
|
|
3
3
|
import { freeze, entries, keys, defineProperties, values } from '../../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/object/index.esm.js';
|
|
4
4
|
import { createSet } from '../../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/set/index.esm.js';
|
|
5
|
-
import { existsSync, readFileSync, statSync, lstatSync, readdirSync } from 'node:fs';
|
|
5
|
+
import { existsSync, readFileSync, statSync, lstatSync, readdirSync, realpathSync } from 'node:fs';
|
|
6
6
|
import { isArray } from '../../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/array/index.esm.js';
|
|
7
7
|
import { error, warn, log, info, debug } from '../../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/console/index.esm.js';
|
|
8
8
|
import { stringify, parse } from '../../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/json/index.esm.js';
|
|
9
9
|
import { createLogger } from '../../_dependencies/@hyperfrontend/logging/index.esm.js';
|
|
10
10
|
import { createError } from '../../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/error/index.esm.js';
|
|
11
|
+
import { isSafePath } from '../../_shared/core/fs/guard/index.esm.js';
|
|
11
12
|
import { isFile, isDirectory, exists } from '../../_shared/core/fs/stat/index.esm.js';
|
|
13
|
+
import { isWithinRoot } from '../../_shared/core/path/confine/index.esm.js';
|
|
12
14
|
|
|
13
15
|
/**
|
|
14
16
|
* Global log level registry.
|
|
@@ -195,6 +197,9 @@ function createFileSystemError(message, code, context) {
|
|
|
195
197
|
* ```
|
|
196
198
|
*/
|
|
197
199
|
function readFileContent(filePath, encoding = 'utf-8') {
|
|
200
|
+
if (!isSafePath(filePath)) {
|
|
201
|
+
throw createFileSystemError(`Unsafe file path: ${filePath}`, 'FS_READ_ERROR', { path: filePath, operation: 'read' });
|
|
202
|
+
}
|
|
198
203
|
if (!existsSync(filePath)) {
|
|
199
204
|
fsLogger.debug('File not found', { path: filePath });
|
|
200
205
|
throw createFileSystemError(`File not found: ${filePath}`, 'FS_NOT_FOUND', { path: filePath, operation: 'read' });
|
|
@@ -223,7 +228,7 @@ function readFileContent(filePath, encoding = 'utf-8') {
|
|
|
223
228
|
* ```
|
|
224
229
|
*/
|
|
225
230
|
function readFileIfExists(filePath, encoding = 'utf-8') {
|
|
226
|
-
if (!existsSync(filePath)) {
|
|
231
|
+
if (!isSafePath(filePath) || !existsSync(filePath)) {
|
|
227
232
|
return null;
|
|
228
233
|
}
|
|
229
234
|
try {
|
|
@@ -432,6 +437,10 @@ function resolveImportPath(importPath, fromFile, projectPath, extensions) {
|
|
|
432
437
|
}
|
|
433
438
|
const fromDir = dirname(fromFile);
|
|
434
439
|
const absolutePath = resolve(fromDir, importPath);
|
|
440
|
+
// why: An import string comes from untrusted source code; reject targets that escape the project root before any stat, so a hostile `../../etc/passwd` can't probe the filesystem.
|
|
441
|
+
if (!isWithinRoot(projectPath, absolutePath)) {
|
|
442
|
+
return null;
|
|
443
|
+
}
|
|
435
444
|
if (exists(absolutePath)) {
|
|
436
445
|
if (isFile(absolutePath)) {
|
|
437
446
|
return relative(projectPath, absolutePath);
|
|
@@ -10,6 +10,7 @@ const index_cjs_js$4 = require('../../_dependencies/@hyperfrontend/immutable-api
|
|
|
10
10
|
const index_cjs_js$6 = require('../../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/json/index.cjs.js');
|
|
11
11
|
const index_cjs_js$3 = require('../../_dependencies/@hyperfrontend/logging/index.cjs.js');
|
|
12
12
|
const index_cjs_js$7 = require('../../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/error/index.cjs.js');
|
|
13
|
+
const { isSafePath } = require('../../_shared/core/fs/guard/index.cjs.js');
|
|
13
14
|
const { isDirectory, exists } = require('../../_shared/core/fs/stat/index.cjs.js');
|
|
14
15
|
const { createCache } = require('../../_shared/core/cache/index.cjs.js');
|
|
15
16
|
const { matchGlobPattern } = require('../../_shared/core/patterns/glob/index.cjs.js');
|
|
@@ -198,7 +199,7 @@ function createFileSystemError(message, code, context) {
|
|
|
198
199
|
* ```
|
|
199
200
|
*/
|
|
200
201
|
function readFileIfExists(filePath, encoding = 'utf-8') {
|
|
201
|
-
if (!node_fs.existsSync(filePath)) {
|
|
202
|
+
if (!isSafePath(filePath) || !node_fs.existsSync(filePath)) {
|
|
202
203
|
return null;
|
|
203
204
|
}
|
|
204
205
|
try {
|
|
@@ -8,6 +8,7 @@ import { error, warn, log, info, debug } from '../../_dependencies/@hyperfronten
|
|
|
8
8
|
import { stringify, parse } from '../../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/json/index.esm.js';
|
|
9
9
|
import { createLogger } from '../../_dependencies/@hyperfrontend/logging/index.esm.js';
|
|
10
10
|
import { createError } from '../../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/error/index.esm.js';
|
|
11
|
+
import { isSafePath } from '../../_shared/core/fs/guard/index.esm.js';
|
|
11
12
|
import { isDirectory, exists } from '../../_shared/core/fs/stat/index.esm.js';
|
|
12
13
|
import { createCache } from '../../_shared/core/cache/index.esm.js';
|
|
13
14
|
import { matchGlobPattern } from '../../_shared/core/patterns/glob/index.esm.js';
|
|
@@ -196,7 +197,7 @@ function createFileSystemError(message, code, context) {
|
|
|
196
197
|
* ```
|
|
197
198
|
*/
|
|
198
199
|
function readFileIfExists(filePath, encoding = 'utf-8') {
|
|
199
|
-
if (!existsSync(filePath)) {
|
|
200
|
+
if (!isSafePath(filePath) || !existsSync(filePath)) {
|
|
200
201
|
return null;
|
|
201
202
|
}
|
|
202
203
|
try {
|
|
@@ -11,6 +11,7 @@ const node_path = require('node:path');
|
|
|
11
11
|
const index_cjs_js$7 = require('../../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/error/index.cjs.js');
|
|
12
12
|
const node_fs = require('node:fs');
|
|
13
13
|
const index_cjs_js$8 = require('../../_dependencies/@hyperfrontend/immutable-api-utils/built-in-copy/math/index.cjs.js');
|
|
14
|
+
const { isSafePath } = require('../../_shared/core/fs/guard/index.cjs.js');
|
|
14
15
|
const { isDirectory, exists } = require('../../_shared/core/fs/stat/index.cjs.js');
|
|
15
16
|
const { join } = require('../../_shared/core/path/join/index.cjs.js');
|
|
16
17
|
const { createCache } = require('../../_shared/core/cache/index.cjs.js');
|
|
@@ -201,7 +202,7 @@ function createFileSystemError(message, code, context) {
|
|
|
201
202
|
* ```
|
|
202
203
|
*/
|
|
203
204
|
function readFileIfExists(filePath, encoding = 'utf-8') {
|
|
204
|
-
if (!node_fs.existsSync(filePath)) {
|
|
205
|
+
if (!isSafePath(filePath) || !node_fs.existsSync(filePath)) {
|
|
205
206
|
return null;
|
|
206
207
|
}
|
|
207
208
|
try {
|