VYPR
Critical severityNVD Advisory· Published Feb 4, 2026· Updated Feb 4, 2026

n8n Vulnerable to Command Injection in Community Package Installation

CVE-2026-21893

Description

n8n is an open source workflow automation platform. From version 0.187.0 to before 1.120.3, a command injection vulnerability was identified in n8n’s community package installation functionality. The issue allowed authenticated users with administrative permissions to execute arbitrary system commands on the n8n host under specific conditions. This issue has been patched in version 1.120.3.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
n8nnpm
>= 0.187.0, < 1.120.31.120.3

Affected products

1

Patches

1
ae0669a736cc

fix(core): Validate package version when installing community node (#21886)

https://github.com/n8n-io/n8nRomanDavydchukNov 14, 2025via ghsa
4 files changed · +44 1
  • packages/cli/src/modules/community-packages/community-packages.controller.ts+9 0 modified
    @@ -15,6 +15,7 @@ import { CommunityNodeTypesService } from './community-node-types.service';
     import { CommunityPackagesService } from './community-packages.service';
     import type { CommunityPackages } from './community-packages.types';
     import { InstalledPackages } from './installed-packages.entity';
    +import { valid } from 'semver';
     
     const {
     	PACKAGE_NOT_INSTALLED,
    @@ -51,6 +52,10 @@ export class CommunityPackagesController {
     			throw new BadRequestError(PACKAGE_NAME_NOT_PROVIDED);
     		}
     
    +		if (version && !valid(version)) {
    +			throw new BadRequestError(`Invalid version: ${version}`);
    +		}
    +
     		let checksum: string | undefined = undefined;
     
     		// Get the checksum for the package if flagged to verify
    @@ -253,6 +258,10 @@ export class CommunityPackagesController {
     			throw new BadRequestError(PACKAGE_NAME_NOT_PROVIDED);
     		}
     
    +		if (version && !valid(version)) {
    +			throw new BadRequestError(`Invalid version: ${version}`);
    +		}
    +
     		const previouslyInstalledPackage =
     			await this.communityPackagesService.findInstalledPackage(name);
     
    
  • packages/cli/src/modules/community-packages/community-packages.service.ts+5 0 modified
    @@ -29,6 +29,7 @@ import type { CommunityPackages } from './community-packages.types';
     import { InstalledPackages } from './installed-packages.entity';
     import { InstalledPackagesRepository } from './installed-packages.repository';
     import { checkIfVersionExistsOrThrow, verifyIntegrity } from './npm-utils';
    +import { valid } from 'semver';
     
     const DEFAULT_REGISTRY = 'https://registry.npmjs.org';
     const NPM_COMMON_ARGS = ['--audit=false', '--fund=false'];
    @@ -145,6 +146,10 @@ export class CommunityPackagesService {
     			? packageNameWithoutScope.split('@')[1]
     			: undefined;
     
    +		if (version && !valid(version)) {
    +			throw new UnexpectedError(`Invalid version: ${version}`);
    +		}
    +
     		const packageName = version ? rawString.replace(`@${version}`, '') : rawString;
     
     		return { packageName, scope, version, rawString };
    
  • packages/cli/src/modules/community-packages/__tests__/community-packages.controller.test.ts+24 1 modified
    @@ -31,14 +31,27 @@ describe('CommunityPackagesController', () => {
     		it('should throw error if verify in options but no checksum', async () => {
     			const request = mock<NodeRequest.Post>({
     				user: { id: 'user123' },
    -				body: { name: 'n8n-nodes-test', verify: true },
    +				body: { name: 'n8n-nodes-test', verify: true, version: '1.0.0' },
     			});
     			communityNodeTypesService.findVetted.mockReturnValue(undefined);
     			await expect(controller.installPackage(request)).rejects.toThrow(
     				'Package n8n-nodes-test is not vetted for installation',
     			);
     		});
     
    +		it.each(['foo', 'echo "hello"', '1.a.b', '0.1.29#;ls'])(
    +			'should throw error if version is invalid',
    +			async (version) => {
    +				const request = mock<NodeRequest.Post>({
    +					user: { id: 'user123' },
    +					body: { name: 'n8n-nodes-test', verify: true, version },
    +				});
    +				await expect(controller.installPackage(request)).rejects.toThrow(
    +					`Invalid version: ${version}`,
    +				);
    +			},
    +		);
    +
     		it('should have correct version', async () => {
     			const request = mock<NodeRequest.Post>({
     				user: { id: 'user123' },
    @@ -119,5 +132,15 @@ describe('CommunityPackagesController', () => {
     
     			expect(result).toBe(newInstalledPackage);
     		});
    +
    +		it.each(['foo', 'echo "hello"', '1.a.b', '0.1.29#;ls'])(
    +			'should throw error if version is invalid',
    +			async (version) => {
    +				const req = mock<NodeRequest.Update>({
    +					body: { name: 'n8n-nodes-test', version, checksum: 'a893hfdsy7399' },
    +				});
    +				await expect(controller.updatePackage(req)).rejects.toThrow(`Invalid version: ${version}`);
    +			},
    +		);
     	});
     });
    
  • packages/cli/src/modules/community-packages/__tests__/community-packages.service.test.ts+6 0 modified
    @@ -101,6 +101,12 @@ describe('CommunityPackagesService', () => {
     			).toThrowError();
     		});
     
    +		test.each(['invalid', '1.a.b'])('should fail with invalid version', (version) => {
    +			expect(() =>
    +				communityPackagesService.parseNpmPackageName(`n8n-nodes-test@${version}`),
    +			).toThrow(`Invalid version: ${version}`);
    +		});
    +
     		test('should parse valid package name', () => {
     			const name = mockPackageName();
     			const parsed = communityPackagesService.parseNpmPackageName(name);
    

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

4

News mentions

0

No linked articles in our index yet.