From c4b4f062b073207fbdf0b5fad4221bc5d95069d5 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 13 Feb 2026 04:37:23 +0000 Subject: [PATCH] Fix: Secure SSH key creation with umask 077 Prevent TOCTOU race condition where private keys were briefly world-readable during creation. Use subshell with `umask 077` for atomic permissions. - Wraps `mkdir` and file creation in `(umask 077; ...)` - Removes existing files before writing to ensure new inode creation - Adds Sentinel journal entry regarding secure file creation Co-authored-by: kidchenko <5432753+kidchenko@users.noreply.github.com> --- .jules/sentinel.md | 6 ++++++ tools/setup-ssh-keys.sh | 17 +++++++++++++---- 2 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 .jules/sentinel.md diff --git a/.jules/sentinel.md b/.jules/sentinel.md new file mode 100644 index 0000000..ed9335d --- /dev/null +++ b/.jules/sentinel.md @@ -0,0 +1,6 @@ +# Sentinel's Journal + +## 2025-02-13 - Secure File Creation in Shell Scripts +**Vulnerability:** SSH private keys were created with default umask (often 022, resulting in 644/world-readable) before being restricted with `chmod 600`. This created a race condition where the key was briefly readable by other users. +**Learning:** Shell redirection (`>`) and `mkdir` adhere to the process's `umask` at the time of execution. `chmod` after creation leaves a window of vulnerability. +**Prevention:** Use `(umask 077 && mkdir ...)` for directories and `(umask 077; command > file)` for files to ensure atomic secure permissions. Remove existing files before writing if sensitive to ensure new inode creation with correct permissions. diff --git a/tools/setup-ssh-keys.sh b/tools/setup-ssh-keys.sh index bde52fd..b89f5b6 100755 --- a/tools/setup-ssh-keys.sh +++ b/tools/setup-ssh-keys.sh @@ -148,12 +148,21 @@ cmd_restore() { say "Restoring SSH key from 1Password..." - # Create SSH directory - mkdir -p "$SSH_DIR" + # Create SSH directory with secure permissions + if [[ ! -d "$SSH_DIR" ]]; then + (umask 077 && mkdir -p "$SSH_DIR") + fi chmod 700 "$SSH_DIR" - # Read private key from 1Password and save locally - op read "op://$VAULT/$KEY_NAME/private_key" > "$PRIVATE_KEY_FILE" + # Remove existing files to ensure new files are created with correct permissions + rm -f "$PRIVATE_KEY_FILE" "$PUBLIC_KEY_FILE" + + # Read private key from 1Password and save locally with secure permissions + # usage of subshell with umask 077 ensures file is created with 600 permissions + ( + umask 077 + op read "op://$VAULT/$KEY_NAME/private_key" > "$PRIVATE_KEY_FILE" + ) chmod 600 "$PRIVATE_KEY_FILE" # Read public key from 1Password and save locally