Wrong values for the version or update URL will cause very confusing build-time or runtime errors. Provide a better user experience by validating them up-front. The update URL validator is loose. It rejects only URLs that cannot possibly work: either appending /SHA256SUMS to them doesn't append to the path, or they will definitely be rejected by curl due to being malformed. The version validator is in lib/config.nix, as the version number is used in many places. It checks that the version only uses characters that are permitted by systemd's version number specification [1] and that will not break code that uses them in shell or sed commands. [1]: https://uapi-group.org/specifications/specs/version_format_specification Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com> --- Changes since v2: - Use loose URL validation: allow anything that might work. - Only reject versions that violate the specification. --- host/rootfs/default.nix | 19 ++++++++++++++++++- lib/config.nix | 20 ++++++++++++++------ 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/host/rootfs/default.nix b/host/rootfs/default.nix index f0b7e061a1f39b3e70d337ef4fe14c98a8f022c8..06147eb8d1b713faac9b69ffdf42138d0c3e3093 100644 --- a/host/rootfs/default.nix +++ b/host/rootfs/default.nix @@ -85,6 +85,23 @@ let appvm-systemd-sysupdate = callSpectrumPackage ../../vm/app/systemd-sysupdate {}; }; + update-url = + let update-url = config.update-url; in + # Use builtins.fromJSON because it supports \uXXXX escapes. + # This is the same check done by check-url.awk in the update VM. + # The update code is careful to escape any metacharacters, but some + # simply cannot be made to work. Concatenating the URL with /SHA256SUMS + # must append to the path portion of the URL, and the URL must be one + # that libcurl will accept. I don't know how Unicode space is handled, + # but it is a bad idea. + if builtins.match (builtins.fromJSON "\"^[^\\u0001- #?\\u007F[:space:]]+$\"" update-url) == null then + builtins.abort '' + Update URL ${builtins.toJSON update-url} has forbidden characters. + Query strings, and fragment specifiers are not supported. + ASCII control characters and whitespace must be %-encoded. + '' + else + update-url; packagesSysroot = runCommand "packages-sysroot" { depsBuildBuild = [ inkscape ]; nativeBuildInputs = [ xorg.lndir ]; @@ -151,7 +168,7 @@ stdenvNoCC.mkDerivation { sed p ${writeClosure [ packagesSysroot] } >>$out ''; UPDATE_SIGNING_KEY = config.update-signing-key; - UPDATE_URL = config.update-url; + UPDATE_URL = update-url; VERSION = config.version; }; diff --git a/lib/config.nix b/lib/config.nix index d7edb967f339f2d0af97adef5c0302eb58950d19..4db6c34635abb1419224485f1e56119569375831 100644 --- a/lib/config.nix +++ b/lib/config.nix @@ -21,9 +21,17 @@ let finalConfig = default // callConfig config; in -finalConfig // { - update-signing-key = builtins.path { - name = "signing-key"; - path = finalConfig.update-signing-key; - }; -} +# See https://uapi-group.org/specifications/specs/version_format_specification +# for allowed version strings. +if builtins.match "[[:alnum:]_.~^-]+" finalConfig.version == null then + builtins.abort '' + Version ${builtins.toJSON finalConfig.version} has forbidden characters. + Only ASCII alphanumerics, ".", "_", "~", "^", "+", and "-" are allowed. + '' +else + finalConfig // { + update-signing-key = builtins.path { + name = "signing-key"; + path = finalConfig.update-signing-key; + }; + } -- 2.52.0