From d5bef187e21122f78ddec8c8fe7550c83203ddde Mon Sep 17 00:00:00 2001 From: erikb-stripe Date: Thu, 12 Dec 2024 09:58:43 -0500 Subject: [PATCH] Explicitly enforce project name constraints in StripeTerminal (#840) --- src/stripeTerminal.ts | 13 +++++-- test/suite/stripeTerminal.test.ts | 64 +++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 3 deletions(-) diff --git a/src/stripeTerminal.ts b/src/stripeTerminal.ts index e3daa664..f9f61f93 100644 --- a/src/stripeTerminal.ts +++ b/src/stripeTerminal.ts @@ -57,9 +57,16 @@ export class StripeTerminal { private getGlobalCLIFlags(): Array { const stripeConfig = vscode.workspace.getConfiguration('stripe'); - let projectName = stripeConfig.get('projectName', null); - if (projectName !== null) { - projectName = projectName.replace(/[\\"'`]/g, ''); + const projectName = stripeConfig.get('projectName', null); + + if (projectName !== null && projectName !== '') { + // Regex to validate project name + const projectNameRegex = /^[a-zA-Z0-9_-\s]+$/; + + // Validate project name against the regex + if (!projectNameRegex.test(projectName)) { + throw new Error(`Invalid project name: '${projectName}'. Project names can only contain letters, numbers, spaces, underscores, and hyphens.`); + } } const projectNameFlag = projectName ? ['--project-name', projectName] : []; diff --git a/test/suite/stripeTerminal.test.ts b/test/suite/stripeTerminal.test.ts index 0714756f..76fe9ebe 100644 --- a/test/suite/stripeTerminal.test.ts +++ b/test/suite/stripeTerminal.test.ts @@ -40,6 +40,25 @@ suite('stripeTerminal', function () { .stub(stripeClientStub, 'getCLIPath') .returns(Promise.resolve(path)); + // Mock the getConfiguration function to return a valid project name + sandbox.stub(vscode.workspace, 'getConfiguration').returns({ + get: (key: string) => { + if (key === 'projectName') { + return 'Valid_Project-Name'; // Valid project name + } + return null; + }, + has: function (section: string): boolean { + throw new Error('Function not implemented.'); + }, + inspect: function (section: string): { key: string; defaultValue?: T; globalValue?: T; workspaceValue?: T; workspaceFolderValue?: T; defaultLanguageValue?: T; globalLanguageValue?: T; workspaceLanguageValue?: T; workspaceFolderLanguageValue?: T; languageIds?: string[]; } | undefined { + throw new Error('Function not implemented.'); + }, + update: function (section: string, value: any, configurationTarget?: vscode.ConfigurationTarget | boolean | null, overrideInLanguage?: boolean): Thenable { + throw new Error('Function not implemented.'); + } + }); + const stripeTerminal = new StripeTerminal(stripeClientStub); await stripeTerminal.execute('listen', ['--forward-to', 'localhost']); @@ -54,6 +73,8 @@ suite('stripeTerminal', function () { 'listen', '--forward-to', 'localhost', + '--project-name', + 'Valid_Project-Name', ], { shellQuoting: { @@ -67,6 +88,49 @@ suite('stripeTerminal', function () { ]); }); }); + + test('throws error for invalid project name', async () => { + // Mock the configuration with an invalid project name + const stripeClientStub = { + getCLIPath: () => { }, + isAuthenticated: () => true, + }; + + // Mock the getConfiguration function to return an invalid project name + sandbox.stub(vscode.workspace, 'getConfiguration').returns({ + get: (key: string) => { + if (key === 'projectName') { + return 'Invalid Project Name!'; // Invalid project name + } + return null; + }, + has: function (section: string): boolean { + throw new Error('Function not implemented.'); + }, + inspect: function (section: string): { key: string; defaultValue?: T; globalValue?: T; workspaceValue?: T; workspaceFolderValue?: T; defaultLanguageValue?: T; globalLanguageValue?: T; workspaceLanguageValue?: T; workspaceFolderLanguageValue?: T; languageIds?: string[]; } | undefined { + throw new Error('Function not implemented.'); + }, + update: function (section: string, value: any, configurationTarget?: vscode.ConfigurationTarget | boolean | null, overrideInLanguage?: boolean): Thenable { + throw new Error('Function not implemented.'); + } + }); + + sandbox.stub(vscode.window, 'createTerminal').returns(terminalStub); + sandbox.stub(stripeClientStub, 'getCLIPath').returns(Promise.resolve(path)); + + const stripeTerminal = new StripeTerminal(stripeClientStub); + + // Expect an error to be thrown due to invalid project name + await assert.rejects( + async () => { + await stripeTerminal.execute('listen', ['--forward-to', 'localhost']); + }, + { + name: 'Error', + message: "Invalid project name: 'Invalid Project Name!'. Project names can only contain letters, numbers, spaces, underscores, and hyphens.", + } + ); + }); }); suite('with no Stripe CLI installed', () => {