From 9097e89f7de42e4bb8416f78c0ccaed8024eb012 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Sun, 22 Feb 2026 04:44:52 +0000 Subject: [PATCH] fix(security): set umask 077 in backup-projects.sh to prevent world-readable backups - Adds `umask 077` to `tools/backup-projects.sh` to ensure generated zip files have 600 permissions. - Adds `tests/verify_backup_permissions.sh` as a regression test. - Adds security learning to `.jules/sentinel.md`. Co-authored-by: kidchenko <5432753+kidchenko@users.noreply.github.com> --- .jules/sentinel.md | 4 +++ tests/verify_backup_permissions.sh | 55 ++++++++++++++++++++++++++++++ tools/backup-projects.sh | 3 ++ 3 files changed, 62 insertions(+) create mode 100644 .jules/sentinel.md create mode 100755 tests/verify_backup_permissions.sh diff --git a/.jules/sentinel.md b/.jules/sentinel.md new file mode 100644 index 0000000..08aefb7 --- /dev/null +++ b/.jules/sentinel.md @@ -0,0 +1,4 @@ +## 2026-02-22 - Insecure Default Permissions on Backups +**Vulnerability:** The `tools/backup-projects.sh` script created zip archives with default permissions (often `644` or `664`), allowing other users on the system to read potentially sensitive project backups. +**Learning:** Shell scripts using tools like `zip` or `tar` do not automatically restrict permissions of the output file unless `umask` is set. +**Prevention:** Always set `umask 077` at the beginning of shell scripts that generate sensitive files or directories to ensure they are private by default. diff --git a/tests/verify_backup_permissions.sh b/tests/verify_backup_permissions.sh new file mode 100755 index 0000000..cac4f06 --- /dev/null +++ b/tests/verify_backup_permissions.sh @@ -0,0 +1,55 @@ +#!/bin/bash + +# Setup test environment +PROJECT_DIR="$HOME/kidchenko" +BACKUP_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/dotfiles/backups" +BACKUP_DIR="${BACKUP_DIR/#\~/$HOME}" # Expand ~ just in case + +# Create dummy project +mkdir -p "$PROJECT_DIR" +echo "secret content" > "$PROJECT_DIR/secret.txt" + +# Ensure cleanup +trap 'rm -rf "$PROJECT_DIR"' EXIT + +# Run backup script +# It reads default folders which includes ~/kidchenko +echo "Running backup script..." +# Using --verbose to see output, but suppressing standard output unless needed +if ! bash tools/backup-projects.sh backup --verbose > /tmp/backup_output.log 2>&1; then + echo "Backup failed. Output:" + cat /tmp/backup_output.log + exit 1 +fi + +# Find the latest backup +LATEST_BACKUP=$(ls -t "$BACKUP_DIR"/project-backup-*.zip 2>/dev/null | head -n1) + +if [[ -z "$LATEST_BACKUP" ]]; then + echo "Error: No backup file created in $BACKUP_DIR" + cat /tmp/backup_output.log + exit 1 +fi + +echo "Backup created: $LATEST_BACKUP" + +# Check permissions +if [[ "$OSTYPE" == "darwin"* ]]; then + PERMS=$(stat -f %Lp "$LATEST_BACKUP") +else + PERMS=$(stat -c %a "$LATEST_BACKUP") +fi + +echo "Permissions: $PERMS" + +# Cleanup backup file +rm -f "$LATEST_BACKUP" + +# We expect 600 (rw-------) +if [[ "$PERMS" != "600" ]]; then + echo "FAILURE: Permissions are too open ($PERMS). Expected 600." + exit 1 +else + echo "SUCCESS: Permissions are correct (600)." + exit 0 +fi diff --git a/tools/backup-projects.sh b/tools/backup-projects.sh index 1b7f6d2..9c71a4c 100755 --- a/tools/backup-projects.sh +++ b/tools/backup-projects.sh @@ -27,6 +27,9 @@ # Pipestatus set -o pipefail +# Security: Ensure all created files/directories are private (read/write only by owner) +umask 077 + # --- Configuration --- CONFIG_FILE="${XDG_CONFIG_HOME:-$HOME/.config}/dotfiles/config.yaml" LOG_DIR="${XDG_STATE_HOME:-$HOME/.local/state}/dotfiles"