Skip to content

docker [postgres] create new scripts#209

Open
pneumojoseph wants to merge 1 commit into
masterfrom
docker/scripts/db_scripts
Open

docker [postgres] create new scripts#209
pneumojoseph wants to merge 1 commit into
masterfrom
docker/scripts/db_scripts

Conversation

@pneumojoseph
Copy link
Copy Markdown
Collaborator

@pneumojoseph pneumojoseph commented May 5, 2026

…backup.sh"


Note

Medium Risk
Adds interactive scripts that stop containers and drop/recreate the configured Postgres database during restore; misuse or misconfiguration could cause accidental data loss in local/dev environments.

Overview
Adds two new utility scripts for local Docker Postgres workflows.

scripts/postgres_terminal.sh opens an interactive psql session inside the pneumatic-postgres container using connection settings read from .env.

scripts/restore_backup.sh introduces an interactive restore flow: lists backups from postgres/backups, confirms overwrite, restarts containers, waits for Postgres readiness, drops/recreates the target database, restores the selected SQL file into the container, then restarts services based on a user-selected compose configuration.

Reviewed by Cursor Bugbot for commit 47a8eca. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add postgres terminal and backup restore scripts for Docker

  • postgres_terminal.sh reads PostgreSQL connection params from .env and opens an interactive psql session inside the pneumatic-postgres container.
  • restore_backup.sh lists available backups, prompts for selection, drops and recreates the target database, restores from the chosen backup via psql, then restarts project containers using a user-selected docker-compose configuration.
  • Risk: the restore script is destructive — it drops the existing database after a confirmation prompt, and stops all running project containers via docker compose down.
📊 Macroscope summarized 47a8eca. 2 files reviewed, 7 issues evaluated, 1 issue filtered, 5 comments posted

🗂️ Filtered Issues

scripts/restore_backup.sh — 3 comments posted, 5 evaluated, 1 filtered
  • line 183: On line 183, the variables $POSTGRES_PASSWORD, $POSTGRES_USER, $POSTGRES_HOST, $POSTGRES_DB, and $BACKUP_FILENAME are expanded by the outer shell into the sh -c string without any escaping. If any of these values contain shell metacharacters (spaces, quotes, semicolons, backticks, $, etc.), the inner sh -c command will misinterpret them, potentially causing command injection or command failure. Passwords are especially likely to contain special characters. The same issue affects lines 148, 164, and 173. [ Cross-file consolidated ]

@pneumojoseph pneumojoseph added the DevOps Infrastructure and installation changes label May 5, 2026
@pneumojoseph pneumojoseph self-assigned this May 5, 2026
# =============================================================================

print_info "Connecting to database \"$POSTGRES_DB\" as user \"$POSTGRES_USER\"..."
docker exec -it pneumatic-postgres sh -c "PGPASSWORD=$POSTGRES_PASSWORD psql -U $POSTGRES_USER $POSTGRES_DB"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 High scripts/postgres_terminal.sh:52

Line 52 interpolates $POSTGRES_PASSWORD, $POSTGRES_USER, and $POSTGRES_DB directly into a sh -c "..." command string. Because the outer quotes are double quotes, shell metacharacters in these values (e.g., $, backticks, ;, spaces) are interpreted by the inner shell rather than treated literally. For example, a password like p@ss$word causes $word to expand to empty string, resulting in PGPASSWORD=p@ss. A password like p;rm -rf / would execute rm -rf / inside the container. Even common special characters in database credentials will cause silent credential mangling or command injection. Consider passing the password via docker exec -e and dropping the sh -c wrapper so values are passed as literals.

-docker exec -it pneumatic-postgres sh -c "PGPASSWORD=$POSTGRES_PASSWORD psql -U $POSTGRES_USER $POSTGRES_DB"
+docker exec -e "PGPASSWORD=$POSTGRES_PASSWORD" -it pneumatic-postgres psql -U "$POSTGRES_USER" "$POSTGRES_DB"
Also found in 1 other location(s)

scripts/restore_backup.sh:183

On line 183, the variables $POSTGRES_PASSWORD, $POSTGRES_USER, $POSTGRES_HOST, $POSTGRES_DB, and $BACKUP_FILENAME are expanded by the outer shell into the sh -c string without any escaping. If any of these values contain shell metacharacters (spaces, quotes, semicolons, backticks, $, etc.), the inner sh -c command will misinterpret them, potentially causing command injection or command failure. Passwords are especially likely to contain special characters. The same issue affects lines 148, 164, and 173.

🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file scripts/postgres_terminal.sh around line 52:

Line 52 interpolates `$POSTGRES_PASSWORD`, `$POSTGRES_USER`, and `$POSTGRES_DB` directly into a `sh -c "..."` command string. Because the outer quotes are double quotes, shell metacharacters in these values (e.g., `$`, backticks, `;`, spaces) are interpreted by the inner shell rather than treated literally. For example, a password like `p@ss$word` causes `$word` to expand to empty string, resulting in `PGPASSWORD=p@ss`. A password like `p;rm -rf /` would execute `rm -rf /` inside the container. Even common special characters in database credentials will cause silent credential mangling or command injection. Consider passing the password via `docker exec -e` and dropping the `sh -c` wrapper so values are passed as literals.

Also found in 1 other location(s):
- scripts/restore_backup.sh:183 -- On line 183, the variables `$POSTGRES_PASSWORD`, `$POSTGRES_USER`, `$POSTGRES_HOST`, `$POSTGRES_DB`, and `$BACKUP_FILENAME` are expanded by the outer shell into the `sh -c` string without any escaping. If any of these values contain shell metacharacters (spaces, quotes, semicolons, backticks, `$`, etc.), the inner `sh -c` command will misinterpret them, potentially causing command injection or command failure. Passwords are especially likely to contain special characters. The same issue affects lines 148, 164, and 173.

Comment on lines +36 to +37
key=$(echo "$key" | xargs)
value=$(echo "$value" | xargs)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium scripts/postgres_terminal.sh:36

On lines 36-37, echo "$value" | xargs trims whitespace but also interprets quotes and backslashes in the .env value. A password like p@ss'w"ord or p@ss\word gets mangled or causes xargs: unmatched single quote, corrupting credentials and causing silent connection failures. Consider using sed 's/^[[:space:]]*//;s/[[:space:]]*$//' to trim without shell metacharacter interpretation.

-  key=$(echo "$key" | xargs)
-  value=$(echo "$value" | xargs)
+  key=$(echo "$key" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
+  value=$(echo "$value" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file scripts/postgres_terminal.sh around lines 36-37:

On lines 36-37, `echo "$value" | xargs` trims whitespace but also interprets quotes and backslashes in the `.env` value. A password like `p@ss'w"ord` or `p@ss\word` gets mangled or causes `xargs: unmatched single quote`, corrupting credentials and causing silent connection failures. Consider using `sed 's/^[[:space:]]*//;s/[[:space:]]*$//'` to trim without shell metacharacter interpretation.

Comment thread scripts/restore_backup.sh
Comment on lines +86 to +88
while IFS='=' read -r key value; do
key=$(echo "$key" | xargs)
value=$(echo "$value" | xargs)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Low scripts/restore_backup.sh:86

The .env parsing loop on lines 86-96 does not skip comment lines (starting with #) or blank lines. When the .env file contains comments like # Database config, the IFS='=' read assigns the entire line to key, and xargs processes it. While this won't match any case branch, comments containing special characters cause xargs to fail with errors like "xargs: unmatched single quote" or similar shell parsing failures, breaking the script.

-while IFS='=' read -r key value; do
+while IFS='=' read -r key value || [ -n "$key" ]; do
+  # Skip comment lines and blank lines
+  [[ "$key" =~ ^[[:space:]]*# ]] && continue
+  [[ -z "$key" ]] && continue
+
   key=$(echo "$key" | xargs)
   value=$(echo "$value" | xargs)
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file scripts/restore_backup.sh around lines 86-88:

The `.env` parsing loop on lines 86-96 does not skip comment lines (starting with `#`) or blank lines. When the `.env` file contains comments like `# Database config`, the `IFS='=' read` assigns the entire line to `key`, and `xargs` processes it. While this won't match any `case` branch, comments containing special characters cause `xargs` to fail with errors like "xargs: unmatched single quote" or similar shell parsing failures, breaking the script.

Comment thread scripts/restore_backup.sh
Comment on lines +226 to +242
case "$COMPOSE_FILE" in
1)
output=$(docker compose -f "$PROJECT_DIR/docker-compose.yml" up -d 2>&1)
;;
2)
output=$(TAG=latest docker compose -f "$PROJECT_DIR/docker-compose.yml" up -d 2>&1)
;;
3)
output=$(docker compose -f "$PROJECT_DIR/docker-compose.src.yml" up -d 2>&1)
;;
4)
output=$(docker compose -f "$PROJECT_DIR/frontend/docker-compose.yml" up -d 2>&1)
;;
5)
output=$(docker compose -f "$PROJECT_DIR/backend/docker-compose.yml" up -d 2>&1)
;;
esac
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Critical scripts/restore_backup.sh:226

The docker-compose configuration selector labels are swapped. Option 1 "Root (latest)" runs without setting TAG, so it deploys the stable default. Option 2 "Root (stable)" sets TAG=latest, so it deploys latest images. Users selecting "stable" get "latest" and vice versa.

case "$COMPOSE_FILE" in
   1)
-    output=$(docker compose -f "$PROJECT_DIR/docker-compose.yml" up -d 2>&1)
+    output=$(TAG=latest docker compose -f "$PROJECT_DIR/docker-compose.yml" up -d 2>&1)
     ;;
   2)
-    output=$(TAG=latest docker compose -f "$PROJECT_DIR/docker-compose.yml" up -d 2>&1)
+    output=$(docker compose -f "$PROJECT_DIR/docker-compose.yml" up -d 2>&1)
     ;;
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file scripts/restore_backup.sh around lines 226-242:

The docker-compose configuration selector labels are swapped. Option 1 "Root (latest)" runs without setting `TAG`, so it deploys the `stable` default. Option 2 "Root (stable)" sets `TAG=latest`, so it deploys `latest` images. Users selecting "stable" get "latest" and vice versa.

Comment thread scripts/restore_backup.sh
MAX_RETRIES=30
RETRY_COUNT=0
while true; do
docker exec -it pneumatic-postgres sh -c "pg_isready -U $POSTGRES_USER -h $POSTGRES_HOST" > /dev/null 2>&1
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 High scripts/restore_backup.sh:148

Lines 148, 164, 173, and 183 use docker exec -it with TTY allocation inside $(...) command substitutions where stdout is captured, not a terminal. On many Docker versions, -t without a real TTY produces "the input device is not a TTY" and causes the command to fail or inject \r carriage returns into $output, breaking the $? check or corrupting error messages. Remove -t from these docker exec calls.

-  docker exec -it pneumatic-postgres sh -c "pg_isready -U $POSTGRES_USER -h $POSTGRES_HOST" > /dev/null 2>&1
+  docker exec -i pneumatic-postgres sh -c "pg_isready -U $POSTGRES_USER -h $POSTGRES_HOST" > /dev/null 2>&1
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file scripts/restore_backup.sh around line 148:

Lines 148, 164, 173, and 183 use `docker exec -it` with TTY allocation inside `$(...)` command substitutions where stdout is captured, not a terminal. On many Docker versions, `-t` without a real TTY produces "the input device is not a TTY" and causes the command to fail or inject `\r` carriage returns into `$output`, breaking the `$?` check or corrupting error messages. Remove `-t` from these `docker exec` calls.

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 47a8eca. Configure here.

Comment thread scripts/restore_backup.sh
print_info "Select a docker-compose configuration to start containers:"
echo ""
echo " 1. Root (latest)"
echo " 2. Root (stable)"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Swapped labels for "latest" and "stable" compose options

High Severity

The menu labels "Root (latest)" and "Root (stable)" are swapped relative to their actual behavior. Option 1 ("latest") runs docker-compose.yml without setting TAG, which defaults to stable via ${TAG:-stable}. Option 2 ("stable") explicitly sets TAG=latest. A user choosing "stable" will get latest images, and vice versa — risking unintended deployments after a database restore.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 47a8eca. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

DevOps Infrastructure and installation changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant