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.
| Package | Affected versions | Patched versions |
|---|---|---|
n8nnpm | >= 0.187.0, < 1.120.3 | 1.120.3 |
Affected products
1Patches
1ae0669a736ccfix(core): Validate package version when installing community node (#21886)
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- github.com/advisories/GHSA-7c4h-vh2m-743mghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2026-21893ghsaADVISORY
- github.com/n8n-io/n8n/commit/ae0669a736cc496beeb296e115267862727ae838ghsax_refsource_MISCWEB
- github.com/n8n-io/n8n/security/advisories/GHSA-7c4h-vh2m-743mghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.