mirror of
https://github.com/Crosstalk-Solutions/project-nomad.git
synced 2026-03-28 11:39:26 +01:00
fix: harden shell scripts with set -euo pipefail and safe sed substitution
- Add set -euo pipefail to install and update scripts for fail-fast behavior - Escape sed replacement strings to prevent injection via special characters - Add || true guards for commands expected to fail (tr pipe, read prompts) - Validate target_tag in update-watcher to prevent unsafe characters in sed - Properly quote variable assignments to satisfy strict mode https://claude.ai/code/session_01JFvpTYgm8GiE4vJ4cJKsFx
This commit is contained in:
parent
6058fd31a0
commit
9ca20a99e5
|
|
@ -1,4 +1,5 @@
|
|||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
# Project N.O.M.A.D. Installation Script
|
||||
|
||||
|
|
@ -133,7 +134,8 @@ generateRandomPass() {
|
|||
local password
|
||||
|
||||
# Generate random password using /dev/urandom
|
||||
password=$(tr -dc 'A-Za-z0-9' < /dev/urandom | head -c "$length")
|
||||
# tr may receive SIGPIPE when head closes early; this is expected behavior
|
||||
password=$(tr -dc 'A-Za-z0-9' < /dev/urandom | head -c "$length" || true)
|
||||
|
||||
echo "$password"
|
||||
}
|
||||
|
|
@ -337,7 +339,7 @@ setup_nvidia_container_toolkit() {
|
|||
get_install_confirmation(){
|
||||
echo -e "${YELLOW}#${RESET} This script will install Project N.O.M.A.D. and its dependencies on your machine."
|
||||
echo -e "${YELLOW}#${RESET} If you already have Project N.O.M.A.D. installed with customized config or data, please be aware that running this installation script may overwrite existing files and configurations. It is highly recommended to back up any important data/configs before proceeding."
|
||||
read -p "Are you sure you want to continue? (y/N): " choice
|
||||
read -p "Are you sure you want to continue? (y/N): " choice || true
|
||||
case "$choice" in
|
||||
y|Y )
|
||||
echo -e "${GREEN}#${RESET} User chose to continue with the installation."
|
||||
|
|
@ -358,7 +360,7 @@ accept_terms() {
|
|||
printf "\n"
|
||||
echo "By accepting this agreement, you acknowledge that you have read and understood the terms and conditions of the Apache License 2.0 and agree to be bound by them while using Project N.O.M.A.D."
|
||||
echo -e "\n\n"
|
||||
read -p "I have read and accept License Agreement & Terms of Use (y/N)? " choice
|
||||
read -p "I have read and accept License Agreement & Terms of Use (y/N)? " choice || true
|
||||
case "$choice" in
|
||||
y|Y )
|
||||
accepted_terms='true'
|
||||
|
|
@ -399,18 +401,36 @@ download_management_compose_file() {
|
|||
fi
|
||||
echo -e "${GREEN}#${RESET} Docker compose file downloaded successfully to $compose_file_path.\\n"
|
||||
|
||||
local app_key=$(generateRandomPass)
|
||||
local db_root_password=$(generateRandomPass)
|
||||
local db_user_password=$(generateRandomPass)
|
||||
local app_key
|
||||
local db_root_password
|
||||
local db_user_password
|
||||
app_key=$(generateRandomPass)
|
||||
db_root_password=$(generateRandomPass)
|
||||
db_user_password=$(generateRandomPass)
|
||||
|
||||
# Inject dynamic env values into the compose file
|
||||
# Escape sed special characters in variables to prevent injection
|
||||
# Using '#' as sed delimiter to avoid conflicts with '/' in URLs and IPs
|
||||
# Escaping &, \, #, and . (regex special) in both patterns and replacements
|
||||
echo -e "${YELLOW}#${RESET} Configuring docker-compose file env variables...\\n"
|
||||
sed -i "s|URL=replaceme|URL=http://${local_ip_address}:8080|g" "$compose_file_path"
|
||||
sed -i "s|APP_KEY=replaceme|APP_KEY=${app_key}|g" "$compose_file_path"
|
||||
|
||||
sed -i "s|DB_PASSWORD=replaceme|DB_PASSWORD=${db_user_password}|g" "$compose_file_path"
|
||||
sed -i "s|MYSQL_ROOT_PASSWORD=replaceme|MYSQL_ROOT_PASSWORD=${db_root_password}|g" "$compose_file_path"
|
||||
sed -i "s|MYSQL_PASSWORD=replaceme|MYSQL_PASSWORD=${db_user_password}|g" "$compose_file_path"
|
||||
|
||||
# Escape function for sed replacement strings (using '#' as delimiter)
|
||||
# Escapes: backslash, ampersand, hash (our delimiter), and newline
|
||||
sed_escape_replacement() {
|
||||
printf '%s\n' "$1" | sed 's/[&#\\/]/\\&/g'
|
||||
}
|
||||
|
||||
local escaped_ip escaped_app_key escaped_db_user_password escaped_db_root_password
|
||||
escaped_ip=$(sed_escape_replacement "${local_ip_address}")
|
||||
escaped_app_key=$(sed_escape_replacement "${app_key}")
|
||||
escaped_db_user_password=$(sed_escape_replacement "${db_user_password}")
|
||||
escaped_db_root_password=$(sed_escape_replacement "${db_root_password}")
|
||||
|
||||
sed -i "s#URL=replaceme#URL=http://${escaped_ip}:8080#g" "$compose_file_path"
|
||||
sed -i "s#APP_KEY=replaceme#APP_KEY=${escaped_app_key}#g" "$compose_file_path"
|
||||
sed -i "s#DB_PASSWORD=replaceme#DB_PASSWORD=${escaped_db_user_password}#g" "$compose_file_path"
|
||||
sed -i "s#MYSQL_ROOT_PASSWORD=replaceme#MYSQL_ROOT_PASSWORD=${escaped_db_root_password}#g" "$compose_file_path"
|
||||
sed -i "s#MYSQL_PASSWORD=replaceme#MYSQL_PASSWORD=${escaped_db_user_password}#g" "$compose_file_path"
|
||||
|
||||
echo -e "${GREEN}#${RESET} Docker compose file configured successfully.\\n"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,12 @@ perform_update() {
|
|||
sleep 1
|
||||
|
||||
# Apply target image tag to compose.yml before pulling
|
||||
# Validate target_tag contains only safe characters (alphanumeric, dots, hyphens, underscores)
|
||||
if ! echo "$target_tag" | grep -qE '^[a-zA-Z0-9._-]+$'; then
|
||||
log "ERROR: Invalid target tag '${target_tag}' - contains unsafe characters"
|
||||
write_status "error" 0 "Invalid target tag - contains unsafe characters"
|
||||
return 1
|
||||
fi
|
||||
log "Applying image tag '${target_tag}' to compose.yml..."
|
||||
if sed -i "s|\(image: ghcr\.io/crosstalk-solutions/project-nomad\):.*|\1:${target_tag}|" "$COMPOSE_FILE" 2>> "$LOG_FILE"; then
|
||||
log "Successfully updated compose.yml admin image tag to '${target_tag}'"
|
||||
|
|
@ -78,7 +84,7 @@ perform_update() {
|
|||
|
||||
for service in $SERVICES_TO_UPDATE; do
|
||||
log "Updating service: $service"
|
||||
write_status "recreating" $current_progress "Recreating $service..."
|
||||
write_status "recreating" "$current_progress" "Recreating $service..."
|
||||
|
||||
# Stop the service
|
||||
log " Stopping $service..."
|
||||
|
|
@ -94,7 +100,7 @@ perform_update() {
|
|||
log " ✓ Successfully recreated $service"
|
||||
else
|
||||
log " ERROR: Failed to recreate $service"
|
||||
write_status "error" $current_progress "Failed to recreate $service - check logs"
|
||||
write_status "error" "$current_progress" "Failed to recreate $service - check logs"
|
||||
return 1
|
||||
fi
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
echo "Finding Project N.O.M.A.D containers..."
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
echo "Finding running Docker containers for Project N.O.M.A.D..."
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
# Project N.O.M.A.D. Update Script
|
||||
|
||||
|
|
@ -22,6 +23,15 @@ GRAY_R='\033[39m'
|
|||
RED='\033[1;31m' # Light Red.
|
||||
GREEN='\033[1;32m' # Light Green.
|
||||
|
||||
###################################################################################################################################################################################################
|
||||
# #
|
||||
# Constants & Variables #
|
||||
# #
|
||||
###################################################################################################################################################################################################
|
||||
|
||||
NOMAD_DIR="/opt/project-nomad"
|
||||
local_ip_address=''
|
||||
|
||||
###################################################################################################################################################################################################
|
||||
# #
|
||||
# Functions #
|
||||
|
|
@ -61,7 +71,7 @@ check_is_debian_based() {
|
|||
}
|
||||
|
||||
get_update_confirmation(){
|
||||
read -p "This script will update Project N.O.M.A.D. and its dependencies on your machine. No data loss is expected, but you should always back up your data before proceeding. Are you sure you want to continue? (y/n): " choice
|
||||
read -p "This script will update Project N.O.M.A.D. and its dependencies on your machine. No data loss is expected, but you should always back up your data before proceeding. Are you sure you want to continue? (y/n): " choice || true
|
||||
case "$choice" in
|
||||
y|Y )
|
||||
echo -e "${GREEN}#${RESET} User chose to continue with the update."
|
||||
|
|
@ -136,7 +146,7 @@ get_local_ip() {
|
|||
success_message() {
|
||||
echo -e "${GREEN}#${RESET} Project N.O.M.A.D installation completed successfully!\\n"
|
||||
echo -e "${GREEN}#${RESET} Installation files are located at /opt/project-nomad\\n\n"
|
||||
echo -e "${GREEN}#${RESET} Project N.O.M.A.D's Command Center should automatically start whenever your device reboots. However, if you need to start it manually, you can always do so by running: ${WHITE_R}${nomad_dir}/start_nomad.sh${RESET}\\n"
|
||||
echo -e "${GREEN}#${RESET} Project N.O.M.A.D's Command Center should automatically start whenever your device reboots. However, if you need to start it manually, you can always do so by running: ${WHITE_R}${NOMAD_DIR}/start_nomad.sh${RESET}\\n"
|
||||
echo -e "${GREEN}#${RESET} You can now access the management interface at http://localhost:8080 or http://${local_ip_address}:8080\\n"
|
||||
echo -e "${GREEN}#${RESET} Thank you for supporting Project N.O.M.A.D!\\n"
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user