From 819cc63451f414afe08a6d3c38e6ce62d4857354 Mon Sep 17 00:00:00 2001 From: Alban Bailly Date: Thu, 20 Mar 2025 15:26:16 -0400 Subject: [PATCH 1/3] Remove reliance on regex for utils with security vulnerabilities --- packages/utilities/src/helpers/stringUtils.ts | 28 +++++++++++++++---- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/packages/utilities/src/helpers/stringUtils.ts b/packages/utilities/src/helpers/stringUtils.ts index e6a886355e3..fc917f23167 100644 --- a/packages/utilities/src/helpers/stringUtils.ts +++ b/packages/utilities/src/helpers/stringUtils.ts @@ -29,20 +29,36 @@ export const wrapInQuotes = (s: string) => '"' + s + '"'; export const isNumeric = (s: string) => /^\d+$/.test(s); +const getNumberMatch = (str: string) => { + let match = ''; + + // Start from the end of string and work backwards + for (let i = str.length - 1; i >= 0; i--) { + const char = str[i]; + // Check if character is a digit + if (char >= '0' && char <= '9') { + match = char + match; + } else { + // Stop when we hit a non-digit + break; + } + } + + return match; +}; + export function getNumberAtEnd(str: string) { - // Use a regular expression to match one or more digits at the end of the string - const match = str.match(/\d+$/); + const match = getNumberMatch(str); // If there is a match, return the matched number; otherwise, return null - return match ? parseInt(match[0], 10) : null; + return match ? parseInt(match, 10) : null; } export function removeNumberAtEnd(str: string) { - // Use a regular expression to match one or more digits at the end of the string - const regex = /\d+$/; + const match = getNumberMatch(str); // Use the replace() method to remove the matched portion - return str.replace(regex, ''); + return str.replace(match, ''); } /** From 21160c50f3353f3f7afa6b4dda304cdcf569d1c2 Mon Sep 17 00:00:00 2001 From: Alban Bailly Date: Thu, 20 Mar 2025 15:31:22 -0400 Subject: [PATCH 2/3] remove unused utils with security vulnerabilities --- .../utilities/src/helpers/stringUtils.test.ts | 49 +-------------- packages/utilities/src/helpers/stringUtils.ts | 60 ------------------- 2 files changed, 1 insertion(+), 108 deletions(-) diff --git a/packages/utilities/src/helpers/stringUtils.test.ts b/packages/utilities/src/helpers/stringUtils.test.ts index 7456ac93783..35f6f4e8a27 100644 --- a/packages/utilities/src/helpers/stringUtils.test.ts +++ b/packages/utilities/src/helpers/stringUtils.test.ts @@ -1,12 +1,6 @@ import { describe, expect, it } from 'vitest'; -import { - getNextLabel, - getNumberAtEnd, - isNumeric, - removeNumberAtEnd, - truncateAndJoinList, -} from './stringUtils'; +import { isNumeric, truncateAndJoinList } from './stringUtils'; describe('truncateAndJoinList', () => { const strList = ['a', 'b', 'c']; @@ -57,44 +51,3 @@ describe('isNumeric', () => { expect(isNumeric('my-linode')).toBe(false); }); }); - -describe('getNumberAtEnd', () => { - it('should return 1 when given test-1', () => { - expect(getNumberAtEnd('test-1')).toBe(1); - }); - it('should return null if there is no number in the string', () => { - expect(getNumberAtEnd('test')).toBe(null); - }); - it('should get the last number in the string', () => { - expect(getNumberAtEnd('test-1-2-3')).toBe(3); - }); - it('should handle a string that only contains numbers', () => { - expect(getNumberAtEnd('123')).toBe(123); - }); -}); - -describe('removeNumberAtEnd', () => { - it('should return 1 in "test-1"', () => { - expect(removeNumberAtEnd('test-1')).toBe('test-'); - }); - it('should return the same string if there is no number at the end', () => { - expect(removeNumberAtEnd('test')).toBe('test'); - }); - it('should return an empty string if the input is just a number', () => { - expect(removeNumberAtEnd('123')).toBe(''); - }); - it('should not remove the first number', () => { - expect(removeNumberAtEnd('1-2-3')).toBe('1-2-'); - }); -}); - -describe('getNextLabel', () => { - it('should append a number to get the next label', () => { - expect(getNextLabel({ label: 'test' }, [{ label: 'test' }])).toBe('test-1'); - }); - it('should not duplicate labels so that the returned label is unique', () => { - expect(getNextLabel({ label: 'test' }, [{ label: 'test-1' }])).toBe( - 'test-2' - ); - }); -}); diff --git a/packages/utilities/src/helpers/stringUtils.ts b/packages/utilities/src/helpers/stringUtils.ts index fc917f23167..c183b3af87d 100644 --- a/packages/utilities/src/helpers/stringUtils.ts +++ b/packages/utilities/src/helpers/stringUtils.ts @@ -28,63 +28,3 @@ export const truncateAndJoinList = ( export const wrapInQuotes = (s: string) => '"' + s + '"'; export const isNumeric = (s: string) => /^\d+$/.test(s); - -const getNumberMatch = (str: string) => { - let match = ''; - - // Start from the end of string and work backwards - for (let i = str.length - 1; i >= 0; i--) { - const char = str[i]; - // Check if character is a digit - if (char >= '0' && char <= '9') { - match = char + match; - } else { - // Stop when we hit a non-digit - break; - } - } - - return match; -}; - -export function getNumberAtEnd(str: string) { - const match = getNumberMatch(str); - - // If there is a match, return the matched number; otherwise, return null - return match ? parseInt(match, 10) : null; -} - -export function removeNumberAtEnd(str: string) { - const match = getNumberMatch(str); - - // Use the replace() method to remove the matched portion - return str.replace(match, ''); -} - -/** - * Gets the next available unique entity label - */ -export function getNextLabel( - selectedEntity: T, - allEntities: T[] -): string { - const numberAtEnd = getNumberAtEnd(selectedEntity.label); - - let labelToReturn = ''; - - if (numberAtEnd === null) { - labelToReturn = `${selectedEntity.label}-1`; - } else { - labelToReturn = `${removeNumberAtEnd(selectedEntity.label)}${ - numberAtEnd + 1 - }`; - } - - if (allEntities.some((r) => r.label === labelToReturn)) { - return getNextLabel( - { ...selectedEntity, label: labelToReturn }, - allEntities - ); - } - return labelToReturn; -} From 727e6c165ef84536ac70f44bc9f7569a0b236b81 Mon Sep 17 00:00:00 2001 From: Alban Bailly Date: Fri, 21 Mar 2025 09:20:39 -0400 Subject: [PATCH 3/3] Changeset --- .../utilities/.changeset/pr-11899-removed-1742563209985.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 packages/utilities/.changeset/pr-11899-removed-1742563209985.md diff --git a/packages/utilities/.changeset/pr-11899-removed-1742563209985.md b/packages/utilities/.changeset/pr-11899-removed-1742563209985.md new file mode 100644 index 00000000000..ed8fcff927f --- /dev/null +++ b/packages/utilities/.changeset/pr-11899-removed-1742563209985.md @@ -0,0 +1,5 @@ +--- +"@linode/utilities": Removed +--- + +Unused utils with security vulnerabilities ([#11899](https://github.com/linode/manager/pull/11899))