From 7e2ee49d98a94b59e92c43d62e7e3322996ad18d Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 17 Feb 2026 04:58:24 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=9B=A1=EF=B8=8F=20Sentinel:=20[MEDIUM]=20?= =?UTF-8?q?Secure=20backup=20file=20permissions=20and=20fix=20argument=20i?= =?UTF-8?q?njection?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Enforce 0700 permissions on backup and log directories. - use umask 077 for zip creation (0600 permissions). - Use bash arrays for zip exclude arguments to fix space handling. Co-authored-by: kidchenko <5432753+kidchenko@users.noreply.github.com> --- .jules/sentinel.md | 14 ++++++++++++++ tools/backup-projects.sh | 41 +++++++++++++++++++++------------------- 2 files changed, 36 insertions(+), 19 deletions(-) create mode 100644 .jules/sentinel.md diff --git a/.jules/sentinel.md b/.jules/sentinel.md new file mode 100644 index 0000000..147bfa5 --- /dev/null +++ b/.jules/sentinel.md @@ -0,0 +1,14 @@ +## 2026-02-17 - Insecure Temporary Files & Shell Argument Injection +**Vulnerability:** +1. Backup script created directories and files in default umask (likely 755/644), exposing sensitive source code backups to other users. +2. Shell script passed exclude patterns as a space-separated string to `zip`, causing incorrect argument parsing if patterns contained spaces (argument injection/logic error). + +**Learning:** +- Always explicitly set directory permissions (`chmod 700`) for sensitive data directories. +- Use `umask 077` in a subshell when creating sensitive files to ensure they are private by default (0600). +- In Bash, always use arrays (`"${arr[@]}"`) for passing lists of arguments to commands to handle spaces correctly. String concatenation is dangerous. + +**Prevention:** +- Use `install -d -m 700` or `mkdir` + `chmod 700` for private directories. +- Review all shell scripts for unquoted variable expansions in command arguments. +- Prefer array handling over string manipulation for command arguments. diff --git a/tools/backup-projects.sh b/tools/backup-projects.sh index 1b7f6d2..a76b1b7 100755 --- a/tools/backup-projects.sh +++ b/tools/backup-projects.sh @@ -232,15 +232,6 @@ parse_args() { done } -# --- Build Exclude Arguments for Zip --- -build_exclude_args() { - local args=() - for pattern in "${EXCLUDE_PATTERNS[@]}"; do - args+=("-x" "*/${pattern}/*" "-x" "*/${pattern}") - done - echo "${args[@]}" -} - # --- Git Sync --- sync_git_repos() { say "Syncing git repositories..." @@ -350,11 +341,19 @@ cmd_backup() { # Setup directories if [[ "$DRY_RUN" != true ]]; then - mkdir -p "$BACKUP_TEMP_DIR" - mkdir -p "$LOG_DIR" + # Ensure directories exist with secure permissions (0700) + if [[ ! -d "$BACKUP_TEMP_DIR" ]]; then + mkdir -p "$BACKUP_TEMP_DIR" + chmod 700 "$BACKUP_TEMP_DIR" + fi + + if [[ ! -d "$LOG_DIR" ]]; then + mkdir -p "$LOG_DIR" + chmod 700 "$LOG_DIR" + fi else - debug "Would create: $BACKUP_TEMP_DIR" - debug "Would create: $LOG_DIR" + debug "Would create: $BACKUP_TEMP_DIR (0700)" + debug "Would create: $LOG_DIR (0700)" fi # Sync git repositories first @@ -406,17 +405,21 @@ cmd_backup() { done fi else - local exclude_args - exclude_args=$(build_exclude_args) + # Build exclude arguments for zip + local exclude_args=() + for pattern in "${EXCLUDE_PATTERNS[@]}"; do + exclude_args+=("-x" "*/${pattern}/*" "-x" "*/${pattern}") + done ( cd "$HOME" || exit 1 + # Set umask to 077 so created files are 0600 (owner read/write only) + umask 077 + if [[ "$VERBOSE" == true ]]; then - # shellcheck disable=SC2086 - zip -r "$archive_path" "${relative_paths[@]}" $exclude_args + zip -r "$archive_path" "${relative_paths[@]}" "${exclude_args[@]}" else - # shellcheck disable=SC2086 - zip -r -q "$archive_path" "${relative_paths[@]}" $exclude_args + zip -r -q "$archive_path" "${relative_paths[@]}" "${exclude_args[@]}" fi )