Skip to content

Commit f5ee98e

Browse files
committed
Validate package names for discussion-trigger
1 parent 5b4f002 commit f5ee98e

3 files changed

Lines changed: 30 additions & 6 deletions

File tree

packages/mergebot/src/_tests/discussions.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,18 @@ describe(extractNPMReference, () => {
2525
test.concurrent.each(eventActions)("(%s, %s) is %s", async (title, result) => {
2626
expect(extractNPMReference({ title })).toEqual(result);
2727
});
28+
29+
const invalid = [
30+
"[Pkg: foo] inject", // space disallowed
31+
"[node @attacker] hi", // space + invalid char
32+
"[FOO] uppercase not allowed in npm names",
33+
"[../etc/passwd] traversal",
34+
"[]", // empty
35+
"[ leading-space]",
36+
"[trailing-space ]",
37+
"[has\nnewline]",
38+
];
39+
test.concurrent.each(invalid)("rejects invalid title %p", async (title) => {
40+
expect(extractNPMReference({ title })).toBeUndefined();
41+
});
2842
});
Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
export const canHandleRequest = (event: string, action: string) =>
22
event === "discussion" && (action === "created" || action === "edited");
33

4+
// npm package name grammar (post-2017): optional `@scope/`, lowercase, limited punctuation.
5+
// Used to validate the substring extracted from an untrusted discussion title before it is fed
6+
// into bot comments or used to create repository labels via GraphQL.
7+
const npmPackageNameRegex = /^(?:@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/;
8+
49
export function extractNPMReference(discussion: { title: string }) {
510
const title = discussion.title;
611
if (title.includes("[") && title.includes("]")) {
7-
const full = title.split("[")[1]!.split("]")[0];
8-
return full!.replace("@types/", "");
12+
const full = title.split("[")[1]!.split("]")[0]!;
13+
const name = full.replace("@types/", "");
14+
if (!npmPackageNameRegex.test(name)) return undefined;
15+
return name;
916
}
1017
return undefined;
1118
}

packages/mergebot/src/functions/discussions-trigger.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,16 +55,16 @@ const couldNotFindMessage = txt`
5555
`;
5656

5757
const errorsGettingOwners = (str: string) => txt`
58-
|Hi, we could not find [${str}] in DefinitelyTyped, is there possibly a typo?
58+
|Hi, we could not find [\`${str}\`] in DefinitelyTyped, is there possibly a typo?
5959
`;
6060

6161
const couldNotFindOwners = (str: string) => txt`
62-
|Hi, we had an issue getting the owners for [${str}] - first check if you have a typeo, otherwise please raise an issue on
62+
|Hi, we had an issue getting the owners for [\`${str}\`] - first check if you have a typeo, otherwise please raise an issue on
6363
|microsoft/DefinitelyTyped-tools if the module exists on DT but this bot could not find information for it.
6464
`;
6565

6666
const gotAReferenceMessage = (module: string, owners: string[]) => txt`
67-
|Thanks for the discussion about "${module}", some useful links for everyone:
67+
|Thanks for the discussion about "\`${module}\`", some useful links for everyone:
6868
|
6969
| - [npm](https://www.npmjs.com/package/${module})
7070
| - [DT](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/${module})
@@ -87,8 +87,11 @@ async function pingAuthorsAndSetUpDiscussion(discussion: Discussion) {
8787
} else {
8888
const message = gotAReferenceMessage(aboutNPMRef, owners);
8989
await updateOrCreateMainComment(discussion, message);
90+
// Only create a label once we've confirmed the package actually exists on DT --
91+
// otherwise an unprivileged user could make typescript-bot create arbitrarily-named
92+
// repository labels by editing the discussion title.
93+
await addLabel(discussion, "Pkg: " + aboutNPMRef, `Discussions related to ${aboutNPMRef}`);
9094
}
91-
await addLabel(discussion, "Pkg: " + aboutNPMRef, `Discussions related to ${aboutNPMRef}`);
9295
}
9396
return { status: 200, body: "OK" };
9497
}

0 commit comments

Comments
 (0)