Secure Temporary Files, Permissions, and Cleanup
Temporary files sit directly on a filesystem trust boundary. Secure automation must create them atomically, protect them while they exist, clean them up without hiding errors, and never assume cleanup is guaranteed.
Learning objectives
By the end of this lesson
- Avoid predictable temporary-file races.
- Use private temporary directories.
- Control umask, modes, and ownership.
- Preserve status through cleanup.
- Stage important files safely before promotion.
1. Predictable temporary filenames create race conditions
# Unsafe:
# tmp=/tmp/myapp.$$
# : > "$tmp"
# Safe:
tmp=$(mktemp) || exit 1mktemp creates a unique file atomically enough for the intended temporary-file use case, avoiding the check-then-create race of hand-built names.
2. Prefer private temporary directories for multi-file work
umask 077
tmpdir=$(mktemp -d) || exit 1
cleanup() {
local status=$?
rm -rf -- "$tmpdir"
exit "$status"
}
trap cleanup EXITA private workspace lets multiple scratch files share one protected directory and one cleanup boundary.
3. umask defines default permission removal
old_umask=$(umask)
umask 077
tmp=$(mktemp) || exit 1
umask "$old_umask"077 removes group and other permissions from newly created files and directories.
4. Set final permissions deliberately
install -m 0644 -- generated.conf /etc/myapp/generated.confTemporary privacy and final deployment permissions solve different problems.
5. Symlink races matter around privileged writes
When a privileged script writes to attacker-controlled directories or predictable paths, a symlink can redirect the write. Avoid untrusted directories for privileged temporary state and prefer atomic creation primitives.
6. Ownership is part of the security contract
install \
-o root \
-g myapp \
-m 0640 \
generated.conf \
/etc/myapp/generated.confA file with the right contents but wrong owner or group can be unusable or overly exposed.
7. Cleanup should preserve the original status
cleanup() {
local status=$?
rm -rf -- "${tmpdir:-}"
exit "$status"
}
trap cleanup EXIT8. Cleanup is best effort, not guaranteed
SIGKILL, power loss, kernel crashes, or abrupt runtime termination can bypass traps. Sensitive temporary state should therefore be protected even while it exists, not merely deleted later.
9. Stage and promote important files atomically
target=/etc/myapp/config
dir=$(dirname -- "$target")
tmp=$(mktemp "$dir/.config.XXXXXX") || exit 1
chmod 0640 -- "$tmp"
render_config > "$tmp"
validate_config "$tmp"
mv -- "$tmp" "$target"Creating the temporary file in the destination directory improves the chance that final rename stays on the same filesystem.
10. Directory permissions control traversal too
For directories, execute permission means traversal. A secret file inside a world-traversable directory may still be protected by its own mode, but directory modes affect discoverability and access patterns.
11. Hands-on lab: private temporary workspace
mkdir -p "$HOME/devops-academy/bash/chapter18/lesson03"
cd "$HOME/devops-academy/bash/chapter18/lesson03"
cat > secure-temp.sh <<'EOF'
#!/usr/bin/env bash
set -u
old_umask=$(umask)
umask 077
tmpdir=$(mktemp -d) || exit 1
cleanup() {
local status=$?
rm -rf -- "$tmpdir"
umask "$old_umask"
exit "$status"
}
trap cleanup EXIT
secret_file="$tmpdir/token"
printf '%s\n' 'demo-secret' > "$secret_file"
printf 'tmpdir=%s\n' "$tmpdir"
printf 'dir_mode=%s\n' "$(stat -c '%a' "$tmpdir" 2>/dev/null || printf platform-specific)"
printf 'file_created=yes\n'
EOF
chmod u+x secure-temp.sh
bash secure-temp.shVerification checklist
12. Knowledge check
Question 1. Why is /tmp/file.$$ weaker than mktemp?
Question 2. What does umask 077 do?
Question 3. Why place a staged final file in the destination directory?
Question 4. Is cleanup guaranteed to run?
13. Summary
Secure temporary-state handling starts with atomic creation, private directories, restrictive umask, deliberate ownership/modes, status-preserving cleanup, and same-directory staging for final promotion. Protect temporary data even if cleanup never runs.
14. Further reading
- GNU Coreutils documentation — mktemp, install, chmod, chown.
- POSIX file permission concepts.
- Linux filesystem and symlink security documentation.
- OWASP secure file-handling guidance.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this address.