From 9a4a4ee51a946cd0ffd873614d5ea4cba62d3abb Mon Sep 17 00:00:00 2001 From: naturallaw77 Date: Tue, 27 Oct 2026 02:25:24 +0000 Subject: [PATCH] php: assert the security floor via config.assertions, not a module-level assert MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous commit moved the CVE-2026-109618/109619 floor into a bare `assert ... ; { ... }` above the module body. That breaks evaluation: error: infinite recursion encountered ... while evaluating the module argument `pkgs` in /nix/store/...-source/modules/php.nix ... noting that argument `pkgs` is not externally provided, so querying `_module.args` instead, requiring `config` A module-level assert is checked as soon as the module's attrset is forced to WHNF, which the module system does while merging definitions (it is the `checkUnmatched` branch in lib/modules.nix that was on the stack). At that point `pkgs` is not an externally supplied argument — there are no specialArgs here — so it resolves through `config._module.args.pkgs` (lib/modules.nix:745), and that option lives in the same fixpoint that is still being computed. Hence the loop. The old code never hit this because `phpBase` was only forced from inside `options`/`config`, i.e. after the fixpoint existed. Move the check to `config.assertions`, which is evaluated inside the fixpoint once `pkgs` is available. Behaviour is unchanged: a rolled-back nixpkgs pin still fails the build with the floor message instead of silently building a vulnerable PHP. --- modules/php.nix | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/modules/php.nix b/modules/php.nix index 05f1690..a3ba0f5 100755 --- a/modules/php.nix +++ b/modules/php.nix @@ -103,12 +103,6 @@ let }; in -assert lib.assertMsg (lib.versionAtLeast phpBase.version phpSecurityFloor) '' - sovran_systemsOS: the pinned nixpkgs ships PHP ${phpBase.version}, below the - security floor ${phpSecurityFloor} (CVE-2026-109618 / CVE-2026-109619). - Update the nixpkgs input in flake.lock instead of pinning a version here. -''; - { options.sovran_systemsOS.phpPackage = lib.mkOption { type = lib.types.package; @@ -117,6 +111,29 @@ assert lib.assertMsg (lib.versionAtLeast phpBase.version phpSecurityFloor) '' }; config = { + # Security floor. This has to live in `config.assertions`, NOT in a + # module-level `assert` above the module body: a bare + # `assert ; { ... }` forces `phpBase` (and therefore `pkgs`) as + # soon as the module's attrset is forced to WHNF, which happens while + # the module system is still merging `_module.args`. `pkgs` is not an + # externally supplied argument here, so it resolves through + # `config._module.args.pkgs` (lib/modules.nix:745) — which requires + # `config`, the very fixpoint being computed — giving + # "error: infinite recursion encountered" pointing at modules/php.nix. + # `config.assertions` is evaluated inside the fixpoint, once `pkgs` + # exists, which is the supported way to assert on package versions. + assertions = [ + { + assertion = lib.versionAtLeast phpBase.version phpSecurityFloor; + message = '' + sovran_systemsOS: the pinned nixpkgs ships PHP ${phpBase.version}, + below the security floor ${phpSecurityFloor} (CVE-2026-109618 / + CVE-2026-109619). Update the nixpkgs input in flake.lock instead + of pinning a version in modules/php.nix. + ''; + } + ]; + users.users = { php = {