From 0a0d926531ca3c8f6f25725d268744d06870deab Mon Sep 17 00:00:00 2001 From: Kristian Bremberg <114284895+KristianGrafana@users.noreply.github.com> Date: Fri, 11 Jul 2025 12:13:23 +0200 Subject: [PATCH] BackendSrv: Validate newline and tabs in validatePath (#108008) Validate newline and tabs in validatePath --- .../grafana-data/src/text/sanitize.test.ts | 21 +++++++++++++++++++ packages/grafana-data/src/text/sanitize.ts | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/packages/grafana-data/src/text/sanitize.test.ts b/packages/grafana-data/src/text/sanitize.test.ts index 218e4064046..c3ce3d3eb90 100644 --- a/packages/grafana-data/src/text/sanitize.test.ts +++ b/packages/grafana-data/src/text/sanitize.test.ts @@ -78,6 +78,27 @@ describe('validatePath', () => { expect(() => validatePath('/api/%/admin')).toThrow(PathValidationError); expect(() => validatePath('/api/%2/admin')).toThrow(PathValidationError); }); + + it('should block paths with tab characters', () => { + expect(() => validatePath('/api/\tadmin')).toThrow(PathValidationError); + expect(() => validatePath('/api/users\t/123')).toThrow(PathValidationError); + }); + + it('should block paths with newline characters', () => { + expect(() => validatePath('/api/\nadmin')).toThrow(PathValidationError); + expect(() => validatePath('/api/users\n/123')).toThrow(PathValidationError); + }); + + it('should block paths with carriage return characters', () => { + expect(() => validatePath('/api/\radmin')).toThrow(PathValidationError); + expect(() => validatePath('/api/users\r/123')).toThrow(PathValidationError); + }); + + it('should block URL encoded tab and newline characters', () => { + expect(() => validatePath('/api/%09admin')).toThrow(PathValidationError); // tab + expect(() => validatePath('/api/%0Aadmin')).toThrow(PathValidationError); // newline + expect(() => validatePath('/api/%0Dadmin')).toThrow(PathValidationError); // carriage return + }); }); describe('safe paths', () => { diff --git a/packages/grafana-data/src/text/sanitize.ts b/packages/grafana-data/src/text/sanitize.ts index 8fed4311627..0c3dadd5ebf 100644 --- a/packages/grafana-data/src/text/sanitize.ts +++ b/packages/grafana-data/src/text/sanitize.ts @@ -151,7 +151,7 @@ export function validatePath(path: OriginalPath): O originalDecoded = cleaned; // If the original string contains traversal attempts, block it - if (originalDecoded.includes('..') || originalDecoded.includes('/\\')) { + if (/\.\.|\/\\|[\t\n\r]/.test(originalDecoded)) { throw new PathValidationError(); }