T09 · Insecure Skill Coding Practices
- Location
backups.md:12- Finding
Predictable Temporary Database Backup File Enables Local File Disclosure or Overwrite
- Content
View full analysis
Vulnerability Details
File Location:
backups.md, lines 12-34
Vulnerability Type: Predictable and insecure temporary file handling
Risk Level: MediumVulnerable Code
bash #!/bin/bash # backup-db.sh TIMESTAMP=$(date +%Y%m%d_%H%M%S) BUCKET="s3://myapp-backups/postgres" # Dump pg_dump -Fc $DATABASE_URL > /tmp/backup_$TIMESTAMP.dump # Upload aws s3 cp /tmp/backup_$TIMESTAMP.dump $BUCKET/ # Cleanup local rm /tmp/backup_$TIMESTAMP.dump # Cleanup old backups (keep 30 days) aws s3 ls $BUCKET/ | while read -r line; do createDate=$(echo $line | awk '{print $1" "$2}') createDate=$(date -d "$createDate" +%s) olderThan=$(date -d "30 days ago" +%s) if [[ $createDate -lt $olderThan ]]; then fileName=$(echo $line | awk '{print $4}') aws s3 rm $BUCKET/$fileName fi doneTechnical Analysis
The example writes a potentially sensitive database dump into the shared
/tmpdirectory using a filename derived solely from the current timestamp. The filename is predictable, and shell redirection creates or truncates the path without verifying that it is a regular file owned by the backup process.On systems where relevant symbolic-link protections are absent, disabled, or ineffective for the execution context, another local user can create the expected path as a symbolic link before the backup runs. The shell may then follow that link when processing the redirection. This creates a time-of-check/time-of-use-style temporary-file vulnerability and can cause the database dump to be written to an unintended destination.
The script also does not set a restrictive
umask. Depending on the process environment, the temporary dump can therefore be created with permissions that permit other local users to read it. The file remains on disk until the upload completes, and abnormal termination before thermcommand can leave the plaintext backup behind.Several variable expansion ...[truncated 2250 chars]
- Remediation
View remediation
Remediation Suggestions
- Create the backup with
mktempinside a private directory rather than constructing a predictable path in shared/tmp. - Set
umask 077before creating any backup so only the backup account can read newly created files. - Install an
EXIT,INT, andTERMtrap to remove temporary data even if upload or processing fails. - Quote every variable expansion used as a command argument.
- Where operationally supported, stream the dump directly to encrypted object storage to avoid a plaintext intermediate file.
- Run the backup under a dedicated, least-privileged service account rather than root.
- Enable server-side encryption and restrictive bucket policies for uploaded backups.
- Use native object-storage lifecycle rules for retention instead of parsing
aws s3 lsoutput.
A hardened local-file pattern is:
bash #!/usr/bin/env bash set -euo pipefail umask 077 BUCKET="s3://myapp-backups/postgres" BACKUP_DIR=$(mktemp -d) BACKUP_FILE=$(mktemp "${BACKUP_DIR}/backup_XXXXXXXX.dump") cleanup() { rm -f -- "$BACKUP_FILE" rmdir -- "$BACKUP_DIR" 2>/dev/null || true } trap cleanup EXIT INT TERM pg_dump -Fc -- "$DATABASE_URL" > "$BACKUP_FILE" aws s3 cp "$BACKUP_FILE" "${BUCKET}/backup_$(date +%Y%m%d_%H%M%S).dump"Credentials should preferably be supplied through a protected PostgreSQL password file or another secret mechanism that does not expose sensitive connection details in process arguments. Backup restoration should be tested regularly, and retention should be enforced through an authenticated storage lifecycle policy.
- Create the backup with
