Skip to content

[Yun Tianming] src/config.ts: writeGlobal stores access/refresh tokens at umask default mode #239

Description

@Fermionic-Lyu

Location: src/config.ts:113-116 (writeGlobal), directory created at :114.

Kind: insecure file permissions / credential exposure.

Impact: ~/.insta/config.json holds accessToken, refreshToken, and the durable insta_ API key. writeFile is called with no mode and mkdir with no mode: 0o700, so under the common umask 022 the directory is 0755 and the file 0644. Any other local user or uid on a shared box or CI runner can read a live bearer and refresh token.

Evidence:

export async function writeGlobal(c: GlobalConfig): Promise<void> {
  await mkdir(GLOBAL_DIR, { recursive: true })
  await writeFile(GLOBAL_FILE, JSON.stringify(c, null, 2))
}

Every other credential file in the repo is explicitly 0o600 and says why: src/config.ts:319-320 (link-plane.json), src/agent.ts:44-47 (agent-session.json), src/util.ts:26-34 (writeFileAtomicSync defaults to 0o600 and re-chmods because "writeFileSync applies mode only when it CREATES the file"). No test asserts the mode of config.json.

Fix would touch: writeGlobal only: mkdir(..., { mode: 0o700 }), writeFile(..., { mode: 0o600 }) plus an unconditional chmod(GLOBAL_FILE, 0o600) so existing installs at 0644 are tightened on next write; or route through writeFileAtomicSync, which also makes the write atomic (a crash mid-write currently truncates the login).


Found by Yun Tianming: nightly sweep 2026-09-17-1000 at ecfe5168a32e. Report only; no code was changed for this finding.

🤖 Generated with Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions