diff --git a/nixos-module/default.nix b/nixos-module/default.nix index 74fbd20..275c0cd 100644 --- a/nixos-module/default.nix +++ b/nixos-module/default.nix @@ -41,6 +41,15 @@ let in if builtins.length parts > 1 then lib.concatStringsSep "/" (lib.init parts) else null) writableDirs)); + # Escape a value for interpolation into a single-quoted SQL string literal + # (used for the admin-seed INSERT below). Doubling backslashes first, then + # quotes, matches MySQL/MariaDB's default (backslash-escapes-active) + # string literal rules -- without this, an ordinary value like "O'Brien" + # breaks the INSERT's SQL syntax outright (failing hortusfox-setup on + # first boot, since the script runs under `set -euo pipefail`), and a + # crafted value could inject arbitrary SQL. + sqlEscape = s: lib.replaceStrings [ "\\" "'" ] [ "\\\\" "''" ] s; + # Render one KEY=VALUE .env line. Booleans/ints/floats are left bare so # Asatru's datatype auto-detection picks them up as such rather than string. mkEnvLine = name: value: @@ -384,7 +393,7 @@ in { # this point. ${lib.optionalString (cfg.adminAccount.passwordFile != null) '' admin_hash="$(php -r 'echo password_hash($argv[1], PASSWORD_BCRYPT);' "$(cat "${cfg.adminAccount.passwordFile}")")" - mariadb "${cfg.database.name}" -e "INSERT INTO UserModel (name, email, password, admin) VALUES ('${cfg.adminAccount.username}', '${cfg.adminAccount.email}', '$admin_hash', 1);" + mariadb "${cfg.database.name}" -e "INSERT INTO UserModel (name, email, password, admin) VALUES ('${sqlEscape cfg.adminAccount.username}', '${sqlEscape cfg.adminAccount.email}', '$admin_hash', 1);" ''} touch "${stateDir}/.installed"