diff --git a/.jules/sentinel.md b/.jules/sentinel.md new file mode 100644 index 0000000..19eb735 --- /dev/null +++ b/.jules/sentinel.md @@ -0,0 +1,6 @@ +# Sentinel's Journal + +## 2026-02-19 - Insecure Backup Permissions +**Vulnerability:** Backup archives containing sensitive project data were created with default `umask` (often 022), making them readable by other users on the system (`-rw-rw-r--`). +**Learning:** Even in single-user systems, assuming default permissions are secure is risky. Tools creating sensitive artifacts must explicitly enforce restrictive permissions. +**Prevention:** Added `umask 077` to `tools/backup-projects.sh` and explicitly `chmod 700` on backup directories to ensure least privilege. diff --git a/tests/verify_backup_permissions.sh b/tests/verify_backup_permissions.sh new file mode 100755 index 0000000..5cbf019 --- /dev/null +++ b/tests/verify_backup_permissions.sh @@ -0,0 +1,99 @@ +#!/bin/bash +set -e + +# Setup test environment +# Use mktemp directory +TEST_DIR=$(mktemp -d 2>/dev/null || mktemp -d -t 'test_backup') +BACKUP_DIR="$TEST_DIR/backups" +SOURCE_DIR="$TEST_DIR/source" +CONFIG_FILE="$TEST_DIR/config.yaml" + +mkdir -p "$SOURCE_DIR" +echo "secret" > "$SOURCE_DIR/secret.txt" + +# Create config file +cat < "$CONFIG_FILE" +backup: + folders: + - "$SOURCE_DIR" + local: + base_dir: "$BACKUP_DIR" + remote: + enabled: false + logging: + enabled: false +EOF + +# Determine repo root +REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +BACKUP_SCRIPT="$REPO_ROOT/tools/backup-projects.sh" + +echo "Running backup script: $BACKUP_SCRIPT" +# Run the backup command +# We ignore output to reduce noise, but capture errors if needed +bash "$BACKUP_SCRIPT" --config "$CONFIG_FILE" backup > "$TEST_DIR/backup.log" 2>&1 || { + echo "Backup script failed. Log:" + cat "$TEST_DIR/backup.log" + rm -rf "$TEST_DIR" + exit 1 +} + +# Check permissions +BACKUP_ARCHIVE=$(find "$BACKUP_DIR" -name "*.zip" | head -n 1) + +if [[ ! -f "$BACKUP_ARCHIVE" ]]; then + echo "Backup failed: No archive created" + rm -rf "$TEST_DIR" + exit 1 +fi + +# Get permissions (Linux stat) +if stat --version 2>/dev/null | grep -q "GNU"; then + # GNU stat + PERMS=$(stat -c "%a" "$BACKUP_ARCHIVE") + DIR_PERMS=$(stat -c "%a" "$BACKUP_DIR") +elif stat --version 2>/dev/null; then + # Fallback for other stats that might support --version but not be GNU (unlikely) + PERMS=$(stat -c "%a" "$BACKUP_ARCHIVE") + DIR_PERMS=$(stat -c "%a" "$BACKUP_DIR") +else + # BSD stat (macOS) - stat --version usually fails on BSD stat + # Try BSD syntax + if stat -f "%Lp" "$BACKUP_ARCHIVE" >/dev/null 2>&1; then + PERMS=$(stat -f "%Lp" "$BACKUP_ARCHIVE") + DIR_PERMS=$(stat -f "%Lp" "$BACKUP_DIR") + else + # Fallback to GNU syntax if --version check failed but it is GNU + PERMS=$(stat -c "%a" "$BACKUP_ARCHIVE") + DIR_PERMS=$(stat -c "%a" "$BACKUP_DIR") + fi +fi + +echo "Backup Archive Permissions: $PERMS" +echo "Backup Directory Permissions: $DIR_PERMS" + +FAILED=0 + +# Check archive permissions (should be 600 or 400) +if [[ "$PERMS" != "600" && "$PERMS" != "400" ]]; then + echo "FAIL: Insecure archive permissions ($PERMS). Expected 600 or 400." + FAILED=1 +else + echo "PASS: Archive permissions are secure." +fi + +# Check directory permissions (should be 700) +if [[ "$DIR_PERMS" != "700" ]]; then + echo "FAIL: Insecure directory permissions ($DIR_PERMS). Expected 700." + FAILED=1 +else + echo "PASS: Directory permissions are secure." +fi + +rm -rf "$TEST_DIR" + +if [[ $FAILED -eq 1 ]]; then + exit 1 +fi + +exit 0 diff --git a/tools/backup-projects.sh b/tools/backup-projects.sh index 1b7f6d2..00e2205 100755 --- a/tools/backup-projects.sh +++ b/tools/backup-projects.sh @@ -26,6 +26,7 @@ # Pipestatus set -o pipefail +umask 077 # Secure permissions for backups # --- Configuration --- CONFIG_FILE="${XDG_CONFIG_HOME:-$HOME/.config}/dotfiles/config.yaml" @@ -351,7 +352,9 @@ cmd_backup() { # Setup directories if [[ "$DRY_RUN" != true ]]; then mkdir -p "$BACKUP_TEMP_DIR" + chmod 700 "$BACKUP_TEMP_DIR" mkdir -p "$LOG_DIR" + chmod 700 "$LOG_DIR" else debug "Would create: $BACKUP_TEMP_DIR" debug "Would create: $LOG_DIR"