From dc3a387120b4d724d61489ce54dce84560e1d72d Mon Sep 17 00:00:00 2001 From: Reto Brunner Date: Tue, 23 Nov 2021 17:53:00 +0100 Subject: [PATCH] vapid: keep the file secret Contains a secret key, so we probably should keep it, well, secret. Warn if the file is world readable. --- src/plugins/webpush.js | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/plugins/webpush.js b/src/plugins/webpush.js index cf34c10a..09cfb81d 100644 --- a/src/plugins/webpush.js +++ b/src/plugins/webpush.js @@ -11,7 +11,28 @@ class WebPush { constructor() { const vapidPath = path.join(Helper.getHomePath(), "vapid.json"); - if (fs.existsSync(vapidPath)) { + let vapidStat = undefined; + + try { + vapidStat = fs.statSync(vapidPath); + } catch { + // ignored on purpose, node v14.17.0 will give us {throwIfNoEntry: false} + } + + if (vapidStat) { + const isWorldReadable = (vapidStat.mode & 0o004) !== 0; + + if (isWorldReadable) { + log.warn( + vapidPath, + "is world readable. The file contains secrets. Please fix the permissions" + ); + + if (require("os").platform() !== "win32") { + log.warn(`run \`chmod o= ${vapidPath}\` to correct it`); + } + } + const data = fs.readFileSync(vapidPath, "utf-8"); const parsedData = JSON.parse(data); @@ -29,7 +50,9 @@ class WebPush { if (!this.vapidKeys) { this.vapidKeys = WebPushAPI.generateVAPIDKeys(); - fs.writeFileSync(vapidPath, JSON.stringify(this.vapidKeys, null, "\t")); + fs.writeFileSync(vapidPath, JSON.stringify(this.vapidKeys, null, "\t"), { + mode: 0o600, + }); log.info("New VAPID key pair has been generated for use with push subscription."); }