From b2e56662c0d4cf4393fff58f181b8c3167745155 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 22 Oct 2025 20:25:42 +0200 Subject: [PATCH 1/3] Loose requirements for local file access for gravity Signed-off-by: yubiuser --- gravity.sh | 53 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/gravity.sh b/gravity.sh index 5720ca41..1e394811 100755 --- a/gravity.sh +++ b/gravity.sh @@ -612,7 +612,7 @@ compareLists() { gravity_DownloadBlocklistFromUrl() { local url="${1}" adlistID="${2}" saveLocation="${3}" compression="${4}" gravity_type="${5}" domain="${6}" local listCurlBuffer str httpCode success="" ip customUpstreamResolver="" - local file_path permissions ip_addr port blocked=false download=true + local file_path ip_addr port blocked=false download=true # modifiedOptions is an array to store all the options used to check if the adlist has been changed upstream local modifiedOptions=() @@ -721,29 +721,40 @@ gravity_DownloadBlocklistFromUrl() { fi fi - # If we are going to "download" a local file, we first check if the target - # file has a+r permission. We explicitly check for all+read because we want - # to make sure that the file is readable by everyone and not just the user - # running the script. - if [[ $url == "file://"* ]]; then + # If we "download" a local file (file://), verify read access before using it. + # When running as root (e.g., via pihole -g), check that the 'pihole' user can read the file + # to match the effective runtime user of FTL; otherwise, check the current user's read access + # (e.g., in Docker or when invoked by a non-root user). The target must + # resolve to a regular file and be readable by the evaluated user. + if [[ "${url}" == "file://"* ]]; then # Get the file path - file_path=$(echo "$url" | cut -d'/' -f3-) + file_path=$(echo "${url}" | cut -d'/' -f3-) # Check if the file exists and is a regular file (i.e. not a socket, fifo, tty, block). Might still be a symlink. - if [[ ! -f $file_path ]]; then - # Output that the file does not exist - echo -e "${OVER} ${CROSS} ${file_path} does not exist" - download=false - else - # Check if the file or a file referenced by the symlink has a+r permissions - permissions=$(stat -L -c "%a" "$file_path") - if [[ $permissions == *4 || $permissions == *5 || $permissions == *6 || $permissions == *7 ]]; then - # Output that we are using the local file - echo -e "${OVER} ${INFO} Using local file ${file_path}" - else - # Output that the file does not have the correct permissions - echo -e "${OVER} ${CROSS} Cannot read file (file needs to have a+r permission)" + if [[ ! -f ${file_path} ]]; then + # Output that the file does not exist + echo -e "${OVER} ${CROSS} ${file_path} does not exist" download=false - fi + else + if [ "$(id -un)" == "root" ]; then + # If we are root, we need to check if the pihole user has read permission + # otherwise, we might read files that the pihole user should not be able to read + if sudo -u pihole test -r "${file_path}"; then + echo -e "${OVER} ${INFO} Using local file ${file_path}" + else + echo -e "${OVER} ${CROSS} Cannot read file (user 'pihole' lacks read permission)" + download=false + fi + else + # If we are not root, we just check if the current user has read permission + if [[ -r "${file_path}" ]]; then + # Output that we are using the local file + echo -e "${OVER} ${INFO} Using local file ${file_path}" + else + # Output that the file is not readable by the current user + echo -e "${OVER} ${CROSS} Cannot read file (current user '$(id -un)' lacks read permission)" + download=false + fi + fi fi fi From 11344c39f5bbc960bb343f7e95a45d0d0090c7a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Thu, 23 Oct 2025 22:09:55 +0200 Subject: [PATCH 2/3] Prevent URLs like file:/./ to circumvent permission check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian König --- gravity.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gravity.sh b/gravity.sh index 1e394811..8f1005a0 100755 --- a/gravity.sh +++ b/gravity.sh @@ -726,7 +726,7 @@ gravity_DownloadBlocklistFromUrl() { # to match the effective runtime user of FTL; otherwise, check the current user's read access # (e.g., in Docker or when invoked by a non-root user). The target must # resolve to a regular file and be readable by the evaluated user. - if [[ "${url}" == "file://"* ]]; then + if [[ "${url}" == "file:/"* ]]; then # Get the file path file_path=$(echo "${url}" | cut -d'/' -f3-) # Check if the file exists and is a regular file (i.e. not a socket, fifo, tty, block). Might still be a symlink. From 527895a377b60877d21b9d3ef3d1a4e3738e3c82 Mon Sep 17 00:00:00 2001 From: yubiuser Date: Fri, 24 Oct 2025 21:07:12 +0200 Subject: [PATCH 3/3] Fix indentation Co-authored-by: RD WebDesign Signed-off-by: yubiuser --- gravity.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gravity.sh b/gravity.sh index 8f1005a0..28fa5ead 100755 --- a/gravity.sh +++ b/gravity.sh @@ -736,9 +736,9 @@ gravity_DownloadBlocklistFromUrl() { download=false else if [ "$(id -un)" == "root" ]; then - # If we are root, we need to check if the pihole user has read permission - # otherwise, we might read files that the pihole user should not be able to read - if sudo -u pihole test -r "${file_path}"; then + # If we are root, we need to check if the pihole user has read permission + # otherwise, we might read files that the pihole user should not be able to read + if sudo -u pihole test -r "${file_path}"; then echo -e "${OVER} ${INFO} Using local file ${file_path}" else echo -e "${OVER} ${CROSS} Cannot read file (user 'pihole' lacks read permission)"