-
Notifications
You must be signed in to change notification settings - Fork 1
🛡️ Sentinel: [MEDIUM] Secure backup file permissions and fix argument injection #33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| ## 2026-02-17 - Insecure Temporary Files & Shell Argument Injection | ||
|
Check failure on line 1 in .jules/sentinel.md
|
||
| **Vulnerability:** | ||
| 1. Backup script created directories and files in default umask (likely 755/644), exposing sensitive source code backups to other users. | ||
|
Check failure on line 3 in .jules/sentinel.md
|
||
| 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). | ||
|
Check failure on line 4 in .jules/sentinel.md
|
||
|
|
||
| **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. | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -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 | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+344
to
+353
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Directory permissions are not enforced when the directory already exists, and Two concerns:
Consider always enforcing permissions (unconditionally), and using Proposed fix- # 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
+ # Ensure directories exist with secure permissions (0700)
+ (
+ umask 077
+ mkdir -p "$BACKUP_TEMP_DIR" "$LOG_DIR"
+ )
+ chmod 700 "$BACKUP_TEMP_DIR" "$LOG_DIR"The final 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||
| 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 | ||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix markdown lint failures flagged by the pipeline.
The
Lint Documentationcheck reports several failures on this file:MD041— First line should be a top-level heading (#, not##).MD022— Heading needs a blank line below it.MD032— Lists should be surrounded by blank lines (add a blank line before the numbered list).MD013— Lines exceed the 80-character limit.Proposed fix
📝 Committable suggestion
🧰 Tools
🪛 GitHub Check: Lint Documentation
[failure] 4-4: Line length
.jules/sentinel.md:4:81 MD013/line-length Line length [Expected: 80; Actual: 175] https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md013.md
[failure] 3-3: Lists should be surrounded by blank lines
.jules/sentinel.md:3 MD032/blanks-around-lists Lists should be surrounded by blank lines [Context: "1. Backup script created direc..."] https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md032.md
[failure] 3-3: Line length
.jules/sentinel.md:3:81 MD013/line-length Line length [Expected: 80; Actual: 136] https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md013.md
[failure] 1-1: First line in a file should be a top-level heading
.jules/sentinel.md:1 MD041/first-line-heading/first-line-h1 First line in a file should be a top-level heading [Context: "## 2026-02-17 - Insecure Tempo..."] https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md041.md
[failure] 1-1: Headings should be surrounded by blank lines
.jules/sentinel.md:1 MD022/blanks-around-headings Headings should be surrounded by blank lines [Expected: 1; Actual: 0; Below] [Context: "## 2026-02-17 - Insecure Temporary Files & Shell Argument Injection"] https://github.com/DavidAnson/markdownlint/blob/v0.34.0/doc/md022.md
🤖 Prompt for AI Agents