Skip to content

Commit d6ef72b

Browse files
fix(auth): tighten stored credential permissions (#76)
1 parent 29700dc commit d6ef72b

2 files changed

Lines changed: 13 additions & 3 deletions

File tree

src/auth.mjs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@ const b64url = (buf) => Buffer.from(buf).toString("base64url");
2020
export function loadCreds() {
2121
try { return JSON.parse(fs.readFileSync(credsPath, "utf8")); } catch { return null; }
2222
}
23-
function saveCreds(creds) {
23+
export function saveCreds(creds) {
2424
fs.mkdirSync(CREDS_DIR, { recursive: true });
2525
fs.writeFileSync(credsPath, JSON.stringify(creds, null, 2), { mode: 0o600 });
26+
fs.chmodSync(credsPath, 0o600);
2627
}
2728

2829
function openBrowser(url) {

test/auth.test.mjs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import assert from "node:assert/strict";
2-
import { mkdirSync, mkdtempSync, writeFileSync } from "node:fs";
2+
import { chmodSync, mkdirSync, mkdtempSync, statSync, writeFileSync } from "node:fs";
33
import { tmpdir } from "node:os";
44
import { join } from "node:path";
55
import test from "node:test";
@@ -15,7 +15,8 @@ writeFileSync(
1515
process.env.HOME = home;
1616
process.env.USERPROFILE = home;
1717

18-
const { whoami } = await import("../src/auth.mjs");
18+
const { saveCreds, whoami } = await import("../src/auth.mjs");
19+
const posixMode = process.platform === "win32" ? { skip: "POSIX permission bits" } : {};
1920

2021
/** Run whoami against a canned app response and collect what it printed. */
2122
async function whoamiAgainst({ status, body }) {
@@ -55,3 +56,11 @@ test("whoami still calls out an expired session on 401", async () => {
5556
const out = await whoamiAgainst({ status: 401, body: { error: "unauthorized" } });
5657
assert.match(out, /session expired/);
5758
});
59+
60+
test("saving credentials tightens a world-readable existing file", posixMode, () => {
61+
chmodSync(join(home, ".moshcode", "credentials.json"), 0o644);
62+
63+
saveCreds({ api: "https://app.example.test", token: "tok_fresh", email: "me@example.test" });
64+
65+
assert.equal(statSync(join(home, ".moshcode", "credentials.json")).mode & 0o777, 0o600);
66+
});

0 commit comments

Comments
 (0)