(core) support a wildcard option for ALLOWED_WEBHOOK_DOMAINS

Summary:
Now that webhook payload delivery can be done using a proxy,
it may be desirable to no longer require a set of `ALLOWED_WEBHOOK_DOMAINS`.
This diff allows this variable to be set to `*`. With this setting,
any domain, and both `http` and `https` protocols will now be accepted.

Another possibility would be to default to unchecked
behavior if `ALLOWED_WEBHOOK_DOMAINS` is not set. But this would
introduce a new kind of vulnerability to unconfigured Grist
installations.

Test Plan: switched a test from naming a domain to using `*`

Reviewers: jarek

Reviewed By: jarek

Differential Revision: https://phab.getgrist.com/D3903
This commit is contained in:
Paul Fitzpatrick
2023-05-23 12:51:58 -04:00
parent 4cc19ff748
commit 3f3a0d3aa1
5 changed files with 31 additions and 2 deletions

View File

@@ -1325,6 +1325,22 @@ export class FlexServer implements GristServer {
}
}
public checkOptionCombinations() {
// Check for some bad combinations we should warn about.
const allowedWebhookDomains = appSettings.section('integrations').flag('allowedWebhookDomains').readString({
envVar: 'ALLOWED_WEBHOOK_DOMAINS',
});
const proxy = appSettings.section('integrations').flag('proxy').readString({
envVar: 'GRIST_HTTPS_PROXY',
});
// If all webhook targets are accepted, and no proxy is defined, issue
// a warning. This warning can be removed by explicitly setting the proxy
// to the empty string.
if (allowedWebhookDomains === '*' && proxy === undefined) {
log.warn("Setting an ALLOWED_WEBHOOK_DOMAINS wildcard without a GRIST_HTTPS_PROXY exposes your internal network");
}
}
public async start() {
if (this._check('start')) { return; }

View File

@@ -772,6 +772,17 @@ export function isUrlAllowed(urlString: string) {
return false;
}
// Support at most https and http.
if (url.protocol !== "https:" && url.protocol !== "http:") {
return false;
}
// Support a wildcard that allows all domains.
// Allow either https or http if it is set.
if (process.env.ALLOWED_WEBHOOK_DOMAINS === '*') {
return true;
}
// http (no s) is only allowed for localhost for testing.
// localhost still needs to be explicitly permitted, and it shouldn't be outside dev
if (url.protocol !== "https:" && url.hostname !== "localhost") {

View File

@@ -141,6 +141,7 @@ export async function main(port: number, serverTypes: ServerType[],
server.finalize();
server.checkOptionCombinations();
server.summary();
return server;
}