Spotted what might be an issue in yarn.lock around line 7367.
VULNERABILITY (CVE-2025-71329, HIGH): The image-size package at 2.0.2, pinned in yarn.lock (lines 7367-7374), contains an infinite-loop denial-of-service in its JXL and HEIF parsers. When a crafted image contains a recognized box (container atom) whose size field is 0, the parser's offset never advances, so the parsing loop never terminates. IMPACT: Unlike typical DoS bugs, this permanently blocks the Node.js event loop - it is not just slow, the entire process (and every other request it serves) hangs indefinitely until restarted. Any code path that parses untrusted image buffers (file uploads, avatar processing, image URL fetching, thumbnail generation) becomes trivially exploitable by an unauthenticated attacker with a single tiny crafted file. Risk: HIGH - easy to exploit, no authentication typically required, and effect is total application unavailability. No confidentiality/integrity impact (no RCE or data exposure), but availability impact is severe. NOTE: No fixed version is published yet; remediation requires upgrading as soon as a patched release exists and applying a defensive workaround (worker-thread isolation with timeout) in the interim.
Something like this might fix it:
Step 1 - Upgrade the dependency once a patched release is available (do NOT hand-edit yarn.lock; regenerate it):
```diff
--- a/package.json
+++ b/package.json
@@
- "image-size": "^2.0.2"
+ "image-size": "^2.0.3" # first release containing the infinite-loop fix
```
Then run: `yarn up image-size && yarn audit`
Step 2 - Interim mitigation (safe against CVE-2025-71329 even without a fixed version): never run `imageSize()` on the main event loop; isolate it in a Worker with a hard timeout so a wedged parse cannot hang the server.
```diff
--- /dev/null
+++ b/src/utils/image-size-worker.js
@@
+const { parentPort } = require('worker_threads');
+const { imageSize } = require('image-size');
+
+parentPort.on('message', (buffer) => {
+ try {
+ parentPort.postMessage({ ok: true, result: imageSize(buffer) });
+ } catch (err) {
+ parentPort.postMessage({ ok: false, error: String(err) });
+ }
+});
```
```diff
--- a/src/utils/image-size.js
+++ b/src/utils/image-size.js
@@
-import { imageSize } from 'image-size';
+const { Worker } = require('worker_threads');
+
+const DEFAULT_TIMEOUT_MS = 2000;
+const MAX_BYTES = 10 * 1024 * 1024; // 10 MB policy limit; reject oversized inputs early
+
+const worker = new Worker(require.resolve('./image-size-worker'));
+
+function safeImageSize(buffer, timeoutMs = DEFAULT_TIMEOUT_MS) {
+ return new Promise((resolve, reject) => {
+ if (!Buffer.isBuffer(buffer) || buffer.length === 0) {
+ return reject(new Error('invalid image: empty or non-buffer payload'));
+ }
+ if (buffer.length > MAX_BYTES) {
+ return reject(new Error('invalid image: exceeds maximum allowed size'));
+ }
+
+ const timer = setTimeout(() => {
+ // CVE-2025-71329: zero-size JXL/HEIF box wedges the parser.
+ // Terminating the worker unblocks the event loop; respawn a fresh one.
+ worker.terminate();
+ reject(new Error('image parsing timed out (possible malicious image)'));
+ }, timeoutMs);
+
+ worker.once('message', (msg) => {
+ clearTimeout(timer);
+ msg.ok ? resolve(msg.result) : reject(new Error(msg.error));
+ });
+
+ worker.postMessage(buffer, [buffer.buffer]); // transfer, avoid extra copy
+ });
+}
+
+module.exports = { safeImageSize };
```
Key points: (1) the worker `terminate()` on timeout guarantees the main event loop can never be permanently blocked, even against an unfixed parser; (2) early size validation rejects obviously malicious payloads before parsing; (3) call sites must switch from sync `imageSize(buf)` to `await safeImageSize(buf)`. Once a fixed version (>2.0.2) ships, the worker isolation can be kept as defense-in-depth.
For reference: rule CVE-2025-71329. Rated high.
If I have misread how this is used, sorry for the noise — feel free to close.
Found with automated scanning (RedGem) and reviewed before opening. If it is not useful, closing it is completely fine.
Spotted what might be an issue in
yarn.lockaround line 7367.VULNERABILITY (CVE-2025-71329, HIGH): The
image-sizepackage at 2.0.2, pinned in yarn.lock (lines 7367-7374), contains an infinite-loop denial-of-service in its JXL and HEIF parsers. When a crafted image contains a recognized box (container atom) whose size field is 0, the parser's offset never advances, so the parsing loop never terminates. IMPACT: Unlike typical DoS bugs, this permanently blocks the Node.js event loop - it is not just slow, the entire process (and every other request it serves) hangs indefinitely until restarted. Any code path that parses untrusted image buffers (file uploads, avatar processing, image URL fetching, thumbnail generation) becomes trivially exploitable by an unauthenticated attacker with a single tiny crafted file. Risk: HIGH - easy to exploit, no authentication typically required, and effect is total application unavailability. No confidentiality/integrity impact (no RCE or data exposure), but availability impact is severe. NOTE: No fixed version is published yet; remediation requires upgrading as soon as a patched release exists and applying a defensive workaround (worker-thread isolation with timeout) in the interim.Something like this might fix it:
For reference: rule
CVE-2025-71329. Rated high.If I have misread how this is used, sorry for the noise — feel free to close.
Found with automated scanning (RedGem) and reviewed before opening. If it is not useful, closing it is completely fine.