aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xarchsetup100
-rw-r--r--todo.org8
2 files changed, 85 insertions, 23 deletions
diff --git a/archsetup b/archsetup
index e7739ff..1624e78 100755
--- a/archsetup
+++ b/archsetup
@@ -122,8 +122,82 @@ load_config() {
[[ -n "$DESKTOP_ENV" ]] && desktop_env="$DESKTOP_ENV"
}
-# Load config if specified
-[[ -n "$config_file" ]] && load_config "$config_file"
+# Validate a candidate primary-account username: lowercase, starts with a
+# letter, only [a-z0-9_], and not a reserved system account. Pre-flight style
+# (prints to stderr and exits) since the logging helpers aren't defined yet at
+# the points this gets called.
+validate_username() {
+ local name="$1"
+ if [[ -z "$name" ]]; then
+ echo "ERROR: Username cannot be empty" >&2
+ exit 1
+ fi
+ if [[ ! "$name" =~ ^[a-z][a-z0-9_]*$ ]]; then
+ echo "ERROR: Invalid username: '$name'" >&2
+ echo " Must start with a lowercase letter and contain only lowercase letters, numbers, and underscores." >&2
+ exit 1
+ fi
+ local reserved_users="root bin daemon sys sync games man lp mail news uucp proxy www-data backup list irc gnats nobody systemd-network systemd-resolve messagebus polkitd sshd"
+ local reserved
+ for reserved in $reserved_users; do
+ if [[ "$name" == "$reserved" ]]; then
+ echo "ERROR: '$name' is a reserved system username" >&2
+ exit 1
+ fi
+ done
+}
+
+# Validate values pulled from --config-file, before anything is installed, so a
+# typo (DESKTOP_ENV=hyperland) fails immediately instead of partway through the
+# install. NOT a security boundary: load_config sources the config as bash, so a
+# hostile config can already run arbitrary code -- this just saves users from
+# their own mistakes.
+validate_config() {
+ [[ -n "$username" ]] && validate_username "$username"
+
+ if [[ -n "$desktop_env" && "$desktop_env" != "dwm" && "$desktop_env" != "hyprland" && "$desktop_env" != "none" ]]; then
+ echo "ERROR: DESKTOP_ENV must be one of: dwm, hyprland, none. Got: '$desktop_env'" >&2
+ exit 1
+ fi
+
+ if [[ -n "$AUTOLOGIN" && "$AUTOLOGIN" != "yes" && "$AUTOLOGIN" != "no" ]]; then
+ echo "ERROR: AUTOLOGIN must be 'yes' or 'no'. Got: '$AUTOLOGIN'" >&2
+ exit 1
+ fi
+ if [[ -n "$NO_GPU_DRIVERS" && "$NO_GPU_DRIVERS" != "yes" && "$NO_GPU_DRIVERS" != "no" ]]; then
+ echo "ERROR: NO_GPU_DRIVERS must be 'yes' or 'no'. Got: '$NO_GPU_DRIVERS'" >&2
+ exit 1
+ fi
+
+ if [[ -n "$locale" && ! "$locale" =~ ^[a-z]{2,3}(_[A-Z]{2})?(\.[A-Za-z0-9-]+)?(@[A-Za-z]+)?$ ]]; then
+ echo "ERROR: LOCALE looks malformed: '$locale'. Expected e.g. en_US.UTF-8" >&2
+ exit 1
+ fi
+
+ local repo
+ for repo in "$dwm_repo" "$dmenu_repo" "$st_repo" "$slock_repo" "$dotemacs_repo" "$archsetup_repo"; do
+ [[ -z "$repo" ]] && continue
+ case "$repo" in
+ http://*|https://*|git://*|ssh://*) ;;
+ *@*:*) ;;
+ *)
+ echo "ERROR: Repository URL looks unsupported: '$repo'" >&2
+ echo " Expected http(s)://, git://, ssh://, or user@host:path." >&2
+ exit 1
+ ;;
+ esac
+ if [[ "$repo" =~ [[:space:]] || "$repo" == -* ]]; then
+ echo "ERROR: Repository URL contains whitespace or starts with '-': '$repo'" >&2
+ exit 1
+ fi
+ done
+}
+
+# Load config if specified, then validate what it set
+if [[ -n "$config_file" ]]; then
+ load_config "$config_file"
+ validate_config
+fi
### Configuration Defaults
# These can be overridden via --config-file
@@ -315,30 +389,14 @@ preflight_checks() {
echo " [OK] Locale: $locale (selected)"
fi
- # Prompt for username if not set
+ # Prompt for username if not set; validate either way
if [[ -z "$username" ]]; then
echo ""
read -r -p "Enter username for primary account: " username
- if [[ -z "$username" ]]; then
- echo "ERROR: Username cannot be empty"
- exit 1
- fi
- # Validate username (lowercase, starts with letter, alphanumeric + underscore)
- if [[ ! "$username" =~ ^[a-z][a-z0-9_]*$ ]]; then
- echo "ERROR: Invalid username"
- echo " Must start with lowercase letter, contain only lowercase letters, numbers, underscores"
- exit 1
- fi
- # Reject reserved system usernames
- local reserved_users="root bin daemon sys sync games man lp mail news uucp proxy www-data backup list irc gnats nobody systemd-network systemd-resolve messagebus polkitd sshd"
- for reserved in $reserved_users; do
- if [[ "$username" == "$reserved" ]]; then
- echo "ERROR: '$username' is a reserved system username"
- exit 1
- fi
- done
+ validate_username "$username"
echo " [OK] Username: $username"
else
+ validate_username "$username"
echo " [OK] Username: $username (from config)"
fi
diff --git a/todo.org b/todo.org
index c549464..62b60ff 100644
--- a/todo.org
+++ b/todo.org
@@ -96,12 +96,16 @@ May have licensing issues for redistribution.
Line 1781: =curl | sh= from claude.ai — should be behind a config flag.
Not all users want AI tooling; curl-pipe-bash is a red flag for reviewers.
-*** TODO [#B] Add input validation for username and paths
+*** DOING [#B] Add input validation for username and paths
Variables like ~$username~, ~$source_dir~, and paths are not validated.
Special characters or malicious input could break the script or cause security issues.
Should validate inputs match expected patterns (alphanumeric, valid paths, etc.).
-cj: you can probably do this one on your own
+**** 2026-05-11 Mon @ 18:20:49 -0500 AI Response: validate_config + validate_username added
+Added two pre-flight validators to =archsetup= (right after =load_config=, before any install step):
+- =validate_username()= — the lowercase / starts-with-letter / =[a-z0-9_]= / not-reserved check, extracted from the inline block in =preflight_checks()=. Fixes an existing gap: the inline check only ran on the *prompted* path, so a config with =USERNAME=root= (or =USERNAME=foo bar=) slipped through unvalidated. Now both =preflight_checks= and =validate_config= call it.
+- =validate_config()= — runs whenever =--config-file= is used: rejects unknown =DESKTOP_ENV= (must be dwm/hyprland/none) early instead of dying in step 7-9; rejects =AUTOLOGIN=/=NO_GPU_DRIVERS= values that aren't =yes=/=no= (currently silently ignored); basic shape check on =LOCALE=; and a scheme + no-whitespace/no-leading-dash check on the six =*_REPO= URLs that get passed to =git clone= (rejects e.g. =--upload-pack=…= injection). Plain =echo …>&2; exit 1= (the logging helpers aren't defined that early). =$source_dir= needs no separate check — it's =/home/$username/.local/src=, derived from the now-always-validated =$username=.
+Not a security boundary (=load_config= sources the config as bash; a hostile config can already run anything) — it's typo-catching. Verified with =bash -n= and a smoke-test matrix of good/bad inputs through both functions. The next =make test= run confirms valid configs still install. Leaving as DOING for review.
*** TODO [#B] Move battery out of waybar sysmonitor group
Battery module is inside =group/sysmonitor= which bundles cpu, temp, memory, disk, and battery together. Battery should be a standalone module in =modules-right= so it's visible on laptops without the full sysmonitor group.