fix(entrypoint): no recursive chmod, graceful stop, fpm error_log owner, symlink-safe root paths, dotfile deny #23

Merged
jknapp merged 7 commits from fix/no-recursive-chmod-on-start into trunk 2026-10-21 00:01:30 +00:00
Showing only changes of commit 86a88c87db - Show all commits
+10 -7
View File
@@ -34,13 +34,14 @@ die() {
exit 1
}
# drop_symlink PATH : if PATH is a symlink, unlink it (as root: rm on the final
# component never touches the link target, and the customer cannot deny it) and
# log it. Fails closed: if it is still a symlink afterwards, refuse to start.
# drop_symlink PATH : if PATH is a symlink, unlink it AS THE CUSTOMER (rm on
# the final component never touches the link target, and if a parent dir is
# swapped for a symlink mid-way the customer can only delete what they already
# could) and log it. Fails closed: still a symlink afterwards -> refuse to start.
drop_symlink() {
if [ -L "$1" ]; then
echo "entrypoint: SECURITY: $1 was a symlink to '$(readlink "$1")' - removing" >&2
rm -f -- "$1"
as_user rm -f -- "$1"
[ -L "$1" ] && die "could not remove symlink $1"
fi
return 0
@@ -59,9 +60,11 @@ secure_home() {
# public_html may legitimately be a symlink (release-dir deploys); it is left
# alone and every root-side operation on it runs as the customer instead.
if [ -d "$h/logs" ]; then
# find without -L never follows symlinks; -delete unlinks the link itself.
# Errors are not fatal HERE: require_safe_logs re-checks and fails closed.
find "$h/logs" -xdev -type l \
# As the customer: find without -L never follows symlinks, -delete unlinks
# the link itself, and a raced parent swap can only reach what the customer
# could already delete. Errors are not fatal HERE: require_safe_logs
# re-checks immediately before the daemons start and fails closed.
as_user find "$h/logs" -xdev -type l \
-printf 'entrypoint: SECURITY: %p was a symlink to %l - removed\n' -delete >&2 || true
fi
}