Skip to content

Commit 9e6de75

Browse files
committed
Escape user input (via query params) properly
1 parent 2f0525c commit 9e6de75

File tree

6 files changed

+34
-23
lines changed

6 files changed

+34
-23
lines changed

.eslintrc.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@
177177
"lines-around-comment": "off",
178178
"lines-around-directive": "off",
179179
"max-depth": "off",
180-
"max-len": ["error", 100, { "ignoreUrls": true }],
180+
"max-len": ["error", 100, { "ignoreUrls": true, "ignoreTemplateLiterals": true }],
181181
"max-lines": "off",
182182
"max-nested-callbacks": "off",
183183
"max-params": "off",

__tests__/__snapshots__/get-user-status.js.snap

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,17 @@ Object {
8888
}
8989
`;
9090

91+
exports[`Individuals exist, but the user is not one of them; it is an XSS attempt 1`] = `
92+
Object {
93+
"context": "Participation",
94+
"description": "@<script>alert(1);</script> has not signed up to participate",
95+
"isNothing": true,
96+
"longDescription": "@&lt;script&gt;alert(1);&lt;/script&gt; does not appear to have signed the agreement, or be associated with an entity that has done so. Please sign it, or forward it to an authorized representative!",
97+
"state": "pending",
98+
"target_url": "https://participate.whatwg.org/agreement-status?user=<script>alert(1);</script>&repo=console",
99+
}
100+
`;
101+
91102
exports[`Multiple entities, all not in this workstream 1`] = `
92103
Object {
93104
"context": "Participation",

__tests__/get-user-status.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,3 +203,11 @@ test("Individuals exist, but the user is not one of them", async () => {
203203
]);
204204
expect(await getUserStatus("johndoetw", "console")).toMatchSnapshot();
205205
});
206+
207+
test("Individuals exist, but the user is not one of them; it is an XSS attempt", async () => {
208+
mockData.set("individual-public", [
209+
individualData(["console"], true, { id: "janedoetw" }),
210+
individualData(["console"], true, { id: "bobbosstw" })
211+
]);
212+
expect(await getUserStatus("<script>alert(1);</script>", "console")).toMatchSnapshot();
213+
});

lib/get-user-status.js

Lines changed: 8 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const listify = require("listify");
44
const config = require("../config.json");
55
const gitHubAPI = require("./helpers/github.js").api;
66
const jsonGitHubDatabase = require("./helpers/json-github-database.js");
7+
const html = require("escape-goat").escapeTag;
78

89
const statusURLBase = (new URL(config.statusPath, config.serverURL)).href;
910

@@ -60,8 +61,7 @@ function statusIndividual(submitterGitHubID, repoName) {
6061
state: "success",
6162
isNothing: false,
6263
description: `@${submitterGitHubID} has signed up to participate as an individual`,
63-
longDescription: `@${submitterGitHubID} has signed up to participate as an individual. All ` +
64-
`is well; contribute at will!`,
64+
longDescription: html`@${submitterGitHubID} has signed up to participate as an individual. All is well; contribute at will!`,
6565
target_url: `${statusURLBase}?user=${submitterGitHubID}&repo=${repoName}`,
6666
context: "Participation"
6767
};
@@ -75,10 +75,7 @@ function statusIndividualNoWorkstreams(submitterGitHubID, repoName) {
7575
state: "pending",
7676
isNothing: false,
7777
description: `@${submitterGitHubID} participates as an individual, but not in this workstream`,
78-
longDescription: `@${submitterGitHubID} has signed up to participate as an individual, but ` +
79-
`has not chosen to participate in the ${workstreamName} workstream. To ` +
80-
`amend your agreement, submit a pull request to <a href="https://github.com/` +
81-
`${repo}">${repo}</a>.`,
78+
longDescription: html`@${submitterGitHubID} has signed up to participate as an individual, but has not chosen to participate in the ${workstreamName} workstream. To amend your agreement, submit a pull request to <a href="https://github.com/${repo}">${repo}</a>.`,
8279
target_url: `${statusURLBase}?user=${submitterGitHubID}&repo=${repoName}`,
8380
context: "Participation"
8481
};
@@ -89,8 +86,7 @@ function statusIndividualUnverified(submitterGitHubID, repoName) {
8986
state: "pending",
9087
isNothing: false,
9188
description: `@${submitterGitHubID} is not yet verified`,
92-
longDescription: `@${submitterGitHubID} has signed up to participate as an individual, but ` +
93-
`has not yet been verified. Hold tight while we sort this out on our end!`,
89+
longDescription: html`@${submitterGitHubID} has signed up to participate as an individual, but has not yet been verified. Hold tight while we sort this out on our end!`,
9490
target_url: `${statusURLBase}?user=${submitterGitHubID}&repo=${repoName}`,
9591
context: "Participation"
9692
};
@@ -103,10 +99,7 @@ function statusEntity(submitterGitHubID, repoName, entity) {
10399
state: "success",
104100
isNothing: false,
105101
description: `${submitterGitHubID} participates on behalf of ${entity.info.name}`,
106-
longDescription: `@${submitterGitHubID} is part of the ${entity.info.gitHubOrganization} ` +
107-
`GitHub organization, associated with ${entity.info.name}, which has signed ` +
108-
`the agreement and participates in the ${workstreamName} workstream. All is ` +
109-
`well; contribute at will!`,
102+
longDescription: html`@${submitterGitHubID} is part of the ${entity.info.gitHubOrganization} GitHub organization, associated with ${entity.info.name}, which has signed the agreement and participates in the ${workstreamName} workstream. All is well; contribute at will!`,
110103
target_url: `${statusURLBase}?user=${submitterGitHubID}&repo=${repoName}`,
111104
context: "Participation"
112105
};
@@ -119,9 +112,7 @@ function statusEntitiesUnverified(submitterGitHubID, repoName, entities) {
119112
state: "pending",
120113
isNothing: false,
121114
description: `@${submitterGitHubID} participates on behalf of an unverified entity`,
122-
longDescription: `@${submitterGitHubID} is part of the ${orgs} GitHub ${word}, but ` +
123-
`${pronoun} ${haveVerb} not yet been verified. Hold tight while we sort ` +
124-
`this out on our end!`,
115+
longDescription: html`@${submitterGitHubID} is part of the ${orgs} GitHub ${word}, but ${pronoun} ${haveVerb} not yet been verified. Hold tight while we sort this out on our end!`,
125116
target_url: `${statusURLBase}?user=${submitterGitHubID}&repo=${repoName}`,
126117
context: "Participation"
127118
};
@@ -135,10 +126,7 @@ function statusEntityNoWorkstreams(submitterGitHubID, repoName, entities) {
135126
state: "pending",
136127
isNothing: false,
137128
description: `@${submitterGitHubID} participates on behalf of a non-workstream entity`,
138-
longDescription: `@${submitterGitHubID} is part of the ${orgs} GitHub ${word}, but ` +
139-
`${pronoun} ${doVerb} not participate in the ${workstreamName} workstream. ` +
140-
`Please have the contact for ${pronoun2} ${word} update their participation ` +
141-
`agreement.`,
129+
longDescription: html`@${submitterGitHubID} is part of the ${orgs} GitHub ${word}, but ${pronoun} ${doVerb} not participate in the ${workstreamName} workstream. Please have the contact for ${pronoun2} ${word} update their participation agreement.`,
142130
target_url: `${statusURLBase}?user=${submitterGitHubID}&repo=${repoName}`,
143131
context: "Participation"
144132
};
@@ -149,9 +137,7 @@ function statusNothing(submitterGitHubID, repoName) {
149137
state: "pending",
150138
isNothing: true,
151139
description: `@${submitterGitHubID} has not signed up to participate`,
152-
longDescription: `@${submitterGitHubID} does not appear to have signed the agreement, or be ` +
153-
`associated with an entity that has done so. Please sign it, or forward it ` +
154-
`to an authorized representative!`,
140+
longDescription: html`@${submitterGitHubID} does not appear to have signed the agreement, or be associated with an entity that has done so. Please sign it, or forward it to an authorized representative!`,
155141
target_url: `${statusURLBase}?user=${submitterGitHubID}&repo=${repoName}`,
156142
context: "Participation"
157143
};

package-lock.json

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
},
1414
"dependencies": {
1515
"@octokit/rest": "^15.9.1",
16+
"escape-goat": "^1.3.0",
1617
"github-username-regex": "^1.0.0",
1718
"handlebars": "^4.0.10",
1819
"http-errors": "^1.6.3",

0 commit comments

Comments
 (0)