zone5 1.6.0 → 1.6.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.
- package/dist/processor/file.js +2 -6
- package/dist/remark.js +32 -2
- package/dist/vite.js +11 -2
- package/package.json +1 -1
package/dist/processor/file.js
CHANGED
|
@@ -10,12 +10,8 @@ export const sourceFileHash = (sourceBaseDir, sourceFile) => {
|
|
|
10
10
|
return hash.digest('hex');
|
|
11
11
|
};
|
|
12
12
|
export const ensureDirectoryExists = async (dirPath) => {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
16
|
-
catch {
|
|
17
|
-
await mkdir(dirPath, { recursive: true });
|
|
18
|
-
}
|
|
13
|
+
// mkdir with recursive: true is idempotent - no need to check if dir exists first
|
|
14
|
+
await mkdir(dirPath, { recursive: true });
|
|
19
15
|
};
|
|
20
16
|
export const fileExists = async (filePath) => {
|
|
21
17
|
try {
|
package/dist/remark.js
CHANGED
|
@@ -125,6 +125,28 @@ function collectImageData(images, existingKeys) {
|
|
|
125
125
|
};
|
|
126
126
|
});
|
|
127
127
|
}
|
|
128
|
+
/**
|
|
129
|
+
* Validate and sanitize an image URL for safe use in import statements.
|
|
130
|
+
* Prevents import path injection by ensuring URLs are valid relative paths.
|
|
131
|
+
*/
|
|
132
|
+
function validateImageUrl(url) {
|
|
133
|
+
// Remove the ?z5 suffix for validation
|
|
134
|
+
const cleanUrl = url.replace(/\?z5$/, '');
|
|
135
|
+
// Block URLs with protocol schemes (http:, https:, file:, data:, javascript:, etc.)
|
|
136
|
+
if (cleanUrl.match(/^[a-zA-Z][a-zA-Z0-9+.-]*:/)) {
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
// Block URLs with null bytes or other control characters (ASCII 0-31 and 127)
|
|
140
|
+
// eslint-disable-next-line no-control-regex
|
|
141
|
+
if (/[\x00-\x1f\x7f]/.test(cleanUrl)) {
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
// Block URLs that could escape the import statement (quotes, backticks, newlines)
|
|
145
|
+
if (cleanUrl.match(/['"`\n\r]/)) {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
128
150
|
/**
|
|
129
151
|
* Generate a unique import key for an image URL
|
|
130
152
|
*/
|
|
@@ -146,10 +168,18 @@ function generateImportKey(url, existingKeys) {
|
|
|
146
168
|
return key;
|
|
147
169
|
}
|
|
148
170
|
/**
|
|
149
|
-
* Check if a node is a Zone5 image (ends with ?z5)
|
|
171
|
+
* Check if a node is a Zone5 image (ends with ?z5) with a valid URL
|
|
150
172
|
*/
|
|
151
173
|
function isZ5Image(node) {
|
|
152
|
-
|
|
174
|
+
if (node.type !== 'image' || typeof node.url !== 'string' || !node.url.endsWith('?z5')) {
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
// Security: Validate URL to prevent import path injection
|
|
178
|
+
if (!validateImageUrl(node.url)) {
|
|
179
|
+
console.warn(`Zone5: Skipping image with invalid URL: ${node.url}`);
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
182
|
+
return true;
|
|
153
183
|
}
|
|
154
184
|
/**
|
|
155
185
|
* Check if a paragraph contains only a single Z5 image
|
package/dist/vite.js
CHANGED
|
@@ -3,7 +3,7 @@ import { dataToEsm } from '@rollup/pluginutils';
|
|
|
3
3
|
import mime from 'mime';
|
|
4
4
|
import { createReadStream } from 'node:fs';
|
|
5
5
|
import { cp, readFile, stat } from 'node:fs/promises';
|
|
6
|
-
import { dirname, join } from 'node:path';
|
|
6
|
+
import { dirname, join, resolve } from 'node:path';
|
|
7
7
|
import { load } from './config.js';
|
|
8
8
|
import processor, {} from './processor/index.js';
|
|
9
9
|
const tracer = trace.getTracer('zone5-vite');
|
|
@@ -18,7 +18,16 @@ const serve = (basePath, cacheDir) => async (req, res, next) => {
|
|
|
18
18
|
const [, id] = req.url.split(basePath);
|
|
19
19
|
try {
|
|
20
20
|
const path = decodeURIComponent(id);
|
|
21
|
-
const src =
|
|
21
|
+
const src = resolve(cacheDir, path);
|
|
22
|
+
// Security: Prevent path traversal attacks by ensuring the resolved path
|
|
23
|
+
// is within the cache directory
|
|
24
|
+
const normalizedCacheDir = resolve(cacheDir);
|
|
25
|
+
if (!src.startsWith(normalizedCacheDir + '/') && src !== normalizedCacheDir) {
|
|
26
|
+
console.error(`Zone5: Blocked path traversal attempt: ${path}`);
|
|
27
|
+
res.statusCode = 403;
|
|
28
|
+
res.end('Forbidden');
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
22
31
|
try {
|
|
23
32
|
const image = createReadStream(src);
|
|
24
33
|
const stats = await stat(src);
|