Skip to content

Commit

Permalink
Explicitly enforce project name constraints in StripeTerminal (#840)
Browse files Browse the repository at this point in the history
  • Loading branch information
erikb-stripe authored Dec 12, 2024
1 parent cb9bba6 commit d5bef18
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 3 deletions.
13 changes: 10 additions & 3 deletions src/stripeTerminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,16 @@ export class StripeTerminal {
private getGlobalCLIFlags(): Array<string> {
const stripeConfig = vscode.workspace.getConfiguration('stripe');

let projectName = stripeConfig.get<string | null>('projectName', null);
if (projectName !== null) {
projectName = projectName.replace(/[\\"'`]/g, '');
const projectName = stripeConfig.get<string | null>('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] : [];
Expand Down
64 changes: 64 additions & 0 deletions test/suite/stripeTerminal.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 <T>(section: string): { key: string; defaultValue?: T; globalValue?: T; workspaceValue?: T; workspaceFolderValue?: T; defaultLanguageValue?: T; globalLanguageValue?: T; workspaceLanguageValue?: T; workspaceFolderLanguageValue?: T; languageIds?: string[]; } | undefined {

Check warning on line 54 in test/suite/stripeTerminal.test.ts

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

Unexpected separator (;)

Check warning on line 54 in test/suite/stripeTerminal.test.ts

View workflow job for this annotation

GitHub Actions / build (macos-latest)

Unexpected separator (;)

Check warning on line 54 in test/suite/stripeTerminal.test.ts

View workflow job for this annotation

GitHub Actions / build (windows-latest)

Unexpected separator (;)
throw new Error('Function not implemented.');
},
update: function (section: string, value: any, configurationTarget?: vscode.ConfigurationTarget | boolean | null, overrideInLanguage?: boolean): Thenable<void> {
throw new Error('Function not implemented.');
}
});

const stripeTerminal = new StripeTerminal(stripeClientStub);
await stripeTerminal.execute('listen', ['--forward-to', 'localhost']);

Expand All @@ -54,6 +73,8 @@ suite('stripeTerminal', function () {
'listen',
'--forward-to',
'localhost',
'--project-name',
'Valid_Project-Name',
],
{
shellQuoting: {
Expand All @@ -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 = <any>{
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 <T>(section: string): { key: string; defaultValue?: T; globalValue?: T; workspaceValue?: T; workspaceFolderValue?: T; defaultLanguageValue?: T; globalLanguageValue?: T; workspaceLanguageValue?: T; workspaceFolderLanguageValue?: T; languageIds?: string[]; } | undefined {

Check warning on line 110 in test/suite/stripeTerminal.test.ts

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

Unexpected separator (;)

Check warning on line 110 in test/suite/stripeTerminal.test.ts

View workflow job for this annotation

GitHub Actions / build (macos-latest)

Unexpected separator (;)

Check warning on line 110 in test/suite/stripeTerminal.test.ts

View workflow job for this annotation

GitHub Actions / build (windows-latest)

Unexpected separator (;)
throw new Error('Function not implemented.');
},
update: function (section: string, value: any, configurationTarget?: vscode.ConfigurationTarget | boolean | null, overrideInLanguage?: boolean): Thenable<void> {
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', () => {
Expand Down

0 comments on commit d5bef18

Please sign in to comment.