From 412f2389f14a625074fc0ae5a1bda6f97a1c6d8f Mon Sep 17 00:00:00 2001 From: charliekerfoot Date: Mon, 27 Apr 2026 16:26:06 -0500 Subject: [PATCH] fix(google_oauth): close TOCTOU window when saving credentials --- agent/google_oauth.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/agent/google_oauth.py b/agent/google_oauth.py index d6b96da6e5..ede64251e2 100644 --- a/agent/google_oauth.py +++ b/agent/google_oauth.py @@ -489,16 +489,29 @@ def save_credentials(creds: GoogleCredentials) -> Path: """Atomically write creds to disk with 0o600 permissions.""" path = _credentials_path() path.parent.mkdir(parents=True, exist_ok=True) + # Tighten parent dir to 0o700 so siblings can't traverse to the creds file. + # On Windows this is a no-op (POSIX mode bits aren't enforced); ignore failures. + try: + os.chmod(path.parent, 0o700) + except OSError: + pass payload = json.dumps(creds.to_dict(), indent=2, sort_keys=True) + "\n" with _credentials_lock(): tmp_path = path.with_suffix(f".tmp.{os.getpid()}.{secrets.token_hex(4)}") try: - with open(tmp_path, "w", encoding="utf-8") as fh: + # Create with 0o600 atomically to close the TOCTOU window where the + # default umask (often 0o644) would briefly expose tokens to other + # local users between open() and chmod(). + fd = os.open( + str(tmp_path), + os.O_WRONLY | os.O_CREAT | os.O_EXCL, + stat.S_IRUSR | stat.S_IWUSR, + ) + with os.fdopen(fd, "w", encoding="utf-8") as fh: fh.write(payload) fh.flush() os.fsync(fh.fileno()) - os.chmod(tmp_path, stat.S_IRUSR | stat.S_IWUSR) atomic_replace(tmp_path, path) finally: try: