From 88e1f3f25ac6003a7cf65b3319d70a349e7f460a Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Wed, 4 Feb 2026 04:37:52 +0000 Subject: [PATCH] Fix TOCTOU race condition in SSH key setup Wrapping the private key file creation in a subshell with `umask 077` ensures the file is created with restricted permissions (0600) atomically, preventing a window where it might be world-readable. - tools/setup-ssh-keys.sh: Use umask 077 for private key creation - .jules/sentinel.md: Record security learning Co-authored-by: kidchenko <5432753+kidchenko@users.noreply.github.com> --- .jules/sentinel.md | 4 ++++ tools/setup-ssh-keys.sh | 8 +++++--- 2 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 .jules/sentinel.md diff --git a/.jules/sentinel.md b/.jules/sentinel.md new file mode 100644 index 0000000..17acccb --- /dev/null +++ b/.jules/sentinel.md @@ -0,0 +1,4 @@ +## 2024-10-24 - Shell Script Race Conditions +**Vulnerability:** Found a Time-of-Check Time-of-Use (TOCTOU) race condition in `tools/setup-ssh-keys.sh` where a private key was written to disk with default permissions before being restricted with `chmod`. +**Learning:** Shell scripts often default to permissive `umask` (e.g., 022), making files world-readable for a brief window during creation. +**Prevention:** Always use `umask 077` in a subshell before writing sensitive files to ensure they are created with restricted permissions (0600) atomically. diff --git a/tools/setup-ssh-keys.sh b/tools/setup-ssh-keys.sh index bde52fd..ae23ed6 100755 --- a/tools/setup-ssh-keys.sh +++ b/tools/setup-ssh-keys.sh @@ -152,9 +152,11 @@ cmd_restore() { mkdir -p "$SSH_DIR" chmod 700 "$SSH_DIR" - # Read private key from 1Password and save locally - op read "op://$VAULT/$KEY_NAME/private_key" > "$PRIVATE_KEY_FILE" - chmod 600 "$PRIVATE_KEY_FILE" + # Read private key from 1Password and save locally (with secure permissions) + ( + umask 077 + op read "op://$VAULT/$KEY_NAME/private_key" > "$PRIVATE_KEY_FILE" + ) # Read public key from 1Password and save locally op read "op://$VAULT/$KEY_NAME/public_key" > "$PUBLIC_KEY_FILE"