VYPR
Critical severityCISA KEVOSV Advisory· Published Dec 19, 2025· Updated Mar 12, 2026

n8n Vulnerable to Remote Code Execution via Expression Injection

CVE-2025-68613

Description

n8n is an open source workflow automation platform. Versions starting with 0.211.0 and prior to 1.120.4, 1.121.1, and 1.122.0 contain a critical Remote Code Execution (RCE) vulnerability in their workflow expression evaluation system. Under certain conditions, expressions supplied by authenticated users during workflow configuration may be evaluated in an execution context that is not sufficiently isolated from the underlying runtime. An authenticated attacker could abuse this behavior to execute arbitrary code with the privileges of the n8n process. Successful exploitation may lead to full compromise of the affected instance, including unauthorized access to sensitive data, modification of workflows, and execution of system-level operations. This issue has been fixed in versions 1.120.4, 1.121.1, and 1.122.0. Users are strongly advised to upgrade to a patched version, which introduces additional safeguards to restrict expression evaluation. If upgrading is not immediately possible, administrators should consider the following temporary mitigations: Limit workflow creation and editing permissions to fully trusted users only; and/or deploy n8n in a hardened environment with restricted operating system privileges and network access to reduce the impact of potential exploitation. These workarounds do not fully eliminate the risk and should only be used as short-term measures.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
n8nnpm
>= 0.211.0, < 1.120.41.120.4
n8nnpm
>= 1.121.0, < 1.121.11.121.1

Affected products

1
  • Range: 8n-editor-ui@0.70.0, n8n-core@0.10.0, n8n-core@0.100.0, …

Patches

3
39a2d1d60edd

Merge commit from fork

https://github.com/n8n-io/n8nIván OvejeroNov 18, 2025via ghsa
9 files changed · +253 119
  • package.json+1 0 modified
    @@ -88,6 +88,7 @@
           "sqlite3"
         ],
         "overrides": {
    +      "ast-types": "0.16.1",
           "@azure/identity": "^4.3.0",
           "@lezer/common": "^1.2.0",
           "@mistralai/mistralai": "^1.10.0",
    
  • packages/workflow/package.json+1 1 modified
    @@ -52,7 +52,7 @@
       "dependencies": {
         "@n8n/errors": "workspace:^",
         "@n8n/tournament": "1.0.6",
    -    "ast-types": "0.15.2",
    +    "ast-types": "0.16.1",
         "callsites": "catalog:",
         "esprima-next": "5.8.4",
         "form-data": "catalog:",
    
  • packages/workflow/src/expression-evaluator-proxy.ts+6 2 modified
    @@ -1,13 +1,17 @@
     import { Tournament } from '@n8n/tournament';
     
    -import { DollarSignValidator, PrototypeSanitizer } from './expression-sandboxing';
    +import {
    +	DollarSignValidator,
    +	FunctionThisSanitizer,
    +	PrototypeSanitizer,
    +} from './expression-sandboxing';
     
     type Evaluator = (expr: string, data: unknown) => string | null | (() => unknown);
     type ErrorHandler = (error: Error) => void;
     
     const errorHandler: ErrorHandler = () => {};
     const tournamentEvaluator = new Tournament(errorHandler, undefined, undefined, {
    -	before: [],
    +	before: [FunctionThisSanitizer],
     	after: [PrototypeSanitizer, DollarSignValidator],
     });
     const evaluator: Evaluator = tournamentEvaluator.execute.bind(tournamentEvaluator);
    
  • packages/workflow/src/expression-sandboxing.ts+68 1 modified
    @@ -1,4 +1,4 @@
    -import { type ASTAfterHook, astBuilders as b, astVisit } from '@n8n/tournament';
    +import { type ASTAfterHook, type ASTBeforeHook, astBuilders as b, astVisit } from '@n8n/tournament';
     
     import { ExpressionError } from './errors';
     import { isSafeObjectProperty } from './utils';
    @@ -8,6 +8,10 @@ const sanitizerIdentifier = b.identifier(sanitizerName);
     
     export const DOLLAR_SIGN_ERROR = 'Cannot access "$" without calling it as a function';
     
    +const EMPTY_CONTEXT = b.objectExpression([
    +	b.property('init', b.identifier('process'), b.objectExpression([])),
    +]);
    +
     /**
      * Helper to check if an expression is a valid property access with $ as the property.
      * Returns true for obj.$ or obj.nested.$ but false for bare $ or other expression contexts.
    @@ -49,6 +53,69 @@ const isValidDollarPropertyAccess = (expr: unknown): boolean => {
     	return isPropertyDollar && !isObjectDollar && isObjectValid;
     };
     
    +/**
    + * Prevents regular functions from binding their `this` to the Node.js global.
    + */
    +export const FunctionThisSanitizer: ASTBeforeHook = (ast, dataNode) => {
    +	astVisit(ast, {
    +		visitCallExpression(path) {
    +			const { node } = path;
    +
    +			if (node.callee.type !== 'FunctionExpression') {
    +				this.traverse(path);
    +				return;
    +			}
    +
    +			const fnExpression = node.callee;
    +
    +			/**
    +			 * Called function expressions (IIFEs) - both anonymous and named:
    +			 *
    +			 * ```js
    +			 * (function(x) { return x * 2; })(5)
    +			 * (function factorial(n) { return n <= 1 ? 1 : n * factorial(n-1); })(5)
    +			 *
    +			 * // become
    +			 *
    +			 * (function(x) { return x * 2; }).call({ process: {} }, 5)
    +			 * (function factorial(n) { return n <= 1 ? 1 : n * factorial(n-1); }).call({ process: {} }, 5)
    +			 * ```
    +			 */
    +			this.traverse(path); // depth first to transform inside out
    +			const callExpression = b.callExpression(
    +				b.memberExpression(fnExpression, b.identifier('call')),
    +				[EMPTY_CONTEXT, ...node.arguments],
    +			);
    +			path.replace(callExpression);
    +			return false;
    +		},
    +
    +		visitFunctionExpression(path) {
    +			const { node } = path;
    +
    +			/**
    +			 * Callable function expressions (callbacks) - both anonymous and named:
    +			 *
    +			 * ```js
    +			 * [1, 2, 3].map(function(n) { return n * 2; })
    +			 * [1, 2, 3].map(function factorial(n) { return n <= 1 ? 1 : n * factorial(n-1); })
    +			 *
    +			 * // become
    +			 *
    +			 * [1, 2, 3].map((function(n) { return n * 2; }).bind({ process: {} }))
    +			 * [1, 2, 3].map((function factorial(n) { return n <= 1 ? 1 : n * factorial(n-1); }).bind({ process: {} }))
    +			 * ```
    +			 */
    +			this.traverse(path);
    +			const boundFunction = b.callExpression(b.memberExpression(node, b.identifier('bind')), [
    +				EMPTY_CONTEXT,
    +			]);
    +			path.replace(boundFunction);
    +			return false;
    +		},
    +	});
    +};
    +
     /**
      * Validates that the $ identifier is only used in allowed contexts.
      * This prevents user errors like `{{ $ }}` which would return the function object itself.
    
  • packages/workflow/src/extensions/expression-extension.ts+1 1 modified
    @@ -1,5 +1,5 @@
     /* eslint-disable @typescript-eslint/no-unsafe-member-access */
    -import type { ExpressionKind } from 'ast-types/gen/kinds';
    +import type { ExpressionKind } from 'ast-types/lib/gen/kinds';
     import type { Config as EsprimaConfig } from 'esprima-next';
     import { parse as esprimaParse } from 'esprima-next';
     import { DateTime } from 'luxon';
    
  • packages/workflow/src/utils.ts+9 1 modified
    @@ -332,7 +332,15 @@ export function hasKey<T extends PropertyKey>(value: unknown, key: T): value is
     	return value !== null && typeof value === 'object' && value.hasOwnProperty(key);
     }
     
    -const unsafeObjectProperties = new Set(['__proto__', 'prototype', 'constructor', 'getPrototypeOf']);
    +const unsafeObjectProperties = new Set([
    +	'__proto__',
    +	'prototype',
    +	'constructor',
    +	'getPrototypeOf',
    +	'mainModule',
    +	'binding',
    +	'_load',
    +]);
     
     /**
      * Checks if a property key is safe to use on an object, preventing prototype pollution.
    
  • packages/workflow/test/expression-sandboxing.test.ts+140 1 modified
    @@ -2,6 +2,7 @@ import { Tournament } from '@n8n/tournament';
     
     import {
     	DollarSignValidator,
    +	FunctionThisSanitizer,
     	PrototypeSanitizer,
     	sanitizer,
     	DOLLAR_SIGN_ERROR,
    @@ -14,7 +15,7 @@ const tournament = new Tournament(
     	undefined,
     	undefined,
     	{
    -		before: [],
    +		before: [FunctionThisSanitizer],
     		after: [PrototypeSanitizer, DollarSignValidator],
     	},
     );
    @@ -226,3 +227,141 @@ describe('PrototypeSanitizer', () => {
     		});
     	});
     });
    +
    +describe('FunctionThisSanitizer', () => {
    +	describe('call expression where callee is function expression', () => {
    +		it('should transform call expression', () => {
    +			const result = tournament.execute('{{ (function() { return this.process; })() }}', {
    +				__sanitize: sanitizer,
    +			});
    +			expect(result).toEqual({});
    +		});
    +
    +		it('should handle recursive call expression', () => {
    +			const result = tournament.execute(
    +				'{{ (function factorial(n) { return n <= 1 ? 1 : n * factorial(n - 1); })(5) }}',
    +				{
    +					__sanitize: sanitizer,
    +				},
    +			);
    +			expect(result).toBe(120);
    +		});
    +
    +		it('should not expose process.env through named function', () => {
    +			const result = tournament.execute('{{ (function test(){ return this.process.env })() }}', {
    +				__sanitize: sanitizer,
    +			});
    +			expect(result).toBe(undefined);
    +		});
    +
    +		it('should still allow access to workflow data via variables', () => {
    +			const result = tournament.execute('{{ (function() { return $json.value; })() }}', {
    +				__sanitize: sanitizer,
    +				$json: { value: 'test-value' },
    +			});
    +			expect(result).toBe('test-value');
    +		});
    +
    +		it('should handle nested call expression', () => {
    +			const result = tournament.execute(
    +				'{{ (function() { return (function() { return this.process; })(); })() }}',
    +				{
    +					__sanitize: sanitizer,
    +				},
    +			);
    +			expect(result).toEqual({});
    +		});
    +
    +		it('should handle nested recursive call expression', () => {
    +			const result = tournament.execute(
    +				'{{ (function() { return (function factorial(n) { return n <= 1 ? 1 : n * factorial(n - 1); })(5); })() }}',
    +				{
    +					__sanitize: sanitizer,
    +				},
    +			);
    +			expect(result).toBe(120);
    +		});
    +	});
    +
    +	describe('function expression', () => {
    +		it('should transform function expression', () => {
    +			const result = tournament.execute('{{ [1].map(function() { return this.process; }) }}', {
    +				__sanitize: sanitizer,
    +			});
    +			expect(result).toEqual([{}]);
    +		});
    +
    +		it('should handle recursive function expression', () => {
    +			const result = tournament.execute(
    +				'{{ [1, 2, 3, 4, 5].map(function factorial(n) { return n <= 1 ? 1 : n * factorial(n - 1); }) }}',
    +				{
    +					__sanitize: sanitizer,
    +				},
    +			);
    +			expect(result).toEqual([1, 2, 6, 24, 120]);
    +		});
    +
    +		it('should handle nested function expression', () => {
    +			const result = tournament.execute(
    +				'{{ [1, 2, 3].map(function(n) { return function() { return n * 2; }; }).map(function(fn) { return fn(); }) }}',
    +				{
    +					__sanitize: sanitizer,
    +				},
    +			);
    +			expect(result).toEqual([2, 4, 6]);
    +		});
    +
    +		it('should handle nested recursion', () => {
    +			const result = tournament.execute(
    +				'{{ (function fibonacci(n) { return n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2); })(7) }}',
    +				{
    +					__sanitize: sanitizer,
    +				},
    +			);
    +			expect(result).toBe(13);
    +		});
    +	});
    +
    +	describe('process.env security', () => {
    +		it('should bind function expressions to empty process object', () => {
    +			const processResult = tournament.execute('{{ (function(){ return this.process })() }}', {
    +				__sanitize: sanitizer,
    +			});
    +			expect(processResult).toEqual({});
    +			expect(Object.keys(processResult as object)).toEqual([]);
    +
    +			const envResult = tournament.execute('{{ (function(){ return this.process.env })() }}', {
    +				__sanitize: sanitizer,
    +			});
    +			expect(envResult).toBe(undefined);
    +		});
    +
    +		it('should block process.env in nested functions', () => {
    +			const result = tournament.execute(
    +				'{{ (function outer(){ return (function inner(){ return this.process.env })(); })() }}',
    +				{
    +					__sanitize: sanitizer,
    +				},
    +			);
    +			expect(result).toBe(undefined);
    +		});
    +
    +		it('should block process.env in callbacks', () => {
    +			const result = tournament.execute(
    +				'{{ [1].map(function(){ return this.process.env; })[0] }}',
    +				{
    +					__sanitize: sanitizer,
    +				},
    +			);
    +			expect(result).toBe(undefined);
    +		});
    +
    +		it('should still allow access to workflow variables', () => {
    +			const result = tournament.execute('{{ (function(){ return $json.value })() }}', {
    +				__sanitize: sanitizer,
    +				$json: { value: 'workflow-data' },
    +			});
    +			expect(result).toBe('workflow-data');
    +		});
    +	});
    +});
    
  • packages/workflow/test/utils.test.ts+3 0 modified
    @@ -379,6 +379,9 @@ describe('isSafeObjectProperty', () => {
     		['prototype', false],
     		['constructor', false],
     		['getPrototypeOf', false],
    +		['mainModule', false],
    +		['binding', false],
    +		['_load', false],
     		['safeKey', true],
     		['anotherKey', true],
     		['toString', true],
    
  • pnpm-lock.yaml+24 112 modified
    @@ -192,6 +192,7 @@ catalogs:
           version: 4.5.0
     
     overrides:
    +  ast-types: 0.16.1
       '@azure/identity': ^4.3.0
       '@lezer/common': ^1.2.0
       '@mistralai/mistralai': ^1.10.0
    @@ -1062,7 +1063,7 @@ importers:
             version: 12.1.0
           '@getzep/zep-cloud':
             specifier: 1.0.12
    -        version: 1.0.12(@langchain/core@0.3.68(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67)))(encoding@0.1.13)(langchain@0.3.33(5cc28a029307bb3da1dcaf370c8a2b8d))
    +        version: 1.0.12(@langchain/core@0.3.68(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67)))(encoding@0.1.13)(langchain@0.3.33(ca377405f102dc2905a39d54ecb4d621))
           '@getzep/zep-js':
             specifier: 0.9.0
             version: 0.9.0
    @@ -1089,7 +1090,7 @@ importers:
             version: 0.3.4(@langchain/core@0.3.68(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67)))(encoding@0.1.13)
           '@langchain/community':
             specifier: 'catalog:'
    -        version: 0.3.50(071f2de44c6bccc3a8cd2fadf2db3e78)
    +        version: 0.3.50(ba725e6da5f3cda58245f84e6fe2ecaf)
           '@langchain/core':
             specifier: 'catalog:'
             version: 0.3.68(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67))
    @@ -1212,7 +1213,7 @@ importers:
             version: 23.0.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)
           langchain:
             specifier: 0.3.33
    -        version: 0.3.33(5cc28a029307bb3da1dcaf370c8a2b8d)
    +        version: 0.3.33(ca377405f102dc2905a39d54ecb4d621)
           lodash:
             specifier: 'catalog:'
             version: 4.17.21
    @@ -3283,8 +3284,8 @@ importers:
             specifier: 1.0.6
             version: 1.0.6
           ast-types:
    -        specifier: 0.15.2
    -        version: 0.15.2
    +        specifier: 0.16.1
    +        version: 0.16.1
           callsites:
             specifier: 'catalog:'
             version: 3.1.0
    @@ -4499,28 +4500,24 @@ packages:
         engines: {node: '>=14.21.3'}
         cpu: [arm64]
         os: [linux]
    -    libc: [musl]
     
       '@biomejs/cli-linux-arm64@1.9.0':
         resolution: {integrity: sha512-l8U2lcqsl9yKPP5WUdIrKH//C1pWyM2cSUfcTBn6GSvXmsSjBNEdGSdM4Wfne777Oe/9ONaD1Ga53U2HksHHLw==}
         engines: {node: '>=14.21.3'}
         cpu: [arm64]
         os: [linux]
    -    libc: [glibc]
     
       '@biomejs/cli-linux-x64-musl@1.9.0':
         resolution: {integrity: sha512-N3enoFoIrkB6qJWyYfTiYmFdB1R/Mrij1dd1xBHqxxCKZY9GRkEswRX3F1Uqzo5T+9Iu8nAQobDqI/ygicYy/Q==}
         engines: {node: '>=14.21.3'}
         cpu: [x64]
         os: [linux]
    -    libc: [musl]
     
       '@biomejs/cli-linux-x64@1.9.0':
         resolution: {integrity: sha512-8jAzjrrJTj510pwq4aVs7ZKkOvEy1D+nzl9DKvrPh4TOyUw5Ie+0EDwXGE2RAkCKHkGNOQBZ78WtIdsATgz5sA==}
         engines: {node: '>=14.21.3'}
         cpu: [x64]
         os: [linux]
    -    libc: [glibc]
     
       '@biomejs/cli-win32-arm64@1.9.0':
         resolution: {integrity: sha512-AIjwJTGfdWGMRluSQ9pDB29nzce077dfHh0/HMqzztKzgD3spyuo2R9VoaFpbR0hLHPWEH6g6OxxDO7hfkXNkQ==}
    @@ -5242,79 +5239,67 @@ packages:
         resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==}
         cpu: [arm64]
         os: [linux]
    -    libc: [glibc]
     
       '@img/sharp-libvips-linux-arm@1.0.5':
         resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==}
         cpu: [arm]
         os: [linux]
    -    libc: [glibc]
     
       '@img/sharp-libvips-linux-s390x@1.0.4':
         resolution: {integrity: sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==}
         cpu: [s390x]
         os: [linux]
    -    libc: [glibc]
     
       '@img/sharp-libvips-linux-x64@1.0.4':
         resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==}
         cpu: [x64]
         os: [linux]
    -    libc: [glibc]
     
       '@img/sharp-libvips-linuxmusl-arm64@1.0.4':
         resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==}
         cpu: [arm64]
         os: [linux]
    -    libc: [musl]
     
       '@img/sharp-libvips-linuxmusl-x64@1.0.4':
         resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==}
         cpu: [x64]
         os: [linux]
    -    libc: [musl]
     
       '@img/sharp-linux-arm64@0.33.5':
         resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==}
         engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
         cpu: [arm64]
         os: [linux]
    -    libc: [glibc]
     
       '@img/sharp-linux-arm@0.33.5':
         resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==}
         engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
         cpu: [arm]
         os: [linux]
    -    libc: [glibc]
     
       '@img/sharp-linux-s390x@0.33.5':
         resolution: {integrity: sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==}
         engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
         cpu: [s390x]
         os: [linux]
    -    libc: [glibc]
     
       '@img/sharp-linux-x64@0.33.5':
         resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==}
         engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
         cpu: [x64]
         os: [linux]
    -    libc: [glibc]
     
       '@img/sharp-linuxmusl-arm64@0.33.5':
         resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==}
         engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
         cpu: [arm64]
         os: [linux]
    -    libc: [musl]
     
       '@img/sharp-linuxmusl-x64@0.33.5':
         resolution: {integrity: sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==}
         engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
         cpu: [x64]
         os: [linux]
    -    libc: [musl]
     
       '@img/sharp-wasm32@0.33.5':
         resolution: {integrity: sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==}
    @@ -6251,35 +6236,30 @@ packages:
         engines: {node: '>= 10'}
         cpu: [arm64]
         os: [linux]
    -    libc: [glibc]
     
       '@napi-rs/canvas-linux-arm64-musl@0.1.70':
         resolution: {integrity: sha512-wBTOllEYNfJCHOdZj9v8gLzZ4oY3oyPX8MSRvaxPm/s7RfEXxCyZ8OhJ5xAyicsDdbE5YBZqdmaaeP5+xKxvtg==}
         engines: {node: '>= 10'}
         cpu: [arm64]
         os: [linux]
    -    libc: [musl]
     
       '@napi-rs/canvas-linux-riscv64-gnu@0.1.70':
         resolution: {integrity: sha512-GVUUPC8TuuFqHip0rxHkUqArQnlzmlXmTEBuXAWdgCv85zTCFH8nOHk/YCF5yo0Z2eOm8nOi90aWs0leJ4OE5Q==}
         engines: {node: '>= 10'}
         cpu: [riscv64]
         os: [linux]
    -    libc: [glibc]
     
       '@napi-rs/canvas-linux-x64-gnu@0.1.70':
         resolution: {integrity: sha512-/kvUa2lZRwGNyfznSn5t1ShWJnr/m5acSlhTV3eXECafObjl0VBuA1HJw0QrilLpb4Fe0VLywkpD1NsMoVDROQ==}
         engines: {node: '>= 10'}
         cpu: [x64]
         os: [linux]
    -    libc: [glibc]
     
       '@napi-rs/canvas-linux-x64-musl@0.1.70':
         resolution: {integrity: sha512-aqlv8MLpycoMKRmds7JWCfVwNf1fiZxaU7JwJs9/ExjTD8lX2KjsO7CTeAj5Cl4aEuzxUWbJPUUE2Qu9cZ1vfg==}
         engines: {node: '>= 10'}
         cpu: [x64]
         os: [linux]
    -    libc: [musl]
     
       '@napi-rs/canvas-win32-x64-msvc@0.1.70':
         resolution: {integrity: sha512-Q9QU3WIpwBTVHk4cPfBjGHGU4U0llQYRXgJtFtYqqGNEOKVN4OT6PQ+ve63xwIPODMpZ0HHyj/KLGc9CWc3EtQ==}
    @@ -6599,42 +6579,36 @@ packages:
         engines: {node: '>= 10.0.0'}
         cpu: [arm]
         os: [linux]
    -    libc: [glibc]
     
       '@parcel/watcher-linux-arm-musl@2.5.1':
         resolution: {integrity: sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==}
         engines: {node: '>= 10.0.0'}
         cpu: [arm]
         os: [linux]
    -    libc: [musl]
     
       '@parcel/watcher-linux-arm64-glibc@2.5.1':
         resolution: {integrity: sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==}
         engines: {node: '>= 10.0.0'}
         cpu: [arm64]
         os: [linux]
    -    libc: [glibc]
     
       '@parcel/watcher-linux-arm64-musl@2.5.1':
         resolution: {integrity: sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==}
         engines: {node: '>= 10.0.0'}
         cpu: [arm64]
         os: [linux]
    -    libc: [musl]
     
       '@parcel/watcher-linux-x64-glibc@2.5.1':
         resolution: {integrity: sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==}
         engines: {node: '>= 10.0.0'}
         cpu: [x64]
         os: [linux]
    -    libc: [glibc]
     
       '@parcel/watcher-linux-x64-musl@2.5.1':
         resolution: {integrity: sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==}
         engines: {node: '>= 10.0.0'}
         cpu: [x64]
         os: [linux]
    -    libc: [musl]
     
       '@parcel/watcher-win32-arm64@2.5.1':
         resolution: {integrity: sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==}
    @@ -6843,56 +6817,48 @@ packages:
         engines: {node: ^20.19.0 || >=22.12.0}
         cpu: [arm64]
         os: [linux]
    -    libc: [glibc]
     
       '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.50':
         resolution: {integrity: sha512-ONgyjofCrrE3bnh5GZb8EINSFyR/hmwTzZ7oVuyUB170lboza1VMCnb8jgE6MsyyRgHYmN8Lb59i3NKGrxrYjw==}
         engines: {node: ^20.19.0 || >=22.12.0}
         cpu: [arm64]
         os: [linux]
    -    libc: [glibc]
     
       '@rolldown/binding-linux-arm64-musl@1.0.0-beta.42':
         resolution: {integrity: sha512-/bNTYb9aKNhzdbPn3O4MK2aLv55AlrkUKPE4KNfBYjkoZUfDr4jWp7gsSlvTc5A/99V1RCm9axvt616ZzeXGyA==}
         engines: {node: ^20.19.0 || >=22.12.0}
         cpu: [arm64]
         os: [linux]
    -    libc: [musl]
     
       '@rolldown/binding-linux-arm64-musl@1.0.0-beta.50':
         resolution: {integrity: sha512-L0zRdH2oDPkmB+wvuTl+dJbXCsx62SkqcEqdM+79LOcB+PxbAxxjzHU14BuZIQdXcAVDzfpMfaHWzZuwhhBTcw==}
         engines: {node: ^20.19.0 || >=22.12.0}
         cpu: [arm64]
         os: [linux]
    -    libc: [musl]
     
       '@rolldown/binding-linux-x64-gnu@1.0.0-beta.42':
         resolution: {integrity: sha512-n/SLa4h342oyeGykZdch7Y3GNCNliRPL4k5wkeZ/5eQZs+c6/ZG1SHCJQoy7bZcmxiMyaXs9HoFmv1PEKrZgWg==}
         engines: {node: ^20.19.0 || >=22.12.0}
         cpu: [x64]
         os: [linux]
    -    libc: [glibc]
     
       '@rolldown/binding-linux-x64-gnu@1.0.0-beta.50':
         resolution: {integrity: sha512-gyoI8o/TGpQd3OzkJnh1M2kxy1Bisg8qJ5Gci0sXm9yLFzEXIFdtc4EAzepxGvrT2ri99ar5rdsmNG0zP0SbIg==}
         engines: {node: ^20.19.0 || >=22.12.0}
         cpu: [x64]
         os: [linux]
    -    libc: [glibc]
     
       '@rolldown/binding-linux-x64-musl@1.0.0-beta.42':
         resolution: {integrity: sha512-4PSd46sFzqpLHSGdaSViAb1mk55sCUMpJg+X8ittXaVocQsV3QLG/uydSH8RyL0ngHX5fy3D70LcCzlB15AgHw==}
         engines: {node: ^20.19.0 || >=22.12.0}
         cpu: [x64]
         os: [linux]
    -    libc: [musl]
     
       '@rolldown/binding-linux-x64-musl@1.0.0-beta.50':
         resolution: {integrity: sha512-zti8A7M+xFDpKlghpcCAzyOi+e5nfUl3QhU023ce5NCgUxRG5zGP2GR9LTydQ1rnIPwZUVBWd4o7NjZDaQxaXA==}
         engines: {node: ^20.19.0 || >=22.12.0}
         cpu: [x64]
         os: [linux]
    -    libc: [musl]
     
       '@rolldown/binding-openharmony-arm64@1.0.0-beta.42':
         resolution: {integrity: sha512-BmWoeJJyeZXmZBcfoxG6J9+rl2G7eO47qdTkAzEegj4n3aC6CBIHOuDcbE8BvhZaEjQR0nh0nJrtEDlt65Q7Sw==}
    @@ -7040,133 +7006,111 @@ packages:
         resolution: {integrity: sha512-OVSQgEZDVLnTbMq5NBs6xkmz3AADByCWI4RdKSFNlDsYXdFtlxS59J+w+LippJe8KcmeSSM3ba+GlsM9+WwC1w==}
         cpu: [arm]
         os: [linux]
    -    libc: [glibc]
     
       '@rollup/rollup-linux-arm-gnueabihf@4.52.4':
         resolution: {integrity: sha512-xRiOu9Of1FZ4SxVbB0iEDXc4ddIcjCv2aj03dmW8UrZIW7aIQ9jVJdLBIhxBI+MaTnGAKyvMwPwQnoOEvP7FgQ==}
         cpu: [arm]
         os: [linux]
    -    libc: [glibc]
     
       '@rollup/rollup-linux-arm-musleabihf@4.49.0':
         resolution: {integrity: sha512-ZnfSFA7fDUHNa4P3VwAcfaBLakCbYaxCk0jUnS3dTou9P95kwoOLAMlT3WmEJDBCSrOEFFV0Y1HXiwfLYJuLlA==}
         cpu: [arm]
         os: [linux]
    -    libc: [musl]
     
       '@rollup/rollup-linux-arm-musleabihf@4.52.4':
         resolution: {integrity: sha512-FbhM2p9TJAmEIEhIgzR4soUcsW49e9veAQCziwbR+XWB2zqJ12b4i/+hel9yLiD8pLncDH4fKIPIbt5238341Q==}
         cpu: [arm]
         os: [linux]
    -    libc: [musl]
     
       '@rollup/rollup-linux-arm64-gnu@4.49.0':
         resolution: {integrity: sha512-Z81u+gfrobVK2iV7GqZCBfEB1y6+I61AH466lNK+xy1jfqFLiQ9Qv716WUM5fxFrYxwC7ziVdZRU9qvGHkYIJg==}
         cpu: [arm64]
         os: [linux]
    -    libc: [glibc]
     
       '@rollup/rollup-linux-arm64-gnu@4.52.4':
         resolution: {integrity: sha512-4n4gVwhPHR9q/g8lKCyz0yuaD0MvDf7dV4f9tHt0C73Mp8h38UCtSCSE6R9iBlTbXlmA8CjpsZoujhszefqueg==}
         cpu: [arm64]
         os: [linux]
    -    libc: [glibc]
     
       '@rollup/rollup-linux-arm64-musl@4.49.0':
         resolution: {integrity: sha512-zoAwS0KCXSnTp9NH/h9aamBAIve0DXeYpll85shf9NJ0URjSTzzS+Z9evmolN+ICfD3v8skKUPyk2PO0uGdFqg==}
         cpu: [arm64]
         os: [linux]
    -    libc: [musl]
     
       '@rollup/rollup-linux-arm64-musl@4.52.4':
         resolution: {integrity: sha512-u0n17nGA0nvi/11gcZKsjkLj1QIpAuPFQbR48Subo7SmZJnGxDpspyw2kbpuoQnyK+9pwf3pAoEXerJs/8Mi9g==}
         cpu: [arm64]
         os: [linux]
    -    libc: [musl]
     
       '@rollup/rollup-linux-loong64-gnu@4.52.4':
         resolution: {integrity: sha512-0G2c2lpYtbTuXo8KEJkDkClE/+/2AFPdPAbmaHoE870foRFs4pBrDehilMcrSScrN/fB/1HTaWO4bqw+ewBzMQ==}
         cpu: [loong64]
         os: [linux]
    -    libc: [glibc]
     
       '@rollup/rollup-linux-loongarch64-gnu@4.49.0':
         resolution: {integrity: sha512-2QyUyQQ1ZtwZGiq0nvODL+vLJBtciItC3/5cYN8ncDQcv5avrt2MbKt1XU/vFAJlLta5KujqyHdYtdag4YEjYQ==}
         cpu: [loong64]
         os: [linux]
    -    libc: [glibc]
     
       '@rollup/rollup-linux-ppc64-gnu@4.49.0':
         resolution: {integrity: sha512-k9aEmOWt+mrMuD3skjVJSSxHckJp+SiFzFG+v8JLXbc/xi9hv2icSkR3U7uQzqy+/QbbYY7iNB9eDTwrELo14g==}
         cpu: [ppc64]
         os: [linux]
    -    libc: [glibc]
     
       '@rollup/rollup-linux-ppc64-gnu@4.52.4':
         resolution: {integrity: sha512-teSACug1GyZHmPDv14VNbvZFX779UqWTsd7KtTM9JIZRDI5NUwYSIS30kzI8m06gOPB//jtpqlhmraQ68b5X2g==}
         cpu: [ppc64]
         os: [linux]
    -    libc: [glibc]
     
       '@rollup/rollup-linux-riscv64-gnu@4.49.0':
         resolution: {integrity: sha512-rDKRFFIWJ/zJn6uk2IdYLc09Z7zkE5IFIOWqpuU0o6ZpHcdniAyWkwSUWE/Z25N/wNDmFHHMzin84qW7Wzkjsw==}
         cpu: [riscv64]
         os: [linux]
    -    libc: [glibc]
     
       '@rollup/rollup-linux-riscv64-gnu@4.52.4':
         resolution: {integrity: sha512-/MOEW3aHjjs1p4Pw1Xk4+3egRevx8Ji9N6HUIA1Ifh8Q+cg9dremvFCUbOX2Zebz80BwJIgCBUemjqhU5XI5Eg==}
         cpu: [riscv64]
         os: [linux]
    -    libc: [glibc]
     
       '@rollup/rollup-linux-riscv64-musl@4.49.0':
         resolution: {integrity: sha512-FkkhIY/hYFVnOzz1WeV3S9Bd1h0hda/gRqvZCMpHWDHdiIHn6pqsY3b5eSbvGccWHMQ1uUzgZTKS4oGpykf8Tw==}
         cpu: [riscv64]
         os: [linux]
    -    libc: [musl]
     
       '@rollup/rollup-linux-riscv64-musl@4.52.4':
         resolution: {integrity: sha512-1HHmsRyh845QDpEWzOFtMCph5Ts+9+yllCrREuBR/vg2RogAQGGBRC8lDPrPOMnrdOJ+mt1WLMOC2Kao/UwcvA==}
         cpu: [riscv64]
         os: [linux]
    -    libc: [musl]
     
       '@rollup/rollup-linux-s390x-gnu@4.49.0':
         resolution: {integrity: sha512-gRf5c+A7QiOG3UwLyOOtyJMD31JJhMjBvpfhAitPAoqZFcOeK3Kc1Veg1z/trmt+2P6F/biT02fU19GGTS529A==}
         cpu: [s390x]
         os: [linux]
    -    libc: [glibc]
     
       '@rollup/rollup-linux-s390x-gnu@4.52.4':
         resolution: {integrity: sha512-seoeZp4L/6D1MUyjWkOMRU6/iLmCU2EjbMTyAG4oIOs1/I82Y5lTeaxW0KBfkUdHAWN7j25bpkt0rjnOgAcQcA==}
         cpu: [s390x]
         os: [linux]
    -    libc: [glibc]
     
       '@rollup/rollup-linux-x64-gnu@4.49.0':
         resolution: {integrity: sha512-BR7+blScdLW1h/2hB/2oXM+dhTmpW3rQt1DeSiCP9mc2NMMkqVgjIN3DDsNpKmezffGC9R8XKVOLmBkRUcK/sA==}
         cpu: [x64]
         os: [linux]
    -    libc: [glibc]
     
       '@rollup/rollup-linux-x64-gnu@4.52.4':
         resolution: {integrity: sha512-Wi6AXf0k0L7E2gteNsNHUs7UMwCIhsCTs6+tqQ5GPwVRWMaflqGec4Sd8n6+FNFDw9vGcReqk2KzBDhCa1DLYg==}
         cpu: [x64]
         os: [linux]
    -    libc: [glibc]
     
       '@rollup/rollup-linux-x64-musl@4.49.0':
         resolution: {integrity: sha512-hDMOAe+6nX3V5ei1I7Au3wcr9h3ktKzDvF2ne5ovX8RZiAHEtX1A5SNNk4zt1Qt77CmnbqT+upb/umzoPMWiPg==}
         cpu: [x64]
         os: [linux]
    -    libc: [musl]
     
       '@rollup/rollup-linux-x64-musl@4.52.4':
         resolution: {integrity: sha512-dtBZYjDmCQ9hW+WgEkaffvRRCKm767wWhxsFW3Lw86VXz/uJRuD438/XvbZT//B96Vs8oTA8Q4A0AfHbrxP9zw==}
         cpu: [x64]
         os: [linux]
    -    libc: [musl]
     
       '@rollup/rollup-openharmony-arm64@4.52.4':
         resolution: {integrity: sha512-1ox+GqgRWqaB1RnyZXL8PD6E5f7YyRUJYnCqKpNzxzP0TkaUh112NDrR9Tt+C8rJ4x5G9Mk8PQR3o7Ku2RKqKA==}
    @@ -8720,49 +8664,41 @@ packages:
         resolution: {integrity: sha512-UYA0MA8ajkEDCFRQdng/FVx3F6szBvk3EPnkTTQuuO9lV1kPGuTB+V9TmbDxy5ikaEgyWKxa4CI3ySjklZ9lFA==}
         cpu: [arm64]
         os: [linux]
    -    libc: [glibc]
     
       '@unrs/resolver-binding-linux-arm64-musl@1.9.2':
         resolution: {integrity: sha512-P/CO3ODU9YJIHFqAkHbquKtFst0COxdphc8TKGL5yCX75GOiVpGqd1d15ahpqu8xXVsqP4MGFP2C3LRZnnL5MA==}
         cpu: [arm64]
         os: [linux]
    -    libc: [musl]
     
       '@unrs/resolver-binding-linux-ppc64-gnu@1.9.2':
         resolution: {integrity: sha512-uKStFlOELBxBum2s1hODPtgJhY4NxYJE9pAeyBgNEzHgTqTiVBPjfTlPFJkfxyTjQEuxZbbJlJnMCrRgD7ubzw==}
         cpu: [ppc64]
         os: [linux]
    -    libc: [glibc]
     
       '@unrs/resolver-binding-linux-riscv64-gnu@1.9.2':
         resolution: {integrity: sha512-LkbNnZlhINfY9gK30AHs26IIVEZ9PEl9qOScYdmY2o81imJYI4IMnJiW0vJVtXaDHvBvxeAgEy5CflwJFIl3tQ==}
         cpu: [riscv64]
         os: [linux]
    -    libc: [glibc]
     
       '@unrs/resolver-binding-linux-riscv64-musl@1.9.2':
         resolution: {integrity: sha512-vI+e6FzLyZHSLFNomPi+nT+qUWN4YSj8pFtQZSFTtmgFoxqB6NyjxSjAxEC1m93qn6hUXhIsh8WMp+fGgxCoRg==}
         cpu: [riscv64]
         os: [linux]
    -    libc: [musl]
     
       '@unrs/resolver-binding-linux-s390x-gnu@1.9.2':
         resolution: {integrity: sha512-sSO4AlAYhSM2RAzBsRpahcJB1msc6uYLAtP6pesPbZtptF8OU/CbCPhSRW6cnYOGuVmEmWVW5xVboAqCnWTeHQ==}
         cpu: [s390x]
         os: [linux]
    -    libc: [glibc]
     
       '@unrs/resolver-binding-linux-x64-gnu@1.9.2':
         resolution: {integrity: sha512-jkSkwch0uPFva20Mdu8orbQjv2A3G88NExTN2oPTI1AJ+7mZfYW3cDCTyoH6OnctBKbBVeJCEqh0U02lTkqD5w==}
         cpu: [x64]
         os: [linux]
    -    libc: [glibc]
     
       '@unrs/resolver-binding-linux-x64-musl@1.9.2':
         resolution: {integrity: sha512-Uk64NoiTpQbkpl+bXsbeyOPRpUoMdcUqa+hDC1KhMW7aN1lfW8PBlBH4mJ3n3Y47dYE8qi0XTxy1mBACruYBaw==}
         cpu: [x64]
         os: [linux]
    -    libc: [musl]
     
       '@unrs/resolver-binding-wasm32-wasi@1.9.2':
         resolution: {integrity: sha512-EpBGwkcjDicjR/ybC0g8wO5adPNdVuMrNalVgYcWi+gYtC1XYNuxe3rufcO7dA76OHGeVabcO6cSkPJKVcbCXQ==}
    @@ -9367,10 +9303,6 @@ packages:
         resolution: {integrity: sha512-WHw67kLXYbZuHTmcdbIrVArCq5wxo6NEuj3hiYAWr8mwJeC+C2mMCIBIWCiDoCye/OF/xelc+teJ1ERoWmnEIA==}
         engines: {node: '>=18'}
     
    -  ast-types@0.15.2:
    -    resolution: {integrity: sha512-c27loCv9QkZinsa5ProX751khO9DJl/AcB5c2KNtA6NRvHKS0PgLfcftz72KVq504vB0Gku5s2kUZzDBvQWvHg==}
    -    engines: {node: '>=4'}
    -
       ast-types@0.16.1:
         resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==}
         engines: {node: '>=4'}
    @@ -13425,28 +13357,24 @@ packages:
         engines: {node: '>= 12.0.0'}
         cpu: [arm64]
         os: [linux]
    -    libc: [glibc]
     
       lightningcss-linux-arm64-musl@1.30.2:
         resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==}
         engines: {node: '>= 12.0.0'}
         cpu: [arm64]
         os: [linux]
    -    libc: [musl]
     
       lightningcss-linux-x64-gnu@1.30.2:
         resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==}
         engines: {node: '>= 12.0.0'}
         cpu: [x64]
         os: [linux]
    -    libc: [glibc]
     
       lightningcss-linux-x64-musl@1.30.2:
         resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==}
         engines: {node: '>= 12.0.0'}
         cpu: [x64]
         os: [linux]
    -    libc: [musl]
     
       lightningcss-win32-arm64-msvc@1.30.2:
         resolution: {integrity: sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==}
    @@ -17644,8 +17572,8 @@ packages:
       vue-component-type-helpers@2.2.12:
         resolution: {integrity: sha512-YbGqHZ5/eW4SnkPNR44mKVc6ZKQoRs/Rux1sxC6rdwXb4qpbOSYfDr9DsTHolOTGmIKgM9j141mZbBeg05R1pw==}
     
    -  vue-component-type-helpers@3.1.3:
    -    resolution: {integrity: sha512-V1dOD8XYfstOKCnXbWyEJIrhTBMwSyNjv271L1Jlx9ExpNlCSuqOs3OdWrGJ0V544zXufKbcYabi/o+gK8lyfQ==}
    +  vue-component-type-helpers@3.1.4:
    +    resolution: {integrity: sha512-Uws7Ew1OzTTqHW8ZVl/qLl/HB+jf08M0NdFONbVWAx0N4gMLK8yfZDgeB77hDnBmaigWWEn5qP8T9BG59jIeyQ==}
     
       vue-demi@0.14.10:
         resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==}
    @@ -21013,7 +20941,7 @@ snapshots:
       '@gar/promisify@1.1.3':
         optional: true
     
    -  '@getzep/zep-cloud@1.0.12(@langchain/core@0.3.68(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67)))(encoding@0.1.13)(langchain@0.3.33(5cc28a029307bb3da1dcaf370c8a2b8d))':
    +  '@getzep/zep-cloud@1.0.12(@langchain/core@0.3.68(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67)))(encoding@0.1.13)(langchain@0.3.33(ca377405f102dc2905a39d54ecb4d621))':
         dependencies:
           form-data: 4.0.4
           node-fetch: 2.7.0(encoding@0.1.13)
    @@ -21022,7 +20950,7 @@ snapshots:
           zod: 3.25.67
         optionalDependencies:
           '@langchain/core': 0.3.68(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67))
    -      langchain: 0.3.33(5cc28a029307bb3da1dcaf370c8a2b8d)
    +      langchain: 0.3.33(ca377405f102dc2905a39d54ecb4d621)
         transitivePeerDependencies:
           - encoding
     
    @@ -21708,7 +21636,7 @@ snapshots:
           - aws-crt
           - encoding
     
    -  '@langchain/community@0.3.50(071f2de44c6bccc3a8cd2fadf2db3e78)':
    +  '@langchain/community@0.3.50(ba725e6da5f3cda58245f84e6fe2ecaf)':
         dependencies:
           '@browserbasehq/stagehand': 1.9.0(@playwright/test@1.56.0)(bufferutil@4.0.9)(deepmerge@4.3.1)(dotenv@16.6.1)(encoding@0.1.13)(openai@5.12.2(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67))(utf-8-validate@5.0.10)(zod@3.25.67)
           '@ibm-cloud/watsonx-ai': 1.1.2
    @@ -21720,7 +21648,7 @@ snapshots:
           flat: 5.0.2
           ibm-cloud-sdk-core: 5.3.2
           js-yaml: 4.1.0
    -      langchain: 0.3.33(5cc28a029307bb3da1dcaf370c8a2b8d)
    +      langchain: 0.3.33(ca377405f102dc2905a39d54ecb4d621)
           langsmith: 0.3.55(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67))
           openai: 5.12.2(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67)
           uuid: 10.0.0
    @@ -21735,7 +21663,7 @@ snapshots:
           '@azure/search-documents': 12.1.0
           '@azure/storage-blob': 12.26.0
           '@browserbasehq/sdk': 2.6.0(encoding@0.1.13)
    -      '@getzep/zep-cloud': 1.0.12(@langchain/core@0.3.68(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67)))(encoding@0.1.13)(langchain@0.3.33(5cc28a029307bb3da1dcaf370c8a2b8d))
    +      '@getzep/zep-cloud': 1.0.12(@langchain/core@0.3.68(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67)))(encoding@0.1.13)(langchain@0.3.33(ca377405f102dc2905a39d54ecb4d621))
           '@getzep/zep-js': 0.9.0
           '@google-ai/generativelanguage': 3.4.0(encoding@0.1.13)
           '@google-cloud/storage': 7.12.1(encoding@0.1.13)
    @@ -22859,7 +22787,7 @@ snapshots:
         dependencies:
           '@rollup/pluginutils': 5.1.4(rollup@4.52.4)
           estree-walker: 2.0.2
    -      magic-string: 0.30.19
    +      magic-string: 0.30.21
         optionalDependencies:
           rollup: 4.52.4
     
    @@ -24059,7 +23987,7 @@ snapshots:
           storybook: 9.1.7(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10)(vite@7.0.0(@types/node@20.19.21)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3))
           type-fest: 2.19.0
           vue: 3.5.13(typescript@5.9.2)
    -      vue-component-type-helpers: 3.1.3
    +      vue-component-type-helpers: 3.1.4
     
       '@stylistic/eslint-plugin@5.0.0(eslint@9.29.0(jiti@2.6.1))':
         dependencies:
    @@ -25115,15 +25043,15 @@ snapshots:
         dependencies:
           '@vitest/spy': 3.2.4
           estree-walker: 3.0.3
    -      magic-string: 0.30.19
    +      magic-string: 0.30.21
         optionalDependencies:
           vite: rolldown-vite@7.1.16(@types/node@20.19.21)(esbuild@0.25.10)(jiti@2.6.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3)
     
       '@vitest/mocker@3.2.4(vite@7.0.0(@types/node@20.19.21)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3))':
         dependencies:
           '@vitest/spy': 3.2.4
           estree-walker: 3.0.3
    -      magic-string: 0.30.19
    +      magic-string: 0.30.21
         optionalDependencies:
           vite: 7.0.0(@types/node@20.19.21)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3)
     
    @@ -25792,10 +25720,6 @@ snapshots:
     
       ast-module-types@6.0.1: {}
     
    -  ast-types@0.15.2:
    -    dependencies:
    -      tslib: 2.6.2
    -
       ast-types@0.16.1:
         dependencies:
           tslib: 2.8.1
    @@ -25871,14 +25795,6 @@ snapshots:
         transitivePeerDependencies:
           - debug
     
    -  axios@1.12.0(debug@4.4.3):
    -    dependencies:
    -      follow-redirects: 1.15.11(debug@4.4.3)
    -      form-data: 4.0.4
    -      proxy-from-env: 1.1.0
    -    transitivePeerDependencies:
    -      - debug
    -
       b4a@1.6.7: {}
     
       babel-jest@29.6.2(@babel/core@7.28.4):
    @@ -28655,10 +28571,6 @@ snapshots:
         optionalDependencies:
           debug: 4.4.1(supports-color@8.1.1)
     
    -  follow-redirects@1.15.11(debug@4.4.3):
    -    optionalDependencies:
    -      debug: 4.4.3
    -
       for-each@0.3.5:
         dependencies:
           is-callable: 1.2.7
    @@ -29361,7 +29273,7 @@ snapshots:
           '@types/debug': 4.1.12
           '@types/node': 20.19.21
           '@types/tough-cookie': 4.0.5
    -      axios: 1.12.0(debug@4.4.3)
    +      axios: 1.12.0(debug@4.4.1)
           camelcase: 6.3.0
           debug: 4.4.3
           dotenv: 16.6.1
    @@ -29371,7 +29283,7 @@ snapshots:
           isstream: 0.1.2
           jsonwebtoken: 9.0.2
           mime-types: 2.1.35
    -      retry-axios: 2.6.0(axios@1.12.0)
    +      retry-axios: 2.6.0(axios@1.12.0(debug@4.4.3))
           tough-cookie: 4.1.4
         transitivePeerDependencies:
           - supports-color
    @@ -30828,7 +30740,7 @@ snapshots:
     
       kuler@2.0.0: {}
     
    -  langchain@0.3.33(5cc28a029307bb3da1dcaf370c8a2b8d):
    +  langchain@0.3.33(ca377405f102dc2905a39d54ecb4d621):
         dependencies:
           '@langchain/core': 0.3.68(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67))
           '@langchain/openai': 0.6.16(@langchain/core@0.3.68(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67)))(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))
    @@ -33480,7 +33392,7 @@ snapshots:
       recast@0.22.0:
         dependencies:
           assert: 2.1.0
    -      ast-types: 0.15.2
    +      ast-types: 0.16.1
           esprima: 4.0.1
           source-map: 0.6.1
           tslib: 2.8.1
    @@ -33721,7 +33633,7 @@ snapshots:
           onetime: 5.1.2
           signal-exit: 3.0.7
     
    -  retry-axios@2.6.0(axios@1.12.0):
    +  retry-axios@2.6.0(axios@1.12.0(debug@4.4.3)):
         dependencies:
           axios: 1.12.0(debug@4.4.1)
     
    @@ -35386,7 +35298,7 @@ snapshots:
           obug: 2.0.0(ms@2.1.3)
           rolldown: 1.0.0-beta.50
           rolldown-plugin-dts: 0.17.8(ms@2.1.3)(rolldown@1.0.0-beta.50)(typescript@5.9.2)(vue-tsc@2.2.8(patch_hash=e2aee939ccac8a57fe449bfd92bedd8117841579526217bc39aca26c6b8c317f)(typescript@5.9.2))
    -      semver: 7.7.3
    +      semver: 7.7.2
           tinyexec: 1.0.2
           tinyglobby: 0.2.15
           tree-kill: 1.2.2
    @@ -36056,7 +35968,7 @@ snapshots:
     
       vue-component-type-helpers@2.2.12: {}
     
    -  vue-component-type-helpers@3.1.3: {}
    +  vue-component-type-helpers@3.1.4: {}
     
       vue-demi@0.14.10(vue@3.5.13(typescript@5.9.2)):
         dependencies:
    
1c933358acef

Merge commit from fork

https://github.com/n8n-io/n8nIván OvejeroNov 18, 2025via ghsa
9 files changed · +253 30
  • package.json+1 0 modified
    @@ -88,6 +88,7 @@
           "sqlite3"
         ],
         "overrides": {
    +      "ast-types": "0.16.1",
           "@azure/identity": "^4.3.0",
           "@lezer/common": "^1.2.0",
           "@mistralai/mistralai": "^1.10.0",
    
  • packages/workflow/package.json+1 1 modified
    @@ -52,7 +52,7 @@
       "dependencies": {
         "@n8n/errors": "workspace:^",
         "@n8n/tournament": "1.0.6",
    -    "ast-types": "0.15.2",
    +    "ast-types": "0.16.1",
         "callsites": "catalog:",
         "esprima-next": "5.8.4",
         "form-data": "catalog:",
    
  • packages/workflow/src/expression-evaluator-proxy.ts+6 2 modified
    @@ -1,13 +1,17 @@
     import { Tournament } from '@n8n/tournament';
     
    -import { DollarSignValidator, PrototypeSanitizer } from './expression-sandboxing';
    +import {
    +	DollarSignValidator,
    +	FunctionThisSanitizer,
    +	PrototypeSanitizer,
    +} from './expression-sandboxing';
     
     type Evaluator = (expr: string, data: unknown) => string | null | (() => unknown);
     type ErrorHandler = (error: Error) => void;
     
     const errorHandler: ErrorHandler = () => {};
     const tournamentEvaluator = new Tournament(errorHandler, undefined, undefined, {
    -	before: [],
    +	before: [FunctionThisSanitizer],
     	after: [PrototypeSanitizer, DollarSignValidator],
     });
     const evaluator: Evaluator = tournamentEvaluator.execute.bind(tournamentEvaluator);
    
  • packages/workflow/src/expression-sandboxing.ts+68 1 modified
    @@ -1,4 +1,4 @@
    -import { type ASTAfterHook, astBuilders as b, astVisit } from '@n8n/tournament';
    +import { type ASTAfterHook, type ASTBeforeHook, astBuilders as b, astVisit } from '@n8n/tournament';
     
     import { ExpressionError } from './errors';
     import { isSafeObjectProperty } from './utils';
    @@ -8,6 +8,10 @@ const sanitizerIdentifier = b.identifier(sanitizerName);
     
     export const DOLLAR_SIGN_ERROR = 'Cannot access "$" without calling it as a function';
     
    +const EMPTY_CONTEXT = b.objectExpression([
    +	b.property('init', b.identifier('process'), b.objectExpression([])),
    +]);
    +
     /**
      * Helper to check if an expression is a valid property access with $ as the property.
      * Returns true for obj.$ or obj.nested.$ but false for bare $ or other expression contexts.
    @@ -49,6 +53,69 @@ const isValidDollarPropertyAccess = (expr: unknown): boolean => {
     	return isPropertyDollar && !isObjectDollar && isObjectValid;
     };
     
    +/**
    + * Prevents regular functions from binding their `this` to the Node.js global.
    + */
    +export const FunctionThisSanitizer: ASTBeforeHook = (ast, dataNode) => {
    +	astVisit(ast, {
    +		visitCallExpression(path) {
    +			const { node } = path;
    +
    +			if (node.callee.type !== 'FunctionExpression') {
    +				this.traverse(path);
    +				return;
    +			}
    +
    +			const fnExpression = node.callee;
    +
    +			/**
    +			 * Called function expressions (IIFEs) - both anonymous and named:
    +			 *
    +			 * ```js
    +			 * (function(x) { return x * 2; })(5)
    +			 * (function factorial(n) { return n <= 1 ? 1 : n * factorial(n-1); })(5)
    +			 *
    +			 * // become
    +			 *
    +			 * (function(x) { return x * 2; }).call({ process: {} }, 5)
    +			 * (function factorial(n) { return n <= 1 ? 1 : n * factorial(n-1); }).call({ process: {} }, 5)
    +			 * ```
    +			 */
    +			this.traverse(path); // depth first to transform inside out
    +			const callExpression = b.callExpression(
    +				b.memberExpression(fnExpression, b.identifier('call')),
    +				[EMPTY_CONTEXT, ...node.arguments],
    +			);
    +			path.replace(callExpression);
    +			return false;
    +		},
    +
    +		visitFunctionExpression(path) {
    +			const { node } = path;
    +
    +			/**
    +			 * Callable function expressions (callbacks) - both anonymous and named:
    +			 *
    +			 * ```js
    +			 * [1, 2, 3].map(function(n) { return n * 2; })
    +			 * [1, 2, 3].map(function factorial(n) { return n <= 1 ? 1 : n * factorial(n-1); })
    +			 *
    +			 * // become
    +			 *
    +			 * [1, 2, 3].map((function(n) { return n * 2; }).bind({ process: {} }))
    +			 * [1, 2, 3].map((function factorial(n) { return n <= 1 ? 1 : n * factorial(n-1); }).bind({ process: {} }))
    +			 * ```
    +			 */
    +			this.traverse(path);
    +			const boundFunction = b.callExpression(b.memberExpression(node, b.identifier('bind')), [
    +				EMPTY_CONTEXT,
    +			]);
    +			path.replace(boundFunction);
    +			return false;
    +		},
    +	});
    +};
    +
     /**
      * Validates that the $ identifier is only used in allowed contexts.
      * This prevents user errors like `{{ $ }}` which would return the function object itself.
    
  • packages/workflow/src/extensions/expression-extension.ts+1 1 modified
    @@ -1,5 +1,5 @@
     /* eslint-disable @typescript-eslint/no-unsafe-member-access */
    -import type { ExpressionKind } from 'ast-types/gen/kinds';
    +import type { ExpressionKind } from 'ast-types/lib/gen/kinds';
     import type { Config as EsprimaConfig } from 'esprima-next';
     import { parse as esprimaParse } from 'esprima-next';
     import { DateTime } from 'luxon';
    
  • packages/workflow/src/utils.ts+9 1 modified
    @@ -332,7 +332,15 @@ export function hasKey<T extends PropertyKey>(value: unknown, key: T): value is
     	return value !== null && typeof value === 'object' && value.hasOwnProperty(key);
     }
     
    -const unsafeObjectProperties = new Set(['__proto__', 'prototype', 'constructor', 'getPrototypeOf']);
    +const unsafeObjectProperties = new Set([
    +	'__proto__',
    +	'prototype',
    +	'constructor',
    +	'getPrototypeOf',
    +	'mainModule',
    +	'binding',
    +	'_load',
    +]);
     
     /**
      * Checks if a property key is safe to use on an object, preventing prototype pollution.
    
  • packages/workflow/test/expression-sandboxing.test.ts+140 1 modified
    @@ -2,6 +2,7 @@ import { Tournament } from '@n8n/tournament';
     
     import {
     	DollarSignValidator,
    +	FunctionThisSanitizer,
     	PrototypeSanitizer,
     	sanitizer,
     	DOLLAR_SIGN_ERROR,
    @@ -14,7 +15,7 @@ const tournament = new Tournament(
     	undefined,
     	undefined,
     	{
    -		before: [],
    +		before: [FunctionThisSanitizer],
     		after: [PrototypeSanitizer, DollarSignValidator],
     	},
     );
    @@ -226,3 +227,141 @@ describe('PrototypeSanitizer', () => {
     		});
     	});
     });
    +
    +describe('FunctionThisSanitizer', () => {
    +	describe('call expression where callee is function expression', () => {
    +		it('should transform call expression', () => {
    +			const result = tournament.execute('{{ (function() { return this.process; })() }}', {
    +				__sanitize: sanitizer,
    +			});
    +			expect(result).toEqual({});
    +		});
    +
    +		it('should handle recursive call expression', () => {
    +			const result = tournament.execute(
    +				'{{ (function factorial(n) { return n <= 1 ? 1 : n * factorial(n - 1); })(5) }}',
    +				{
    +					__sanitize: sanitizer,
    +				},
    +			);
    +			expect(result).toBe(120);
    +		});
    +
    +		it('should not expose process.env through named function', () => {
    +			const result = tournament.execute('{{ (function test(){ return this.process.env })() }}', {
    +				__sanitize: sanitizer,
    +			});
    +			expect(result).toBe(undefined);
    +		});
    +
    +		it('should still allow access to workflow data via variables', () => {
    +			const result = tournament.execute('{{ (function() { return $json.value; })() }}', {
    +				__sanitize: sanitizer,
    +				$json: { value: 'test-value' },
    +			});
    +			expect(result).toBe('test-value');
    +		});
    +
    +		it('should handle nested call expression', () => {
    +			const result = tournament.execute(
    +				'{{ (function() { return (function() { return this.process; })(); })() }}',
    +				{
    +					__sanitize: sanitizer,
    +				},
    +			);
    +			expect(result).toEqual({});
    +		});
    +
    +		it('should handle nested recursive call expression', () => {
    +			const result = tournament.execute(
    +				'{{ (function() { return (function factorial(n) { return n <= 1 ? 1 : n * factorial(n - 1); })(5); })() }}',
    +				{
    +					__sanitize: sanitizer,
    +				},
    +			);
    +			expect(result).toBe(120);
    +		});
    +	});
    +
    +	describe('function expression', () => {
    +		it('should transform function expression', () => {
    +			const result = tournament.execute('{{ [1].map(function() { return this.process; }) }}', {
    +				__sanitize: sanitizer,
    +			});
    +			expect(result).toEqual([{}]);
    +		});
    +
    +		it('should handle recursive function expression', () => {
    +			const result = tournament.execute(
    +				'{{ [1, 2, 3, 4, 5].map(function factorial(n) { return n <= 1 ? 1 : n * factorial(n - 1); }) }}',
    +				{
    +					__sanitize: sanitizer,
    +				},
    +			);
    +			expect(result).toEqual([1, 2, 6, 24, 120]);
    +		});
    +
    +		it('should handle nested function expression', () => {
    +			const result = tournament.execute(
    +				'{{ [1, 2, 3].map(function(n) { return function() { return n * 2; }; }).map(function(fn) { return fn(); }) }}',
    +				{
    +					__sanitize: sanitizer,
    +				},
    +			);
    +			expect(result).toEqual([2, 4, 6]);
    +		});
    +
    +		it('should handle nested recursion', () => {
    +			const result = tournament.execute(
    +				'{{ (function fibonacci(n) { return n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2); })(7) }}',
    +				{
    +					__sanitize: sanitizer,
    +				},
    +			);
    +			expect(result).toBe(13);
    +		});
    +	});
    +
    +	describe('process.env security', () => {
    +		it('should bind function expressions to empty process object', () => {
    +			const processResult = tournament.execute('{{ (function(){ return this.process })() }}', {
    +				__sanitize: sanitizer,
    +			});
    +			expect(processResult).toEqual({});
    +			expect(Object.keys(processResult as object)).toEqual([]);
    +
    +			const envResult = tournament.execute('{{ (function(){ return this.process.env })() }}', {
    +				__sanitize: sanitizer,
    +			});
    +			expect(envResult).toBe(undefined);
    +		});
    +
    +		it('should block process.env in nested functions', () => {
    +			const result = tournament.execute(
    +				'{{ (function outer(){ return (function inner(){ return this.process.env })(); })() }}',
    +				{
    +					__sanitize: sanitizer,
    +				},
    +			);
    +			expect(result).toBe(undefined);
    +		});
    +
    +		it('should block process.env in callbacks', () => {
    +			const result = tournament.execute(
    +				'{{ [1].map(function(){ return this.process.env; })[0] }}',
    +				{
    +					__sanitize: sanitizer,
    +				},
    +			);
    +			expect(result).toBe(undefined);
    +		});
    +
    +		it('should still allow access to workflow variables', () => {
    +			const result = tournament.execute('{{ (function(){ return $json.value })() }}', {
    +				__sanitize: sanitizer,
    +				$json: { value: 'workflow-data' },
    +			});
    +			expect(result).toBe('workflow-data');
    +		});
    +	});
    +});
    
  • packages/workflow/test/utils.test.ts+3 0 modified
    @@ -379,6 +379,9 @@ describe('isSafeObjectProperty', () => {
     		['prototype', false],
     		['constructor', false],
     		['getPrototypeOf', false],
    +		['mainModule', false],
    +		['binding', false],
    +		['_load', false],
     		['safeKey', true],
     		['anotherKey', true],
     		['toString', true],
    
  • pnpm-lock.yaml+24 23 modified
    @@ -186,6 +186,7 @@ catalogs:
           version: 4.5.0
     
     overrides:
    +  ast-types: 0.16.1
       '@azure/identity': ^4.3.0
       '@lezer/common': ^1.2.0
       '@mistralai/mistralai': ^1.10.0
    @@ -3267,8 +3268,8 @@ importers:
             specifier: 1.0.6
             version: 1.0.6
           ast-types:
    -        specifier: 0.15.2
    -        version: 0.15.2
    +        specifier: 0.16.1
    +        version: 0.16.1
           callsites:
             specifier: 'catalog:'
             version: 3.1.0
    @@ -9340,10 +9341,6 @@ packages:
         resolution: {integrity: sha512-WHw67kLXYbZuHTmcdbIrVArCq5wxo6NEuj3hiYAWr8mwJeC+C2mMCIBIWCiDoCye/OF/xelc+teJ1ERoWmnEIA==}
         engines: {node: '>=18'}
     
    -  ast-types@0.15.2:
    -    resolution: {integrity: sha512-c27loCv9QkZinsa5ProX751khO9DJl/AcB5c2KNtA6NRvHKS0PgLfcftz72KVq504vB0Gku5s2kUZzDBvQWvHg==}
    -    engines: {node: '>=4'}
    -
       ast-types@0.16.1:
         resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==}
         engines: {node: '>=4'}
    @@ -17595,8 +17592,8 @@ packages:
       vue-component-type-helpers@2.2.12:
         resolution: {integrity: sha512-YbGqHZ5/eW4SnkPNR44mKVc6ZKQoRs/Rux1sxC6rdwXb4qpbOSYfDr9DsTHolOTGmIKgM9j141mZbBeg05R1pw==}
     
    -  vue-component-type-helpers@3.1.3:
    -    resolution: {integrity: sha512-V1dOD8XYfstOKCnXbWyEJIrhTBMwSyNjv271L1Jlx9ExpNlCSuqOs3OdWrGJ0V544zXufKbcYabi/o+gK8lyfQ==}
    +  vue-component-type-helpers@3.1.4:
    +    resolution: {integrity: sha512-Uws7Ew1OzTTqHW8ZVl/qLl/HB+jf08M0NdFONbVWAx0N4gMLK8yfZDgeB77hDnBmaigWWEn5qP8T9BG59jIeyQ==}
     
       vue-demi@0.14.10:
         resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==}
    @@ -22948,7 +22945,7 @@ snapshots:
     
       '@rudderstack/rudder-sdk-node@2.1.4(tslib@2.8.1)':
         dependencies:
    -      axios: 1.12.0(debug@4.4.1)
    +      axios: 1.12.0
           axios-retry: 4.5.0(axios@1.12.0)
           component-type: 2.0.0
           join-component: 1.1.0
    @@ -24006,7 +24003,7 @@ snapshots:
           storybook: 9.1.7(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10)(vite@7.0.0(@types/node@20.19.21)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3))
           type-fest: 2.19.0
           vue: 3.5.13(typescript@5.9.2)
    -      vue-component-type-helpers: 3.1.3
    +      vue-component-type-helpers: 3.1.4
     
       '@stylistic/eslint-plugin@5.0.0(eslint@9.29.0(jiti@2.6.1))':
         dependencies:
    @@ -25739,10 +25736,6 @@ snapshots:
     
       ast-module-types@6.0.1: {}
     
    -  ast-types@0.15.2:
    -    dependencies:
    -      tslib: 2.6.2
    -
       ast-types@0.16.1:
         dependencies:
           tslib: 2.8.1
    @@ -25799,9 +25792,17 @@ snapshots:
     
       axios-retry@4.5.0(axios@1.12.0):
         dependencies:
    -      axios: 1.12.0(debug@4.4.1)
    +      axios: 1.12.0
           is-retry-allowed: 2.2.0
     
    +  axios@1.12.0:
    +    dependencies:
    +      follow-redirects: 1.15.11(debug@4.4.1)
    +      form-data: 4.0.4
    +      proxy-from-env: 1.1.0
    +    transitivePeerDependencies:
    +      - debug
    +
       axios@1.12.0(debug@4.3.6):
         dependencies:
           follow-redirects: 1.15.11(debug@4.3.6)
    @@ -26206,7 +26207,7 @@ snapshots:
     
       bundlemon@3.1.0(typescript@5.9.2):
         dependencies:
    -      axios: 1.12.0(debug@4.4.1)
    +      axios: 1.12.0
           axios-retry: 4.5.0(axios@1.12.0)
           brotli-size: 4.0.0
           bundlemon-utils: 2.0.1
    @@ -29416,7 +29417,7 @@ snapshots:
     
       infisical-node@1.3.0:
         dependencies:
    -      axios: 1.12.0(debug@4.4.1)
    +      axios: 1.12.0
           dotenv: 16.3.1
           tweetnacl: 1.0.3
           tweetnacl-util: 0.15.1
    @@ -30817,7 +30818,7 @@ snapshots:
           '@langchain/groq': 0.2.3(@langchain/core@0.3.68(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67)))(encoding@0.1.13)
           '@langchain/mistralai': 0.2.3(@langchain/core@0.3.68(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67)))
           '@langchain/ollama': 0.2.3(@langchain/core@0.3.68(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67)))
    -      axios: 1.12.0(debug@4.4.1)
    +      axios: 1.12.0
           cheerio: 1.0.0
           handlebars: 4.7.8
         transitivePeerDependencies:
    @@ -32963,7 +32964,7 @@ snapshots:
     
       posthog-node@3.2.1:
         dependencies:
    -      axios: 1.12.0(debug@4.4.1)
    +      axios: 1.12.0
           rusha: 0.8.14
         transitivePeerDependencies:
           - debug
    @@ -33440,7 +33441,7 @@ snapshots:
       recast@0.22.0:
         dependencies:
           assert: 2.1.0
    -      ast-types: 0.15.2
    +      ast-types: 0.16.1
           esprima: 4.0.1
           source-map: 0.6.1
           tslib: 2.8.1
    @@ -33683,7 +33684,7 @@ snapshots:
     
       retry-axios@2.6.0(axios@1.12.0):
         dependencies:
    -      axios: 1.12.0(debug@4.4.1)
    +      axios: 1.12.0
     
       retry-request@7.0.2(encoding@0.1.13):
         dependencies:
    @@ -34290,7 +34291,7 @@ snapshots:
           asn1.js: 5.4.1
           asn1.js-rfc2560: 5.0.1(asn1.js@5.4.1)
           asn1.js-rfc5280: 3.0.0
    -      axios: 1.12.0(debug@4.4.1)
    +      axios: 1.12.0
           big-integer: 1.6.52
           bignumber.js: 9.1.2
           binascii: 0.0.2
    @@ -36011,7 +36012,7 @@ snapshots:
     
       vue-component-type-helpers@2.2.12: {}
     
    -  vue-component-type-helpers@3.1.3: {}
    +  vue-component-type-helpers@3.1.4: {}
     
       vue-demi@0.14.10(vue@3.5.13(typescript@5.9.2)):
         dependencies:
    
08f332015153

Merge commit from fork

https://github.com/n8n-io/n8nIván OvejeroNov 18, 2025via ghsa
9 files changed · +253 119
  • package.json+1 0 modified
    @@ -88,6 +88,7 @@
           "sqlite3"
         ],
         "overrides": {
    +      "ast-types": "0.16.1",
           "@azure/identity": "^4.3.0",
           "@lezer/common": "^1.2.0",
           "@mistralai/mistralai": "^1.10.0",
    
  • packages/workflow/package.json+1 1 modified
    @@ -52,7 +52,7 @@
       "dependencies": {
         "@n8n/errors": "workspace:^",
         "@n8n/tournament": "1.0.6",
    -    "ast-types": "0.15.2",
    +    "ast-types": "0.16.1",
         "callsites": "catalog:",
         "esprima-next": "5.8.4",
         "form-data": "catalog:",
    
  • packages/workflow/src/expression-evaluator-proxy.ts+6 2 modified
    @@ -1,13 +1,17 @@
     import { Tournament } from '@n8n/tournament';
     
    -import { DollarSignValidator, PrototypeSanitizer } from './expression-sandboxing';
    +import {
    +	DollarSignValidator,
    +	FunctionThisSanitizer,
    +	PrototypeSanitizer,
    +} from './expression-sandboxing';
     
     type Evaluator = (expr: string, data: unknown) => string | null | (() => unknown);
     type ErrorHandler = (error: Error) => void;
     
     const errorHandler: ErrorHandler = () => {};
     const tournamentEvaluator = new Tournament(errorHandler, undefined, undefined, {
    -	before: [],
    +	before: [FunctionThisSanitizer],
     	after: [PrototypeSanitizer, DollarSignValidator],
     });
     const evaluator: Evaluator = tournamentEvaluator.execute.bind(tournamentEvaluator);
    
  • packages/workflow/src/expression-sandboxing.ts+68 1 modified
    @@ -1,4 +1,4 @@
    -import { type ASTAfterHook, astBuilders as b, astVisit } from '@n8n/tournament';
    +import { type ASTAfterHook, type ASTBeforeHook, astBuilders as b, astVisit } from '@n8n/tournament';
     
     import { ExpressionError } from './errors';
     import { isSafeObjectProperty } from './utils';
    @@ -8,6 +8,10 @@ const sanitizerIdentifier = b.identifier(sanitizerName);
     
     export const DOLLAR_SIGN_ERROR = 'Cannot access "$" without calling it as a function';
     
    +const EMPTY_CONTEXT = b.objectExpression([
    +	b.property('init', b.identifier('process'), b.objectExpression([])),
    +]);
    +
     /**
      * Helper to check if an expression is a valid property access with $ as the property.
      * Returns true for obj.$ or obj.nested.$ but false for bare $ or other expression contexts.
    @@ -49,6 +53,69 @@ const isValidDollarPropertyAccess = (expr: unknown): boolean => {
     	return isPropertyDollar && !isObjectDollar && isObjectValid;
     };
     
    +/**
    + * Prevents regular functions from binding their `this` to the Node.js global.
    + */
    +export const FunctionThisSanitizer: ASTBeforeHook = (ast, dataNode) => {
    +	astVisit(ast, {
    +		visitCallExpression(path) {
    +			const { node } = path;
    +
    +			if (node.callee.type !== 'FunctionExpression') {
    +				this.traverse(path);
    +				return;
    +			}
    +
    +			const fnExpression = node.callee;
    +
    +			/**
    +			 * Called function expressions (IIFEs) - both anonymous and named:
    +			 *
    +			 * ```js
    +			 * (function(x) { return x * 2; })(5)
    +			 * (function factorial(n) { return n <= 1 ? 1 : n * factorial(n-1); })(5)
    +			 *
    +			 * // become
    +			 *
    +			 * (function(x) { return x * 2; }).call({ process: {} }, 5)
    +			 * (function factorial(n) { return n <= 1 ? 1 : n * factorial(n-1); }).call({ process: {} }, 5)
    +			 * ```
    +			 */
    +			this.traverse(path); // depth first to transform inside out
    +			const callExpression = b.callExpression(
    +				b.memberExpression(fnExpression, b.identifier('call')),
    +				[EMPTY_CONTEXT, ...node.arguments],
    +			);
    +			path.replace(callExpression);
    +			return false;
    +		},
    +
    +		visitFunctionExpression(path) {
    +			const { node } = path;
    +
    +			/**
    +			 * Callable function expressions (callbacks) - both anonymous and named:
    +			 *
    +			 * ```js
    +			 * [1, 2, 3].map(function(n) { return n * 2; })
    +			 * [1, 2, 3].map(function factorial(n) { return n <= 1 ? 1 : n * factorial(n-1); })
    +			 *
    +			 * // become
    +			 *
    +			 * [1, 2, 3].map((function(n) { return n * 2; }).bind({ process: {} }))
    +			 * [1, 2, 3].map((function factorial(n) { return n <= 1 ? 1 : n * factorial(n-1); }).bind({ process: {} }))
    +			 * ```
    +			 */
    +			this.traverse(path);
    +			const boundFunction = b.callExpression(b.memberExpression(node, b.identifier('bind')), [
    +				EMPTY_CONTEXT,
    +			]);
    +			path.replace(boundFunction);
    +			return false;
    +		},
    +	});
    +};
    +
     /**
      * Validates that the $ identifier is only used in allowed contexts.
      * This prevents user errors like `{{ $ }}` which would return the function object itself.
    
  • packages/workflow/src/extensions/expression-extension.ts+1 1 modified
    @@ -1,5 +1,5 @@
     /* eslint-disable @typescript-eslint/no-unsafe-member-access */
    -import type { ExpressionKind } from 'ast-types/gen/kinds';
    +import type { ExpressionKind } from 'ast-types/lib/gen/kinds';
     import type { Config as EsprimaConfig } from 'esprima-next';
     import { parse as esprimaParse } from 'esprima-next';
     import { DateTime } from 'luxon';
    
  • packages/workflow/src/utils.ts+9 1 modified
    @@ -332,7 +332,15 @@ export function hasKey<T extends PropertyKey>(value: unknown, key: T): value is
     	return value !== null && typeof value === 'object' && value.hasOwnProperty(key);
     }
     
    -const unsafeObjectProperties = new Set(['__proto__', 'prototype', 'constructor', 'getPrototypeOf']);
    +const unsafeObjectProperties = new Set([
    +	'__proto__',
    +	'prototype',
    +	'constructor',
    +	'getPrototypeOf',
    +	'mainModule',
    +	'binding',
    +	'_load',
    +]);
     
     /**
      * Checks if a property key is safe to use on an object, preventing prototype pollution.
    
  • packages/workflow/test/expression-sandboxing.test.ts+140 1 modified
    @@ -2,6 +2,7 @@ import { Tournament } from '@n8n/tournament';
     
     import {
     	DollarSignValidator,
    +	FunctionThisSanitizer,
     	PrototypeSanitizer,
     	sanitizer,
     	DOLLAR_SIGN_ERROR,
    @@ -14,7 +15,7 @@ const tournament = new Tournament(
     	undefined,
     	undefined,
     	{
    -		before: [],
    +		before: [FunctionThisSanitizer],
     		after: [PrototypeSanitizer, DollarSignValidator],
     	},
     );
    @@ -226,3 +227,141 @@ describe('PrototypeSanitizer', () => {
     		});
     	});
     });
    +
    +describe('FunctionThisSanitizer', () => {
    +	describe('call expression where callee is function expression', () => {
    +		it('should transform call expression', () => {
    +			const result = tournament.execute('{{ (function() { return this.process; })() }}', {
    +				__sanitize: sanitizer,
    +			});
    +			expect(result).toEqual({});
    +		});
    +
    +		it('should handle recursive call expression', () => {
    +			const result = tournament.execute(
    +				'{{ (function factorial(n) { return n <= 1 ? 1 : n * factorial(n - 1); })(5) }}',
    +				{
    +					__sanitize: sanitizer,
    +				},
    +			);
    +			expect(result).toBe(120);
    +		});
    +
    +		it('should not expose process.env through named function', () => {
    +			const result = tournament.execute('{{ (function test(){ return this.process.env })() }}', {
    +				__sanitize: sanitizer,
    +			});
    +			expect(result).toBe(undefined);
    +		});
    +
    +		it('should still allow access to workflow data via variables', () => {
    +			const result = tournament.execute('{{ (function() { return $json.value; })() }}', {
    +				__sanitize: sanitizer,
    +				$json: { value: 'test-value' },
    +			});
    +			expect(result).toBe('test-value');
    +		});
    +
    +		it('should handle nested call expression', () => {
    +			const result = tournament.execute(
    +				'{{ (function() { return (function() { return this.process; })(); })() }}',
    +				{
    +					__sanitize: sanitizer,
    +				},
    +			);
    +			expect(result).toEqual({});
    +		});
    +
    +		it('should handle nested recursive call expression', () => {
    +			const result = tournament.execute(
    +				'{{ (function() { return (function factorial(n) { return n <= 1 ? 1 : n * factorial(n - 1); })(5); })() }}',
    +				{
    +					__sanitize: sanitizer,
    +				},
    +			);
    +			expect(result).toBe(120);
    +		});
    +	});
    +
    +	describe('function expression', () => {
    +		it('should transform function expression', () => {
    +			const result = tournament.execute('{{ [1].map(function() { return this.process; }) }}', {
    +				__sanitize: sanitizer,
    +			});
    +			expect(result).toEqual([{}]);
    +		});
    +
    +		it('should handle recursive function expression', () => {
    +			const result = tournament.execute(
    +				'{{ [1, 2, 3, 4, 5].map(function factorial(n) { return n <= 1 ? 1 : n * factorial(n - 1); }) }}',
    +				{
    +					__sanitize: sanitizer,
    +				},
    +			);
    +			expect(result).toEqual([1, 2, 6, 24, 120]);
    +		});
    +
    +		it('should handle nested function expression', () => {
    +			const result = tournament.execute(
    +				'{{ [1, 2, 3].map(function(n) { return function() { return n * 2; }; }).map(function(fn) { return fn(); }) }}',
    +				{
    +					__sanitize: sanitizer,
    +				},
    +			);
    +			expect(result).toEqual([2, 4, 6]);
    +		});
    +
    +		it('should handle nested recursion', () => {
    +			const result = tournament.execute(
    +				'{{ (function fibonacci(n) { return n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2); })(7) }}',
    +				{
    +					__sanitize: sanitizer,
    +				},
    +			);
    +			expect(result).toBe(13);
    +		});
    +	});
    +
    +	describe('process.env security', () => {
    +		it('should bind function expressions to empty process object', () => {
    +			const processResult = tournament.execute('{{ (function(){ return this.process })() }}', {
    +				__sanitize: sanitizer,
    +			});
    +			expect(processResult).toEqual({});
    +			expect(Object.keys(processResult as object)).toEqual([]);
    +
    +			const envResult = tournament.execute('{{ (function(){ return this.process.env })() }}', {
    +				__sanitize: sanitizer,
    +			});
    +			expect(envResult).toBe(undefined);
    +		});
    +
    +		it('should block process.env in nested functions', () => {
    +			const result = tournament.execute(
    +				'{{ (function outer(){ return (function inner(){ return this.process.env })(); })() }}',
    +				{
    +					__sanitize: sanitizer,
    +				},
    +			);
    +			expect(result).toBe(undefined);
    +		});
    +
    +		it('should block process.env in callbacks', () => {
    +			const result = tournament.execute(
    +				'{{ [1].map(function(){ return this.process.env; })[0] }}',
    +				{
    +					__sanitize: sanitizer,
    +				},
    +			);
    +			expect(result).toBe(undefined);
    +		});
    +
    +		it('should still allow access to workflow variables', () => {
    +			const result = tournament.execute('{{ (function(){ return $json.value })() }}', {
    +				__sanitize: sanitizer,
    +				$json: { value: 'workflow-data' },
    +			});
    +			expect(result).toBe('workflow-data');
    +		});
    +	});
    +});
    
  • packages/workflow/test/utils.test.ts+3 0 modified
    @@ -379,6 +379,9 @@ describe('isSafeObjectProperty', () => {
     		['prototype', false],
     		['constructor', false],
     		['getPrototypeOf', false],
    +		['mainModule', false],
    +		['binding', false],
    +		['_load', false],
     		['safeKey', true],
     		['anotherKey', true],
     		['toString', true],
    
  • pnpm-lock.yaml+24 112 modified
    @@ -192,6 +192,7 @@ catalogs:
           version: 4.5.0
     
     overrides:
    +  ast-types: 0.16.1
       '@azure/identity': ^4.3.0
       '@lezer/common': ^1.2.0
       '@mistralai/mistralai': ^1.10.0
    @@ -1062,7 +1063,7 @@ importers:
             version: 12.1.0
           '@getzep/zep-cloud':
             specifier: 1.0.12
    -        version: 1.0.12(@langchain/core@0.3.68(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67)))(encoding@0.1.13)(langchain@0.3.33(5cc28a029307bb3da1dcaf370c8a2b8d))
    +        version: 1.0.12(@langchain/core@0.3.68(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67)))(encoding@0.1.13)(langchain@0.3.33(ca377405f102dc2905a39d54ecb4d621))
           '@getzep/zep-js':
             specifier: 0.9.0
             version: 0.9.0
    @@ -1089,7 +1090,7 @@ importers:
             version: 0.3.4(@langchain/core@0.3.68(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67)))(encoding@0.1.13)
           '@langchain/community':
             specifier: 'catalog:'
    -        version: 0.3.50(071f2de44c6bccc3a8cd2fadf2db3e78)
    +        version: 0.3.50(ba725e6da5f3cda58245f84e6fe2ecaf)
           '@langchain/core':
             specifier: 'catalog:'
             version: 0.3.68(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67))
    @@ -1212,7 +1213,7 @@ importers:
             version: 23.0.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)
           langchain:
             specifier: 0.3.33
    -        version: 0.3.33(5cc28a029307bb3da1dcaf370c8a2b8d)
    +        version: 0.3.33(ca377405f102dc2905a39d54ecb4d621)
           lodash:
             specifier: 'catalog:'
             version: 4.17.21
    @@ -3283,8 +3284,8 @@ importers:
             specifier: 1.0.6
             version: 1.0.6
           ast-types:
    -        specifier: 0.15.2
    -        version: 0.15.2
    +        specifier: 0.16.1
    +        version: 0.16.1
           callsites:
             specifier: 'catalog:'
             version: 3.1.0
    @@ -4499,28 +4500,24 @@ packages:
         engines: {node: '>=14.21.3'}
         cpu: [arm64]
         os: [linux]
    -    libc: [musl]
     
       '@biomejs/cli-linux-arm64@1.9.0':
         resolution: {integrity: sha512-l8U2lcqsl9yKPP5WUdIrKH//C1pWyM2cSUfcTBn6GSvXmsSjBNEdGSdM4Wfne777Oe/9ONaD1Ga53U2HksHHLw==}
         engines: {node: '>=14.21.3'}
         cpu: [arm64]
         os: [linux]
    -    libc: [glibc]
     
       '@biomejs/cli-linux-x64-musl@1.9.0':
         resolution: {integrity: sha512-N3enoFoIrkB6qJWyYfTiYmFdB1R/Mrij1dd1xBHqxxCKZY9GRkEswRX3F1Uqzo5T+9Iu8nAQobDqI/ygicYy/Q==}
         engines: {node: '>=14.21.3'}
         cpu: [x64]
         os: [linux]
    -    libc: [musl]
     
       '@biomejs/cli-linux-x64@1.9.0':
         resolution: {integrity: sha512-8jAzjrrJTj510pwq4aVs7ZKkOvEy1D+nzl9DKvrPh4TOyUw5Ie+0EDwXGE2RAkCKHkGNOQBZ78WtIdsATgz5sA==}
         engines: {node: '>=14.21.3'}
         cpu: [x64]
         os: [linux]
    -    libc: [glibc]
     
       '@biomejs/cli-win32-arm64@1.9.0':
         resolution: {integrity: sha512-AIjwJTGfdWGMRluSQ9pDB29nzce077dfHh0/HMqzztKzgD3spyuo2R9VoaFpbR0hLHPWEH6g6OxxDO7hfkXNkQ==}
    @@ -5242,79 +5239,67 @@ packages:
         resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==}
         cpu: [arm64]
         os: [linux]
    -    libc: [glibc]
     
       '@img/sharp-libvips-linux-arm@1.0.5':
         resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==}
         cpu: [arm]
         os: [linux]
    -    libc: [glibc]
     
       '@img/sharp-libvips-linux-s390x@1.0.4':
         resolution: {integrity: sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==}
         cpu: [s390x]
         os: [linux]
    -    libc: [glibc]
     
       '@img/sharp-libvips-linux-x64@1.0.4':
         resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==}
         cpu: [x64]
         os: [linux]
    -    libc: [glibc]
     
       '@img/sharp-libvips-linuxmusl-arm64@1.0.4':
         resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==}
         cpu: [arm64]
         os: [linux]
    -    libc: [musl]
     
       '@img/sharp-libvips-linuxmusl-x64@1.0.4':
         resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==}
         cpu: [x64]
         os: [linux]
    -    libc: [musl]
     
       '@img/sharp-linux-arm64@0.33.5':
         resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==}
         engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
         cpu: [arm64]
         os: [linux]
    -    libc: [glibc]
     
       '@img/sharp-linux-arm@0.33.5':
         resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==}
         engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
         cpu: [arm]
         os: [linux]
    -    libc: [glibc]
     
       '@img/sharp-linux-s390x@0.33.5':
         resolution: {integrity: sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==}
         engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
         cpu: [s390x]
         os: [linux]
    -    libc: [glibc]
     
       '@img/sharp-linux-x64@0.33.5':
         resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==}
         engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
         cpu: [x64]
         os: [linux]
    -    libc: [glibc]
     
       '@img/sharp-linuxmusl-arm64@0.33.5':
         resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==}
         engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
         cpu: [arm64]
         os: [linux]
    -    libc: [musl]
     
       '@img/sharp-linuxmusl-x64@0.33.5':
         resolution: {integrity: sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==}
         engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
         cpu: [x64]
         os: [linux]
    -    libc: [musl]
     
       '@img/sharp-wasm32@0.33.5':
         resolution: {integrity: sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==}
    @@ -6251,35 +6236,30 @@ packages:
         engines: {node: '>= 10'}
         cpu: [arm64]
         os: [linux]
    -    libc: [glibc]
     
       '@napi-rs/canvas-linux-arm64-musl@0.1.70':
         resolution: {integrity: sha512-wBTOllEYNfJCHOdZj9v8gLzZ4oY3oyPX8MSRvaxPm/s7RfEXxCyZ8OhJ5xAyicsDdbE5YBZqdmaaeP5+xKxvtg==}
         engines: {node: '>= 10'}
         cpu: [arm64]
         os: [linux]
    -    libc: [musl]
     
       '@napi-rs/canvas-linux-riscv64-gnu@0.1.70':
         resolution: {integrity: sha512-GVUUPC8TuuFqHip0rxHkUqArQnlzmlXmTEBuXAWdgCv85zTCFH8nOHk/YCF5yo0Z2eOm8nOi90aWs0leJ4OE5Q==}
         engines: {node: '>= 10'}
         cpu: [riscv64]
         os: [linux]
    -    libc: [glibc]
     
       '@napi-rs/canvas-linux-x64-gnu@0.1.70':
         resolution: {integrity: sha512-/kvUa2lZRwGNyfznSn5t1ShWJnr/m5acSlhTV3eXECafObjl0VBuA1HJw0QrilLpb4Fe0VLywkpD1NsMoVDROQ==}
         engines: {node: '>= 10'}
         cpu: [x64]
         os: [linux]
    -    libc: [glibc]
     
       '@napi-rs/canvas-linux-x64-musl@0.1.70':
         resolution: {integrity: sha512-aqlv8MLpycoMKRmds7JWCfVwNf1fiZxaU7JwJs9/ExjTD8lX2KjsO7CTeAj5Cl4aEuzxUWbJPUUE2Qu9cZ1vfg==}
         engines: {node: '>= 10'}
         cpu: [x64]
         os: [linux]
    -    libc: [musl]
     
       '@napi-rs/canvas-win32-x64-msvc@0.1.70':
         resolution: {integrity: sha512-Q9QU3WIpwBTVHk4cPfBjGHGU4U0llQYRXgJtFtYqqGNEOKVN4OT6PQ+ve63xwIPODMpZ0HHyj/KLGc9CWc3EtQ==}
    @@ -6599,42 +6579,36 @@ packages:
         engines: {node: '>= 10.0.0'}
         cpu: [arm]
         os: [linux]
    -    libc: [glibc]
     
       '@parcel/watcher-linux-arm-musl@2.5.1':
         resolution: {integrity: sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==}
         engines: {node: '>= 10.0.0'}
         cpu: [arm]
         os: [linux]
    -    libc: [musl]
     
       '@parcel/watcher-linux-arm64-glibc@2.5.1':
         resolution: {integrity: sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==}
         engines: {node: '>= 10.0.0'}
         cpu: [arm64]
         os: [linux]
    -    libc: [glibc]
     
       '@parcel/watcher-linux-arm64-musl@2.5.1':
         resolution: {integrity: sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==}
         engines: {node: '>= 10.0.0'}
         cpu: [arm64]
         os: [linux]
    -    libc: [musl]
     
       '@parcel/watcher-linux-x64-glibc@2.5.1':
         resolution: {integrity: sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==}
         engines: {node: '>= 10.0.0'}
         cpu: [x64]
         os: [linux]
    -    libc: [glibc]
     
       '@parcel/watcher-linux-x64-musl@2.5.1':
         resolution: {integrity: sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==}
         engines: {node: '>= 10.0.0'}
         cpu: [x64]
         os: [linux]
    -    libc: [musl]
     
       '@parcel/watcher-win32-arm64@2.5.1':
         resolution: {integrity: sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==}
    @@ -6843,56 +6817,48 @@ packages:
         engines: {node: ^20.19.0 || >=22.12.0}
         cpu: [arm64]
         os: [linux]
    -    libc: [glibc]
     
       '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.50':
         resolution: {integrity: sha512-ONgyjofCrrE3bnh5GZb8EINSFyR/hmwTzZ7oVuyUB170lboza1VMCnb8jgE6MsyyRgHYmN8Lb59i3NKGrxrYjw==}
         engines: {node: ^20.19.0 || >=22.12.0}
         cpu: [arm64]
         os: [linux]
    -    libc: [glibc]
     
       '@rolldown/binding-linux-arm64-musl@1.0.0-beta.42':
         resolution: {integrity: sha512-/bNTYb9aKNhzdbPn3O4MK2aLv55AlrkUKPE4KNfBYjkoZUfDr4jWp7gsSlvTc5A/99V1RCm9axvt616ZzeXGyA==}
         engines: {node: ^20.19.0 || >=22.12.0}
         cpu: [arm64]
         os: [linux]
    -    libc: [musl]
     
       '@rolldown/binding-linux-arm64-musl@1.0.0-beta.50':
         resolution: {integrity: sha512-L0zRdH2oDPkmB+wvuTl+dJbXCsx62SkqcEqdM+79LOcB+PxbAxxjzHU14BuZIQdXcAVDzfpMfaHWzZuwhhBTcw==}
         engines: {node: ^20.19.0 || >=22.12.0}
         cpu: [arm64]
         os: [linux]
    -    libc: [musl]
     
       '@rolldown/binding-linux-x64-gnu@1.0.0-beta.42':
         resolution: {integrity: sha512-n/SLa4h342oyeGykZdch7Y3GNCNliRPL4k5wkeZ/5eQZs+c6/ZG1SHCJQoy7bZcmxiMyaXs9HoFmv1PEKrZgWg==}
         engines: {node: ^20.19.0 || >=22.12.0}
         cpu: [x64]
         os: [linux]
    -    libc: [glibc]
     
       '@rolldown/binding-linux-x64-gnu@1.0.0-beta.50':
         resolution: {integrity: sha512-gyoI8o/TGpQd3OzkJnh1M2kxy1Bisg8qJ5Gci0sXm9yLFzEXIFdtc4EAzepxGvrT2ri99ar5rdsmNG0zP0SbIg==}
         engines: {node: ^20.19.0 || >=22.12.0}
         cpu: [x64]
         os: [linux]
    -    libc: [glibc]
     
       '@rolldown/binding-linux-x64-musl@1.0.0-beta.42':
         resolution: {integrity: sha512-4PSd46sFzqpLHSGdaSViAb1mk55sCUMpJg+X8ittXaVocQsV3QLG/uydSH8RyL0ngHX5fy3D70LcCzlB15AgHw==}
         engines: {node: ^20.19.0 || >=22.12.0}
         cpu: [x64]
         os: [linux]
    -    libc: [musl]
     
       '@rolldown/binding-linux-x64-musl@1.0.0-beta.50':
         resolution: {integrity: sha512-zti8A7M+xFDpKlghpcCAzyOi+e5nfUl3QhU023ce5NCgUxRG5zGP2GR9LTydQ1rnIPwZUVBWd4o7NjZDaQxaXA==}
         engines: {node: ^20.19.0 || >=22.12.0}
         cpu: [x64]
         os: [linux]
    -    libc: [musl]
     
       '@rolldown/binding-openharmony-arm64@1.0.0-beta.42':
         resolution: {integrity: sha512-BmWoeJJyeZXmZBcfoxG6J9+rl2G7eO47qdTkAzEegj4n3aC6CBIHOuDcbE8BvhZaEjQR0nh0nJrtEDlt65Q7Sw==}
    @@ -7040,133 +7006,111 @@ packages:
         resolution: {integrity: sha512-OVSQgEZDVLnTbMq5NBs6xkmz3AADByCWI4RdKSFNlDsYXdFtlxS59J+w+LippJe8KcmeSSM3ba+GlsM9+WwC1w==}
         cpu: [arm]
         os: [linux]
    -    libc: [glibc]
     
       '@rollup/rollup-linux-arm-gnueabihf@4.52.4':
         resolution: {integrity: sha512-xRiOu9Of1FZ4SxVbB0iEDXc4ddIcjCv2aj03dmW8UrZIW7aIQ9jVJdLBIhxBI+MaTnGAKyvMwPwQnoOEvP7FgQ==}
         cpu: [arm]
         os: [linux]
    -    libc: [glibc]
     
       '@rollup/rollup-linux-arm-musleabihf@4.49.0':
         resolution: {integrity: sha512-ZnfSFA7fDUHNa4P3VwAcfaBLakCbYaxCk0jUnS3dTou9P95kwoOLAMlT3WmEJDBCSrOEFFV0Y1HXiwfLYJuLlA==}
         cpu: [arm]
         os: [linux]
    -    libc: [musl]
     
       '@rollup/rollup-linux-arm-musleabihf@4.52.4':
         resolution: {integrity: sha512-FbhM2p9TJAmEIEhIgzR4soUcsW49e9veAQCziwbR+XWB2zqJ12b4i/+hel9yLiD8pLncDH4fKIPIbt5238341Q==}
         cpu: [arm]
         os: [linux]
    -    libc: [musl]
     
       '@rollup/rollup-linux-arm64-gnu@4.49.0':
         resolution: {integrity: sha512-Z81u+gfrobVK2iV7GqZCBfEB1y6+I61AH466lNK+xy1jfqFLiQ9Qv716WUM5fxFrYxwC7ziVdZRU9qvGHkYIJg==}
         cpu: [arm64]
         os: [linux]
    -    libc: [glibc]
     
       '@rollup/rollup-linux-arm64-gnu@4.52.4':
         resolution: {integrity: sha512-4n4gVwhPHR9q/g8lKCyz0yuaD0MvDf7dV4f9tHt0C73Mp8h38UCtSCSE6R9iBlTbXlmA8CjpsZoujhszefqueg==}
         cpu: [arm64]
         os: [linux]
    -    libc: [glibc]
     
       '@rollup/rollup-linux-arm64-musl@4.49.0':
         resolution: {integrity: sha512-zoAwS0KCXSnTp9NH/h9aamBAIve0DXeYpll85shf9NJ0URjSTzzS+Z9evmolN+ICfD3v8skKUPyk2PO0uGdFqg==}
         cpu: [arm64]
         os: [linux]
    -    libc: [musl]
     
       '@rollup/rollup-linux-arm64-musl@4.52.4':
         resolution: {integrity: sha512-u0n17nGA0nvi/11gcZKsjkLj1QIpAuPFQbR48Subo7SmZJnGxDpspyw2kbpuoQnyK+9pwf3pAoEXerJs/8Mi9g==}
         cpu: [arm64]
         os: [linux]
    -    libc: [musl]
     
       '@rollup/rollup-linux-loong64-gnu@4.52.4':
         resolution: {integrity: sha512-0G2c2lpYtbTuXo8KEJkDkClE/+/2AFPdPAbmaHoE870foRFs4pBrDehilMcrSScrN/fB/1HTaWO4bqw+ewBzMQ==}
         cpu: [loong64]
         os: [linux]
    -    libc: [glibc]
     
       '@rollup/rollup-linux-loongarch64-gnu@4.49.0':
         resolution: {integrity: sha512-2QyUyQQ1ZtwZGiq0nvODL+vLJBtciItC3/5cYN8ncDQcv5avrt2MbKt1XU/vFAJlLta5KujqyHdYtdag4YEjYQ==}
         cpu: [loong64]
         os: [linux]
    -    libc: [glibc]
     
       '@rollup/rollup-linux-ppc64-gnu@4.49.0':
         resolution: {integrity: sha512-k9aEmOWt+mrMuD3skjVJSSxHckJp+SiFzFG+v8JLXbc/xi9hv2icSkR3U7uQzqy+/QbbYY7iNB9eDTwrELo14g==}
         cpu: [ppc64]
         os: [linux]
    -    libc: [glibc]
     
       '@rollup/rollup-linux-ppc64-gnu@4.52.4':
         resolution: {integrity: sha512-teSACug1GyZHmPDv14VNbvZFX779UqWTsd7KtTM9JIZRDI5NUwYSIS30kzI8m06gOPB//jtpqlhmraQ68b5X2g==}
         cpu: [ppc64]
         os: [linux]
    -    libc: [glibc]
     
       '@rollup/rollup-linux-riscv64-gnu@4.49.0':
         resolution: {integrity: sha512-rDKRFFIWJ/zJn6uk2IdYLc09Z7zkE5IFIOWqpuU0o6ZpHcdniAyWkwSUWE/Z25N/wNDmFHHMzin84qW7Wzkjsw==}
         cpu: [riscv64]
         os: [linux]
    -    libc: [glibc]
     
       '@rollup/rollup-linux-riscv64-gnu@4.52.4':
         resolution: {integrity: sha512-/MOEW3aHjjs1p4Pw1Xk4+3egRevx8Ji9N6HUIA1Ifh8Q+cg9dremvFCUbOX2Zebz80BwJIgCBUemjqhU5XI5Eg==}
         cpu: [riscv64]
         os: [linux]
    -    libc: [glibc]
     
       '@rollup/rollup-linux-riscv64-musl@4.49.0':
         resolution: {integrity: sha512-FkkhIY/hYFVnOzz1WeV3S9Bd1h0hda/gRqvZCMpHWDHdiIHn6pqsY3b5eSbvGccWHMQ1uUzgZTKS4oGpykf8Tw==}
         cpu: [riscv64]
         os: [linux]
    -    libc: [musl]
     
       '@rollup/rollup-linux-riscv64-musl@4.52.4':
         resolution: {integrity: sha512-1HHmsRyh845QDpEWzOFtMCph5Ts+9+yllCrREuBR/vg2RogAQGGBRC8lDPrPOMnrdOJ+mt1WLMOC2Kao/UwcvA==}
         cpu: [riscv64]
         os: [linux]
    -    libc: [musl]
     
       '@rollup/rollup-linux-s390x-gnu@4.49.0':
         resolution: {integrity: sha512-gRf5c+A7QiOG3UwLyOOtyJMD31JJhMjBvpfhAitPAoqZFcOeK3Kc1Veg1z/trmt+2P6F/biT02fU19GGTS529A==}
         cpu: [s390x]
         os: [linux]
    -    libc: [glibc]
     
       '@rollup/rollup-linux-s390x-gnu@4.52.4':
         resolution: {integrity: sha512-seoeZp4L/6D1MUyjWkOMRU6/iLmCU2EjbMTyAG4oIOs1/I82Y5lTeaxW0KBfkUdHAWN7j25bpkt0rjnOgAcQcA==}
         cpu: [s390x]
         os: [linux]
    -    libc: [glibc]
     
       '@rollup/rollup-linux-x64-gnu@4.49.0':
         resolution: {integrity: sha512-BR7+blScdLW1h/2hB/2oXM+dhTmpW3rQt1DeSiCP9mc2NMMkqVgjIN3DDsNpKmezffGC9R8XKVOLmBkRUcK/sA==}
         cpu: [x64]
         os: [linux]
    -    libc: [glibc]
     
       '@rollup/rollup-linux-x64-gnu@4.52.4':
         resolution: {integrity: sha512-Wi6AXf0k0L7E2gteNsNHUs7UMwCIhsCTs6+tqQ5GPwVRWMaflqGec4Sd8n6+FNFDw9vGcReqk2KzBDhCa1DLYg==}
         cpu: [x64]
         os: [linux]
    -    libc: [glibc]
     
       '@rollup/rollup-linux-x64-musl@4.49.0':
         resolution: {integrity: sha512-hDMOAe+6nX3V5ei1I7Au3wcr9h3ktKzDvF2ne5ovX8RZiAHEtX1A5SNNk4zt1Qt77CmnbqT+upb/umzoPMWiPg==}
         cpu: [x64]
         os: [linux]
    -    libc: [musl]
     
       '@rollup/rollup-linux-x64-musl@4.52.4':
         resolution: {integrity: sha512-dtBZYjDmCQ9hW+WgEkaffvRRCKm767wWhxsFW3Lw86VXz/uJRuD438/XvbZT//B96Vs8oTA8Q4A0AfHbrxP9zw==}
         cpu: [x64]
         os: [linux]
    -    libc: [musl]
     
       '@rollup/rollup-openharmony-arm64@4.52.4':
         resolution: {integrity: sha512-1ox+GqgRWqaB1RnyZXL8PD6E5f7YyRUJYnCqKpNzxzP0TkaUh112NDrR9Tt+C8rJ4x5G9Mk8PQR3o7Ku2RKqKA==}
    @@ -8720,49 +8664,41 @@ packages:
         resolution: {integrity: sha512-UYA0MA8ajkEDCFRQdng/FVx3F6szBvk3EPnkTTQuuO9lV1kPGuTB+V9TmbDxy5ikaEgyWKxa4CI3ySjklZ9lFA==}
         cpu: [arm64]
         os: [linux]
    -    libc: [glibc]
     
       '@unrs/resolver-binding-linux-arm64-musl@1.9.2':
         resolution: {integrity: sha512-P/CO3ODU9YJIHFqAkHbquKtFst0COxdphc8TKGL5yCX75GOiVpGqd1d15ahpqu8xXVsqP4MGFP2C3LRZnnL5MA==}
         cpu: [arm64]
         os: [linux]
    -    libc: [musl]
     
       '@unrs/resolver-binding-linux-ppc64-gnu@1.9.2':
         resolution: {integrity: sha512-uKStFlOELBxBum2s1hODPtgJhY4NxYJE9pAeyBgNEzHgTqTiVBPjfTlPFJkfxyTjQEuxZbbJlJnMCrRgD7ubzw==}
         cpu: [ppc64]
         os: [linux]
    -    libc: [glibc]
     
       '@unrs/resolver-binding-linux-riscv64-gnu@1.9.2':
         resolution: {integrity: sha512-LkbNnZlhINfY9gK30AHs26IIVEZ9PEl9qOScYdmY2o81imJYI4IMnJiW0vJVtXaDHvBvxeAgEy5CflwJFIl3tQ==}
         cpu: [riscv64]
         os: [linux]
    -    libc: [glibc]
     
       '@unrs/resolver-binding-linux-riscv64-musl@1.9.2':
         resolution: {integrity: sha512-vI+e6FzLyZHSLFNomPi+nT+qUWN4YSj8pFtQZSFTtmgFoxqB6NyjxSjAxEC1m93qn6hUXhIsh8WMp+fGgxCoRg==}
         cpu: [riscv64]
         os: [linux]
    -    libc: [musl]
     
       '@unrs/resolver-binding-linux-s390x-gnu@1.9.2':
         resolution: {integrity: sha512-sSO4AlAYhSM2RAzBsRpahcJB1msc6uYLAtP6pesPbZtptF8OU/CbCPhSRW6cnYOGuVmEmWVW5xVboAqCnWTeHQ==}
         cpu: [s390x]
         os: [linux]
    -    libc: [glibc]
     
       '@unrs/resolver-binding-linux-x64-gnu@1.9.2':
         resolution: {integrity: sha512-jkSkwch0uPFva20Mdu8orbQjv2A3G88NExTN2oPTI1AJ+7mZfYW3cDCTyoH6OnctBKbBVeJCEqh0U02lTkqD5w==}
         cpu: [x64]
         os: [linux]
    -    libc: [glibc]
     
       '@unrs/resolver-binding-linux-x64-musl@1.9.2':
         resolution: {integrity: sha512-Uk64NoiTpQbkpl+bXsbeyOPRpUoMdcUqa+hDC1KhMW7aN1lfW8PBlBH4mJ3n3Y47dYE8qi0XTxy1mBACruYBaw==}
         cpu: [x64]
         os: [linux]
    -    libc: [musl]
     
       '@unrs/resolver-binding-wasm32-wasi@1.9.2':
         resolution: {integrity: sha512-EpBGwkcjDicjR/ybC0g8wO5adPNdVuMrNalVgYcWi+gYtC1XYNuxe3rufcO7dA76OHGeVabcO6cSkPJKVcbCXQ==}
    @@ -9367,10 +9303,6 @@ packages:
         resolution: {integrity: sha512-WHw67kLXYbZuHTmcdbIrVArCq5wxo6NEuj3hiYAWr8mwJeC+C2mMCIBIWCiDoCye/OF/xelc+teJ1ERoWmnEIA==}
         engines: {node: '>=18'}
     
    -  ast-types@0.15.2:
    -    resolution: {integrity: sha512-c27loCv9QkZinsa5ProX751khO9DJl/AcB5c2KNtA6NRvHKS0PgLfcftz72KVq504vB0Gku5s2kUZzDBvQWvHg==}
    -    engines: {node: '>=4'}
    -
       ast-types@0.16.1:
         resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==}
         engines: {node: '>=4'}
    @@ -13425,28 +13357,24 @@ packages:
         engines: {node: '>= 12.0.0'}
         cpu: [arm64]
         os: [linux]
    -    libc: [glibc]
     
       lightningcss-linux-arm64-musl@1.30.2:
         resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==}
         engines: {node: '>= 12.0.0'}
         cpu: [arm64]
         os: [linux]
    -    libc: [musl]
     
       lightningcss-linux-x64-gnu@1.30.2:
         resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==}
         engines: {node: '>= 12.0.0'}
         cpu: [x64]
         os: [linux]
    -    libc: [glibc]
     
       lightningcss-linux-x64-musl@1.30.2:
         resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==}
         engines: {node: '>= 12.0.0'}
         cpu: [x64]
         os: [linux]
    -    libc: [musl]
     
       lightningcss-win32-arm64-msvc@1.30.2:
         resolution: {integrity: sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==}
    @@ -17644,8 +17572,8 @@ packages:
       vue-component-type-helpers@2.2.12:
         resolution: {integrity: sha512-YbGqHZ5/eW4SnkPNR44mKVc6ZKQoRs/Rux1sxC6rdwXb4qpbOSYfDr9DsTHolOTGmIKgM9j141mZbBeg05R1pw==}
     
    -  vue-component-type-helpers@3.1.3:
    -    resolution: {integrity: sha512-V1dOD8XYfstOKCnXbWyEJIrhTBMwSyNjv271L1Jlx9ExpNlCSuqOs3OdWrGJ0V544zXufKbcYabi/o+gK8lyfQ==}
    +  vue-component-type-helpers@3.1.4:
    +    resolution: {integrity: sha512-Uws7Ew1OzTTqHW8ZVl/qLl/HB+jf08M0NdFONbVWAx0N4gMLK8yfZDgeB77hDnBmaigWWEn5qP8T9BG59jIeyQ==}
     
       vue-demi@0.14.10:
         resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==}
    @@ -21013,7 +20941,7 @@ snapshots:
       '@gar/promisify@1.1.3':
         optional: true
     
    -  '@getzep/zep-cloud@1.0.12(@langchain/core@0.3.68(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67)))(encoding@0.1.13)(langchain@0.3.33(5cc28a029307bb3da1dcaf370c8a2b8d))':
    +  '@getzep/zep-cloud@1.0.12(@langchain/core@0.3.68(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67)))(encoding@0.1.13)(langchain@0.3.33(ca377405f102dc2905a39d54ecb4d621))':
         dependencies:
           form-data: 4.0.4
           node-fetch: 2.7.0(encoding@0.1.13)
    @@ -21022,7 +20950,7 @@ snapshots:
           zod: 3.25.67
         optionalDependencies:
           '@langchain/core': 0.3.68(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67))
    -      langchain: 0.3.33(5cc28a029307bb3da1dcaf370c8a2b8d)
    +      langchain: 0.3.33(ca377405f102dc2905a39d54ecb4d621)
         transitivePeerDependencies:
           - encoding
     
    @@ -21708,7 +21636,7 @@ snapshots:
           - aws-crt
           - encoding
     
    -  '@langchain/community@0.3.50(071f2de44c6bccc3a8cd2fadf2db3e78)':
    +  '@langchain/community@0.3.50(ba725e6da5f3cda58245f84e6fe2ecaf)':
         dependencies:
           '@browserbasehq/stagehand': 1.9.0(@playwright/test@1.56.0)(bufferutil@4.0.9)(deepmerge@4.3.1)(dotenv@16.6.1)(encoding@0.1.13)(openai@5.12.2(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67))(utf-8-validate@5.0.10)(zod@3.25.67)
           '@ibm-cloud/watsonx-ai': 1.1.2
    @@ -21720,7 +21648,7 @@ snapshots:
           flat: 5.0.2
           ibm-cloud-sdk-core: 5.3.2
           js-yaml: 4.1.0
    -      langchain: 0.3.33(5cc28a029307bb3da1dcaf370c8a2b8d)
    +      langchain: 0.3.33(ca377405f102dc2905a39d54ecb4d621)
           langsmith: 0.3.55(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67))
           openai: 5.12.2(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67)
           uuid: 10.0.0
    @@ -21735,7 +21663,7 @@ snapshots:
           '@azure/search-documents': 12.1.0
           '@azure/storage-blob': 12.26.0
           '@browserbasehq/sdk': 2.6.0(encoding@0.1.13)
    -      '@getzep/zep-cloud': 1.0.12(@langchain/core@0.3.68(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67)))(encoding@0.1.13)(langchain@0.3.33(5cc28a029307bb3da1dcaf370c8a2b8d))
    +      '@getzep/zep-cloud': 1.0.12(@langchain/core@0.3.68(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67)))(encoding@0.1.13)(langchain@0.3.33(ca377405f102dc2905a39d54ecb4d621))
           '@getzep/zep-js': 0.9.0
           '@google-ai/generativelanguage': 3.4.0(encoding@0.1.13)
           '@google-cloud/storage': 7.12.1(encoding@0.1.13)
    @@ -22859,7 +22787,7 @@ snapshots:
         dependencies:
           '@rollup/pluginutils': 5.1.4(rollup@4.52.4)
           estree-walker: 2.0.2
    -      magic-string: 0.30.19
    +      magic-string: 0.30.21
         optionalDependencies:
           rollup: 4.52.4
     
    @@ -24059,7 +23987,7 @@ snapshots:
           storybook: 9.1.7(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10)(vite@7.0.0(@types/node@20.19.21)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3))
           type-fest: 2.19.0
           vue: 3.5.13(typescript@5.9.2)
    -      vue-component-type-helpers: 3.1.3
    +      vue-component-type-helpers: 3.1.4
     
       '@stylistic/eslint-plugin@5.0.0(eslint@9.29.0(jiti@2.6.1))':
         dependencies:
    @@ -25115,15 +25043,15 @@ snapshots:
         dependencies:
           '@vitest/spy': 3.2.4
           estree-walker: 3.0.3
    -      magic-string: 0.30.19
    +      magic-string: 0.30.21
         optionalDependencies:
           vite: rolldown-vite@7.1.16(@types/node@20.19.21)(esbuild@0.25.10)(jiti@2.6.1)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3)
     
       '@vitest/mocker@3.2.4(vite@7.0.0(@types/node@20.19.21)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3))':
         dependencies:
           '@vitest/spy': 3.2.4
           estree-walker: 3.0.3
    -      magic-string: 0.30.19
    +      magic-string: 0.30.21
         optionalDependencies:
           vite: 7.0.0(@types/node@20.19.21)(jiti@2.6.1)(lightningcss@1.30.2)(sass@1.89.2)(terser@5.16.1)(tsx@4.19.3)
     
    @@ -25792,10 +25720,6 @@ snapshots:
     
       ast-module-types@6.0.1: {}
     
    -  ast-types@0.15.2:
    -    dependencies:
    -      tslib: 2.6.2
    -
       ast-types@0.16.1:
         dependencies:
           tslib: 2.8.1
    @@ -25871,14 +25795,6 @@ snapshots:
         transitivePeerDependencies:
           - debug
     
    -  axios@1.12.0(debug@4.4.3):
    -    dependencies:
    -      follow-redirects: 1.15.11(debug@4.4.3)
    -      form-data: 4.0.4
    -      proxy-from-env: 1.1.0
    -    transitivePeerDependencies:
    -      - debug
    -
       b4a@1.6.7: {}
     
       babel-jest@29.6.2(@babel/core@7.28.4):
    @@ -28655,10 +28571,6 @@ snapshots:
         optionalDependencies:
           debug: 4.4.1(supports-color@8.1.1)
     
    -  follow-redirects@1.15.11(debug@4.4.3):
    -    optionalDependencies:
    -      debug: 4.4.3
    -
       for-each@0.3.5:
         dependencies:
           is-callable: 1.2.7
    @@ -29361,7 +29273,7 @@ snapshots:
           '@types/debug': 4.1.12
           '@types/node': 20.19.21
           '@types/tough-cookie': 4.0.5
    -      axios: 1.12.0(debug@4.4.3)
    +      axios: 1.12.0(debug@4.4.1)
           camelcase: 6.3.0
           debug: 4.4.3
           dotenv: 16.6.1
    @@ -29371,7 +29283,7 @@ snapshots:
           isstream: 0.1.2
           jsonwebtoken: 9.0.2
           mime-types: 2.1.35
    -      retry-axios: 2.6.0(axios@1.12.0)
    +      retry-axios: 2.6.0(axios@1.12.0(debug@4.4.3))
           tough-cookie: 4.1.4
         transitivePeerDependencies:
           - supports-color
    @@ -30828,7 +30740,7 @@ snapshots:
     
       kuler@2.0.0: {}
     
    -  langchain@0.3.33(5cc28a029307bb3da1dcaf370c8a2b8d):
    +  langchain@0.3.33(ca377405f102dc2905a39d54ecb4d621):
         dependencies:
           '@langchain/core': 0.3.68(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67))
           '@langchain/openai': 0.6.16(@langchain/core@0.3.68(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.25.67)))(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))
    @@ -33480,7 +33392,7 @@ snapshots:
       recast@0.22.0:
         dependencies:
           assert: 2.1.0
    -      ast-types: 0.15.2
    +      ast-types: 0.16.1
           esprima: 4.0.1
           source-map: 0.6.1
           tslib: 2.8.1
    @@ -33721,7 +33633,7 @@ snapshots:
           onetime: 5.1.2
           signal-exit: 3.0.7
     
    -  retry-axios@2.6.0(axios@1.12.0):
    +  retry-axios@2.6.0(axios@1.12.0(debug@4.4.3)):
         dependencies:
           axios: 1.12.0(debug@4.4.1)
     
    @@ -35386,7 +35298,7 @@ snapshots:
           obug: 2.0.0(ms@2.1.3)
           rolldown: 1.0.0-beta.50
           rolldown-plugin-dts: 0.17.8(ms@2.1.3)(rolldown@1.0.0-beta.50)(typescript@5.9.2)(vue-tsc@2.2.8(patch_hash=e2aee939ccac8a57fe449bfd92bedd8117841579526217bc39aca26c6b8c317f)(typescript@5.9.2))
    -      semver: 7.7.3
    +      semver: 7.7.2
           tinyexec: 1.0.2
           tinyglobby: 0.2.15
           tree-kill: 1.2.2
    @@ -36056,7 +35968,7 @@ snapshots:
     
       vue-component-type-helpers@2.2.12: {}
     
    -  vue-component-type-helpers@3.1.3: {}
    +  vue-component-type-helpers@3.1.4: {}
     
       vue-demi@0.14.10(vue@3.5.13(typescript@5.9.2)):
         dependencies:
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

8

News mentions

0

No linked articles in our index yet.