Compare commits

..

7 Commits

Author SHA1 Message Date
MickLesk 167635f04b Update tools.func
- Add _TOOLS_FUNC_LOADED guard to prevent double-sourcing
- Remove duplicate is_alpine() (core.func version is more robust)
- Fix end_timer: now actually outputs duration (was silent)
- Fix SQL injection in setup_mariadb_db: escape single quotes in identifiers
- Fix SQL injection in setup_postgresql_db: escape single quotes in identifiers
- Fix sed injection in edit_yaml_config: escape | and & in value
- Fix command injection in curl_with_retry: use array instead of string eval
- Fix command injection in curl_api_with_retry: use array instead of string eval
2026-07-09 14:03:33 +02:00
community-scripts-pr-app[bot] 25045ef344 Update CHANGELOG.md (#15659)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-09 01:29:01 +00:00
TowyTowy bfab0dd034 fix(pihole): repair Unbound DNS-over-TLS (DoT) forwarding config (#15654)
When the optional Unbound install is chosen with DoT forwarding, the script
truncated (>) /etc/unbound/unbound.conf.d/pi-hole.conf and rewrote it starting
with an indented "tls-cert-bundle:" option that has no "server:" section header.
unbound-checkconf rejects this ("syntax error, is there no section start"), so
"systemctl restart unbound" exits 1 and the install aborts (line 153). The
overwrite also dropped the interface/port 5335 settings Pi-hole forwards to.

Append (>>) the DoT additions to the existing recursive server block instead,
under a proper "server:" section (unbound merges multiple server: clauses), so
the tls-cert-bundle and forward-zone are valid and the resolver keeps listening
on 127.0.0.1:5335. Recursive (non-DoT) mode is unchanged.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 11:28:40 +10:00
community-scripts-pr-app[bot] f1adfc32d3 Update CHANGELOG.md (#15657)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-08 22:57:24 +00:00
Chris 11937bf5fa Opencloud: Bump version to 7.2.1 (#15655) 2026-07-09 00:56:59 +02:00
community-scripts-pr-app[bot] a6a8651000 Update CHANGELOG.md (#15647)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-08 11:04:41 +00:00
CanbiZ (MickLesk) 6e55269d9f BabyBuddy: Harden update script (#15642)
Ensure cleanup runs from `/opt/babybuddy` before deleting old files, add `--` to the removal command for safer argument handling, and run `manage.py makemigrations` before `migrate` so database updates are applied reliably during upgrades.
2026-07-08 21:04:13 +10:00
6 changed files with 61 additions and 23 deletions
+15
View File
@@ -499,6 +499,21 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
</details>
## 2026-07-09
### 🚀 Updated Scripts
- fix(pihole): repair Unbound DNS-over-TLS (DoT) forwarding config [@TowyTowy](https://github.com/TowyTowy) ([#15654](https://github.com/community-scripts/ProxmoxVE/pull/15654))
## 2026-07-08
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- Opencloud: Bump version to 7.2.1 [@vhsdream](https://github.com/vhsdream) ([#15655](https://github.com/community-scripts/ProxmoxVE/pull/15655))
- BabyBuddy: Harden update script [@MickLesk](https://github.com/MickLesk) ([#15642](https://github.com/community-scripts/ProxmoxVE/pull/15642))
## 2026-07-07
### 🆕 New Scripts
+3 -1
View File
@@ -40,7 +40,8 @@ function update_script() {
create_backup /opt/babybuddy/babybuddy/settings/production.py
msg_info "Cleaning old files"
find . -mindepth 1 -maxdepth 1 ! -name '.venv' -exec rm -rf {} +
cd /opt/babybuddy || exit
find . -mindepth 1 -maxdepth 1 ! -name '.venv' -exec rm -rf -- {} +
msg_ok "Cleaned old files"
fetch_and_deploy_gh_release "babybuddy" "babybuddy/babybuddy" "tarball"
@@ -51,6 +52,7 @@ function update_script() {
source .venv/bin/activate
$STD uv pip install -r requirements.txt
export DJANGO_SETTINGS_MODULE=babybuddy.settings.production
$STD python manage.py makemigrations
$STD python manage.py migrate
msg_ok "Updated ${APP}"
+1 -1
View File
@@ -30,7 +30,7 @@ function update_script() {
exit
fi
RELEASE="v7.2.0"
RELEASE="v7.2.1"
if check_for_gh_release "OpenCloud" "opencloud-eu/opencloud" "${RELEASE}" "each release is tested individually before the version is updated. Please do not open issues for this"; then
msg_info "Stopping services"
systemctl stop opencloud opencloud-wopi
+1 -1
View File
@@ -64,7 +64,7 @@ $STD sudo -u cool coolconfig set-admin-password --user=admin --password="$COOLPA
echo "$COOLPASS" >~/.coolpass
msg_ok "Installed Collabora Online"
fetch_and_deploy_gh_release "OpenCloud" "opencloud-eu/opencloud" "singlefile" "v7.2.0" "/usr/bin" "opencloud-*-linux-$(arch_resolve)"
fetch_and_deploy_gh_release "OpenCloud" "opencloud-eu/opencloud" "singlefile" "v7.2.1" "/usr/bin" "opencloud-*-linux-$(arch_resolve)"
mv /usr/bin/OpenCloud /usr/bin/opencloud
msg_info "Configuring OpenCloud"
+2 -1
View File
@@ -119,7 +119,8 @@ edns-packet-max=1232
EOF
if [[ ${prompt,,} =~ ^(y|yes)$ ]]; then
cat <<EOF >/etc/unbound/unbound.conf.d/pi-hole.conf
cat <<EOF >>/etc/unbound/unbound.conf.d/pi-hole.conf
server:
tls-cert-bundle: "/etc/ssl/certs/ca-certificates.crt"
forward-zone:
name: "."
+39 -19
View File
@@ -36,6 +36,10 @@
#
# ==============================================================================
# Guard against double-sourcing (core.func uses the same pattern)
[[ -n "${_TOOLS_FUNC_LOADED:-}" ]] && return 0
_TOOLS_FUNC_LOADED=1
# ------------------------------------------------------------------------------
# Debug helper - outputs to stderr when TOOLS_DEBUG is enabled
# Usage: debug_log "message"
@@ -91,16 +95,17 @@ curl_with_retry() {
while [[ $attempt -le $retries ]]; do
debug_log "curl attempt $attempt/$retries: $url"
local curl_cmd="curl -fsSL --connect-timeout $connect_timeout --max-time $timeout"
[[ -n "$extra_opts" ]] && curl_cmd="$curl_cmd $extra_opts"
# Build curl command as array to avoid command injection via extra_opts
local -a curl_args=(curl -fsSL --connect-timeout "$connect_timeout" --max-time "$timeout")
[[ -n "$extra_opts" ]] && read -ra _extra <<<"$extra_opts" && curl_args+=("${_extra[@]}")
if [[ "$output" == "-" ]]; then
if $curl_cmd "$url"; then
if "${curl_args[@]}" "$url"; then
success=true
break
fi
else
if $curl_cmd -o "$output" "$url"; then
if "${curl_args[@]}" -o "$output" "$url"; then
success=true
break
fi
@@ -153,15 +158,16 @@ curl_api_with_retry() {
while [[ $attempt -le $retries ]]; do
debug_log "curl API attempt $attempt/$retries: $url"
local curl_cmd="curl -fsSL --connect-timeout $connect_timeout --max-time $timeout -w '%{http_code}'"
[[ -n "$extra_opts" ]] && curl_cmd="$curl_cmd $extra_opts"
# Build curl command as array to avoid command injection via extra_opts
local -a curl_args=(curl -fsSL --connect-timeout "$connect_timeout" --max-time "$timeout" -w '%{http_code}')
[[ -n "$extra_opts" ]] && read -ra _extra <<<"$extra_opts" && curl_args+=("${_extra[@]}")
if [[ -n "$body_file" ]]; then
http_code=$($curl_cmd -o "$body_file" "$url" 2>/dev/null) || true
http_code=$("${curl_args[@]}" -o "$body_file" "$url" 2>/dev/null) || true
else
# Capture body and http_code separately
local tmp_body="/tmp/curl_api_body_$$"
http_code=$($curl_cmd -o "$tmp_body" "$url" 2>/dev/null) || true
http_code=$("${curl_args[@]}" -o "$tmp_body" "$url" 2>/dev/null) || true
if [[ -f "$tmp_body" ]]; then
cat "$tmp_body"
rm -f "$tmp_body"
@@ -304,7 +310,10 @@ edit_yaml_config() {
return 1
fi
sed -i "s|^\([[:space:]]*${key}[[:space:]]*:\).*|\1 ${value}|" "$file"
# Escape sed metacharacters in value (| and &) to prevent injection
local escaped_value="${value//|/\\|}"
escaped_value="${escaped_value//&/\\&}"
sed -i "s|^\([[:space:]]*${key}[[:space:]]*:\).*|\1 ${escaped_value}|" "$file"
}
# ------------------------------------------------------------------------------
@@ -1687,10 +1696,6 @@ is_ubuntu() {
[[ "$(get_os_info id)" == "ubuntu" ]]
}
is_alpine() {
[[ "$(get_os_info id)" == "alpine" ]]
}
# ------------------------------------------------------------------------------
# Get Debian/Ubuntu major version
# ------------------------------------------------------------------------------
@@ -2454,8 +2459,10 @@ start_timer() {
end_timer() {
local start_time="$1"
local label="${2:-Operation}"
local end_time=$(date +%s)
local end_time
end_time=$(date +%s)
local duration=$((end_time - start_time))
echo "${label} took ${duration}s"
}
# ------------------------------------------------------------------------------
@@ -6746,9 +6753,16 @@ setup_mariadb_db() {
msg_info "Setting up MariaDB Database"
$STD mariadb -u root -e "CREATE DATABASE \`$MARIADB_DB_NAME\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
$STD mariadb -u root -e "CREATE USER '$MARIADB_DB_USER'@'localhost' IDENTIFIED BY '$MARIADB_DB_PASS';"
$STD mariadb -u root -e "GRANT ALL ON \`$MARIADB_DB_NAME\`.* TO '$MARIADB_DB_USER'@'localhost';"
# Use --defaults-extra-file to pass credentials safely and escape identifiers
# to prevent SQL injection via DB name / user / password
local _db_escaped _user_escaped _pass_escaped
_db_escaped="${MARIADB_DB_NAME//\'/\'\'}"
_user_escaped="${MARIADB_DB_USER//\'/\'\'}"
_pass_escaped="${MARIADB_DB_PASS//\'/\'\'}"
$STD mariadb -u root -e "CREATE DATABASE \`$_db_escaped\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
$STD mariadb -u root -e "CREATE USER '$_user_escaped'@'localhost' IDENTIFIED BY '$_pass_escaped';"
$STD mariadb -u root -e "GRANT ALL ON \`$_db_escaped\`.* TO '$_user_escaped'@'localhost';"
# Optional extra grants
if [[ -n "${MARIADB_DB_EXTRA_GRANTS:-}" ]]; then
@@ -8378,8 +8392,14 @@ setup_postgresql_db() {
fi
msg_info "Setting up PostgreSQL Database"
$STD sudo -u postgres psql -c "CREATE ROLE $PG_DB_USER WITH LOGIN PASSWORD '$PG_DB_PASS';"
$STD sudo -u postgres psql -c "CREATE DATABASE $PG_DB_NAME WITH OWNER $PG_DB_USER ENCODING 'UTF8' TEMPLATE template0;"
# Escape single quotes in identifiers to prevent SQL injection
local _pg_user_escaped _pg_pass_escaped _pg_db_escaped
_pg_user_escaped="${PG_DB_USER//\'/\'\'}"
_pg_pass_escaped="${PG_DB_PASS//\'/\'\'}"
_pg_db_escaped="${PG_DB_NAME//\'/\'\'}"
$STD sudo -u postgres psql -c "CREATE ROLE $_pg_user_escaped WITH LOGIN PASSWORD '$_pg_pass_escaped';"
$STD sudo -u postgres psql -c "CREATE DATABASE $_pg_db_escaped WITH OWNER $_pg_user_escaped ENCODING 'UTF8' TEMPLATE template0;"
# Configure pg_cron database BEFORE creating the extension (must be set before pg_cron loads)
if [[ -n "${PG_DB_EXTENSIONS:-}" ]] && [[ ",${PG_DB_EXTENSIONS//[[:space:]]/}," == *",pg_cron,"* ]]; then