From 4dd853b2d5fe5e35940c14813da0fa72b6c87136 Mon Sep 17 00:00:00 2001 From: RomanDavydchuk Date: Fri, 14 Nov 2025 16:55:46 +0200 Subject: [PATCH] fix(Git Node): Disable git hooks by default (#21797) Co-authored-by: yehorkardash --- .../config/src/configs/security.config.ts | 6 +++++ packages/@n8n/config/test/config.test.ts | 1 + packages/nodes-base/nodes/Git/Git.node.ts | 5 ++++ .../nodes/Git/__test__/Git.node.test.ts | 27 +++++++++++++++++++ 4 files changed, 39 insertions(+) diff --git a/packages/@n8n/config/src/configs/security.config.ts b/packages/@n8n/config/src/configs/security.config.ts index 48dd3eb3956..5bba4f960b3 100644 --- a/packages/@n8n/config/src/configs/security.config.ts +++ b/packages/@n8n/config/src/configs/security.config.ts @@ -55,4 +55,10 @@ export class SecurityConfig { /** Whether to allow access to AWS system credentials, e.g. in awsAssumeRole credentials */ @Env('N8N_AWS_SYSTEM_CREDENTIALS_ACCESS_ENABLED') awsSystemCredentialsAccess: boolean = false; + + /** + * Whether to enable hooks (like pre-commit hooks) for the Git node. + */ + @Env('N8N_GIT_NODE_ENABLE_HOOKS') + enableGitNodeHooks: boolean = false; } diff --git a/packages/@n8n/config/test/config.test.ts b/packages/@n8n/config/test/config.test.ts index aa7b6b1ee9b..1fdd2835cda 100644 --- a/packages/@n8n/config/test/config.test.ts +++ b/packages/@n8n/config/test/config.test.ts @@ -317,6 +317,7 @@ describe('GlobalConfig', () => { disableWebhookHtmlSandboxing: false, disableBareRepos: false, awsSystemCredentialsAccess: false, + enableGitNodeHooks: false, }, executions: { mode: 'regular', diff --git a/packages/nodes-base/nodes/Git/Git.node.ts b/packages/nodes-base/nodes/Git/Git.node.ts index be44c970d40..8017010a18a 100644 --- a/packages/nodes-base/nodes/Git/Git.node.ts +++ b/packages/nodes-base/nodes/Git/Git.node.ts @@ -302,6 +302,11 @@ export class Git implements INodeType { gitConfig.push('safe.bareRepository=explicit'); } + const enableHooks = securityConfig.enableGitNodeHooks; + if (!enableHooks) { + gitConfig.push('core.hooksPath=/dev/null'); + } + const gitOptions: Partial = { baseDir: repositoryPath, config: gitConfig, diff --git a/packages/nodes-base/nodes/Git/__test__/Git.node.test.ts b/packages/nodes-base/nodes/Git/__test__/Git.node.test.ts index 748cbc18a25..51a10add6cf 100644 --- a/packages/nodes-base/nodes/Git/__test__/Git.node.test.ts +++ b/packages/nodes-base/nodes/Git/__test__/Git.node.test.ts @@ -30,6 +30,7 @@ describe('Git Node', () => { }); securityConfig = mock({ disableBareRepos: false, + enableGitNodeHooks: true, }); Container.set(DeploymentConfig, deploymentConfig); Container.set(SecurityConfig, securityConfig); @@ -114,4 +115,30 @@ describe('Git Node', () => { ); }); }); + + describe('Hooks Configuration', () => { + it('should add core.hooksPath=/dev/null when enableGitNodeHooks is false', async () => { + securityConfig.enableGitNodeHooks = false; + + await gitNode.execute.call(executeFunctions); + + expect(mockSimpleGit).toHaveBeenCalledWith( + expect.objectContaining({ + config: ['core.hooksPath=/dev/null'], + }), + ); + }); + + it('should not add core.hooksPath=/dev/null when enableGitNodeHooks is true', async () => { + securityConfig.enableGitNodeHooks = true; + + await gitNode.execute.call(executeFunctions); + + expect(mockSimpleGit).toHaveBeenCalledWith( + expect.objectContaining({ + config: [], + }), + ); + }); + }); });