fix(safe-paths): unlink planted symlinks as the customer, then fail closed
Root rm -f in drop_symlink could be redirected by a parent-directory swap to delete arbitrary files as root. drop_symlink and the logs/ symlink sweep now unlink AS THE CUSTOMER (can never delete anything the customer couldn't), and drop_symlink still refuses to start if the path is a symlink afterwards; the pre-daemon logs/ gate re-checks and fails closed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
02d93f4d1a
commit
86a88c87db
1 file changed
+10
-7
+10
-7
@@ -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
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user