diff --git a/nixos/modules/config/shells-environment.nix b/nixos/modules/config/shells-environment.nix index a3ee4d6507f9..0623ae6fdaeb 100644 --- a/nixos/modules/config/shells-environment.nix +++ b/nixos/modules/config/shells-environment.nix @@ -36,6 +36,24 @@ in options = { + environment.shell.enable = lib.mkEnableOption "" // { + default = true; + internal = true; + description = '' + Whether to enable the shell environment. + + This does NOT necessarily disable all shells on your system. Instead it + just disables the shell environment that configures user shells (i.e. + those in `environment.shells`). + + System services might still depend on and use shells even if this + option is set to false. + + Only set this option if you're sure that you can recover from potential + issues. + ''; + }; + environment.variables = lib.mkOption { default = { }; example = { @@ -175,10 +193,10 @@ in }; environment.binsh = lib.mkOption { - default = "${config.system.build.binsh}/bin/sh"; - defaultText = lib.literalExpression ''"''${config.system.build.binsh}/bin/sh"''; + default = null; + defaultText = lib.literalExpression ''"''${pkgs.bashInteractive}/bin/sh"''; example = lib.literalExpression ''"''${pkgs.dash}/bin/dash"''; - type = lib.types.path; + type = lib.types.nullOr lib.types.path; visible = false; description = '' The shell executable that is linked system-wide to @@ -201,9 +219,10 @@ in }; - config = { + config = lib.mkIf cfg.shell.enable { - system.build.binsh = pkgs.bashInteractive; + # Set this here so its enabled only when shell support is enabled + environment.binsh = lib.mkDefault "${pkgs.bashInteractive}/bin/sh"; # Set session variables in the shell as well. This is usually # unnecessary, but it allows changes to session variables to take diff --git a/nixos/modules/profiles/bashless.nix b/nixos/modules/profiles/bashless.nix new file mode 100644 index 000000000000..b6764a92f4f8 --- /dev/null +++ b/nixos/modules/profiles/bashless.nix @@ -0,0 +1,46 @@ +{ lib, ... }: + +{ + + # Bashless builds on perlless + imports = [ ./perlless.nix ]; + + # Remove bash from activation + system.nixos-init.enable = lib.mkDefault true; + system.activatable = lib.mkDefault false; + environment.shell.enable = lib.mkDefault false; + programs.bash.enable = lib.mkDefault false; + + # Random bash remnants + environment.corePackages = lib.mkForce [ ]; + # Contains bash completions + nix.enable = lib.mkDefault false; + # The fuse{,3} package contains a runtime dependency on bash. + programs.fuse.enable = lib.mkDefault false; + documentation.man.man-db.enable = lib.mkDefault false; + # autovt depends on bash + console.enable = lib.mkDefault false; + # dhcpcd and openresolv depend on bash + networking.useNetworkd = lib.mkDefault true; + # bcache tools depend on bash. + boot.bcache.enable = lib.mkDefault false; + # iptables depends on bash and nixos-firewall-tool is a bash script + networking.firewall.enable = lib.mkDefault false; + # the wrapper script is in bash + security.enableWrappers = lib.mkDefault false; + # kexec script is written in bash + boot.kexec.enable = lib.mkDefault false; + # Relies on bash scripts + powerManagement.enable = lib.mkDefault false; + # Has some bash inside + systemd.shutdownRamfs.enable = lib.mkDefault false; + # Relies on the gzip command which depends on bash + services.logrotate.enable = lib.mkDefault false; + # Service relies on bash scripts + services.timesyncd.enable = lib.mkDefault false; + + # Check that the system does not contain a Nix store path that contains the + # string "bash". + system.forbiddenDependenciesRegexes = [ "bash" ]; + +} diff --git a/nixos/modules/programs/shadow.nix b/nixos/modules/programs/shadow.nix index 049d5d0c78a7..12c9a84333bf 100644 --- a/nixos/modules/programs/shadow.nix +++ b/nixos/modules/programs/shadow.nix @@ -158,6 +158,8 @@ in This must not be a store path, since the path is used outside the store (in particular in /etc/passwd). ''; + # /bin/sh is also the compiled in default of the shadow package. + default = "/bin/sh"; example = lib.literalExpression "pkgs.zsh"; type = lib.types.either lib.types.path lib.types.shellPackage; }; diff --git a/nixos/modules/system/activation/top-level.nix b/nixos/modules/system/activation/top-level.nix index c218bb15ba14..9a1cde27bf77 100644 --- a/nixos/modules/system/activation/top-level.nix +++ b/nixos/modules/system/activation/top-level.nix @@ -376,7 +376,9 @@ in ); # End if legacy environment variables - preSwitchCheck = config.system.preSwitchChecksScript; + preSwitchCheck = lib.mkIf ( + config.system.preSwitchChecks != { } + ) config.system.preSwitchChecksScript; # Not actually used in the builder. `passedChecks` is just here to create # the build dependencies. Checks are similar to build dependencies in the diff --git a/nixos/modules/system/boot/systemd/initrd.nix b/nixos/modules/system/boot/systemd/initrd.nix index 761d05fc873e..f2b1b4fc7ede 100644 --- a/nixos/modules/system/boot/systemd/initrd.nix +++ b/nixos/modules/system/boot/systemd/initrd.nix @@ -325,6 +325,22 @@ in ''; }; + shell.enable = lib.mkEnableOption "" // { + default = config.environment.shell.enable; + internal = true; + description = '' + Whether to enable a shell in the initrd. + + In contrast to `environment.shell.enable`, this option actually + strictly disables all shells in the initrd because they're not copied + into it anymore. Paths that use a shell (e.g. via the `script` option), + will break if this option is set. + + Only set this option if you're sure that you can recover from potential + issues. + ''; + }; + units = mkOption { description = "Definition of systemd units."; default = { }; @@ -460,13 +476,15 @@ in ++ lib.optional (config.boot.initrd.systemd.root == "gpt-auto") "rw"; boot.initrd.systemd = { - # bashInteractive is easier to use and also required by debug-shell.service initrdBin = [ - pkgs.bashInteractive pkgs.coreutils cfg.package ] - ++ lib.optional (config.system.build.kernel.config.isYes "MODULES") cfg.package.kmod; + ++ lib.optional (config.system.build.kernel.config.isYes "MODULES") cfg.package.kmod + ++ lib.optionals cfg.shell.enable [ + # bashInteractive is easier to use and also required by debug-shell.service + pkgs.bashInteractive + ]; extraBin = { less = "${pkgs.less}/bin/less"; mount = "${cfg.package.util-linux}/bin/mount"; @@ -550,11 +568,6 @@ in "${cfg.package.util-linux}/bin/umount" "${cfg.package.util-linux}/bin/sulogin" - # required for services generated with writeShellScript and friends - pkgs.runtimeShell - # some tools like xfs still want the sh symlink - "${pkgs.bashNonInteractive}/bin" - # so NSS can look up usernames "${pkgs.glibc}/lib/libnss_files.so.2" @@ -566,6 +579,12 @@ in ++ lib.optionals config.system.nixos-init.enable [ "${config.system.nixos-init.package}/bin/initrd-init" ] + ++ lib.optionals cfg.shell.enable [ + # required for services generated with writeShellScript and friends + pkgs.runtimeShell + # some tools like xfs still want the sh symlink + "${pkgs.bashNonInteractive}/bin" + ] ++ jobScripts ++ map (c: builtins.removeAttrs c [ "text" ]) (builtins.attrValues cfg.contents); diff --git a/nixos/modules/testing/test-instrumentation.nix b/nixos/modules/testing/test-instrumentation.nix index 9fb3ad6ab774..8461a7472d2b 100644 --- a/nixos/modules/testing/test-instrumentation.nix +++ b/nixos/modules/testing/test-instrumentation.nix @@ -85,6 +85,9 @@ in { options.testing = { + backdoor = lib.mkEnableOption "backdoor service in stage 2" // { + default = true; + }; initrdBackdoor = lib.mkEnableOption '' backdoor.service in initrd. Requires @@ -107,12 +110,14 @@ in } ]; - systemd.services.backdoor = lib.mkMerge [ - backdoorService - { - wantedBy = [ "multi-user.target" ]; - } - ]; + systemd.services.backdoor = lib.mkIf cfg.backdoor ( + lib.mkMerge [ + backdoorService + { + wantedBy = [ "multi-user.target" ]; + } + ] + ); boot.initrd.systemd = lib.mkMerge [ { diff --git a/nixos/tests/activation/bashless-closure.nix b/nixos/tests/activation/bashless-closure.nix new file mode 100644 index 000000000000..660090dd30c3 --- /dev/null +++ b/nixos/tests/activation/bashless-closure.nix @@ -0,0 +1,78 @@ +{ + nixos, + stdenvNoCC, + jq, + zstd, + cpio, +}: + +let + machine = nixos ( + { lib, modulesPath, ... }: + { + imports = [ "${modulesPath}/profiles/bashless.nix" ]; + + fileSystems."/" = { + device = "/dev/disk/by-partlabel/root"; + fsType = "ext4"; + }; + + system.stateVersion = lib.trivial.release; + } + ); +in +{ + # Keep this around for easier debugging, e.g. with nix why-depends. + inherit (machine) toplevel; + + machine = stdenvNoCC.mkDerivation { + name = "bashless-closure-machine"; + + __structuredAttrs = true; + + exportReferencesGraph.closure = [ machine.toplevel ]; + + preferLocalBuild = true; + + nativeBuildInputs = [ + jq + ]; + + buildCommand = '' + set +e + jq -r '.closure[].path' < "$NIX_ATTRS_JSON_FILE" | grep bash + + exit_code=$? + if [ $exit_code -eq 0 ]; then + echo "Error: toplevel contains bash" + exit 1 + fi + + touch $out + ''; + }; + + initrd = stdenvNoCC.mkDerivation { + name = "bashless-closure-initrd"; + + preferLocalBuild = true; + + nativeBuildInputs = [ + zstd + cpio + ]; + + buildCommand = '' + set +e + zstd -dfc ${machine.toplevel}/initrd | cpio --quiet -t | grep bash + + exit_code=$? + if [ $exit_code -eq 0 ]; then + echo "Error: initrd contains bash" + exit 1 + fi + + touch $out + ''; + }; +} diff --git a/nixos/tests/activation/bashless-image.nix b/nixos/tests/activation/bashless-image.nix new file mode 100644 index 000000000000..9b5f868ac6a0 --- /dev/null +++ b/nixos/tests/activation/bashless-image.nix @@ -0,0 +1,109 @@ +# Tests a bashless image. The forbiddenDependenciesRegexes from the bashless +# profile ensures that the closure doesn't contain any bash. + +{ lib, ... }: + +let + storePartitionLabel = "root"; +in +{ + + name = "activation-bashless-image"; + + meta.maintainers = with lib.maintainers; [ nikstur ]; + + nodes.machine = + { + config, + pkgs, + modulesPath, + ... + }: + { + imports = [ + "${modulesPath}/image/repart.nix" + "${modulesPath}/profiles/bashless.nix" + ]; + + # Backdoor uses bash + testing.backdoor = false; + + virtualisation = { + directBoot.enable = false; + mountHostNixStore = false; + useEFIBoot = true; + }; + + boot.loader.grub.enable = false; + + virtualisation.fileSystems = lib.mkForce { + "/" = { + fsType = "tmpfs"; + options = [ "mode=0755" ]; + }; + + "/nix/store" = { + device = "/dev/disk/by-partlabel/${storePartitionLabel}"; + fsType = "erofs"; # Saves ~250MiB over ext4 + }; + }; + + image.repart = { + name = "bashless-image"; + mkfsOptions = { + erofs = [ "-z lz4" ]; # Saves ~150MiB over no compression + }; + partitions = { + "esp" = { + contents = { + "/EFI/BOOT/BOOT${lib.toUpper config.nixpkgs.hostPlatform.efiArch}.EFI".source = + "${config.system.build.uki}/${config.system.boot.loader.ukiFile}"; + }; + repartConfig = { + Type = "esp"; + Format = "vfat"; + SizeMinBytes = if config.nixpkgs.hostPlatform.isx86_64 then "64M" else "96M"; + }; + }; + "root" = { + storePaths = [ config.system.build.toplevel ]; + nixStorePrefix = "/"; + repartConfig = { + Type = "linux-generic"; + Format = config.fileSystems."/nix/store".fsType; + Label = storePartitionLabel; + Minimize = "best"; + }; + }; + }; + }; + }; + + testScript = + { nodes, ... }: + '' + import os + import subprocess + import tempfile + + tmp_disk_image = tempfile.NamedTemporaryFile() + + subprocess.run([ + "${nodes.machine.virtualisation.qemu.package}/bin/qemu-img", + "create", + "-f", + "qcow2", + "-b", + "${nodes.machine.system.build.image}/${nodes.machine.image.fileName}", + "-F", + "raw", + tmp_disk_image.name, + ]) + + # Set NIX_DISK_IMAGE so that the qemu script finds the right disk image. + os.environ['NIX_DISK_IMAGE'] = tmp_disk_image.name + + machine.start() + machine.wait_for_console_text("Startup finished.") + ''; +} diff --git a/nixos/tests/activation/bashless.nix b/nixos/tests/activation/bashless.nix new file mode 100644 index 000000000000..06028a81db30 --- /dev/null +++ b/nixos/tests/activation/bashless.nix @@ -0,0 +1,50 @@ +# This is a smoke test that tests that basic functionality is still available +# with the bashless profile. For this, however, we have to re-enable bash. + +{ lib, ... }: + +{ + + name = "activation-bashless"; + + meta.maintainers = with lib.maintainers; [ nikstur ]; + + nodes.machine = + { pkgs, modulesPath, ... }: + { + imports = [ "${modulesPath}/profiles/bashless.nix" ]; + + # Forcibly re-set options that would normally be set by the bashless + # profile but that we have to re-enable to make the test instrumentation + # work. + environment.binsh = lib.mkForce null; + boot.initrd.systemd.shell.enable = false; + + # This ensures that we only have the store paths of our closure in the + # in the guest. This is necessary so we can grep in the store. + virtualisation.mountHostNixStore = false; + virtualisation.useNixStoreImage = true; + + # Re-enable just enough of a normal NixOS system to be able to run tests + programs.bash.enable = true; + environment.shell.enable = true; + environment.systemPackages = [ + pkgs.coreutils + pkgs.gnugrep + ]; + + # Unset the regex because the tests instrumentation needs bash. + system.forbiddenDependenciesRegexes = lib.mkForce [ ]; + }; + + testScript = '' + machine.wait_for_unit("multi-user.target") + + with subtest("/bin/sh doesn't exist"): + machine.fail("stat /bin/sh") + + bash_store_paths = machine.succeed("ls /nix/store | grep bash || true") + print(bash_store_paths) + ''; + +} diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index e8d95d00a74d..3731a0e29213 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -186,6 +186,9 @@ in acme = import ./acme/default.nix { inherit runTest; }; acme-dns = runTest ./acme-dns.nix; activation = pkgs.callPackage ../modules/system/activation/test.nix { }; + activation-bashless = runTest ./activation/bashless.nix; + activation-bashless-closure = pkgs.callPackage ./activation/bashless-closure.nix { }; + activation-bashless-image = runTest ./activation/bashless-image.nix; activation-etc-overlay-immutable = runTest ./activation/etc-overlay-immutable.nix; activation-etc-overlay-mutable = runTest ./activation/etc-overlay-mutable.nix; activation-lib = pkgs.callPackage ../modules/system/activation/lib/test.nix { }; diff --git a/pkgs/by-name/ni/nixos-rebuild-ng/src/nixos_rebuild/__init__.py b/pkgs/by-name/ni/nixos-rebuild-ng/src/nixos_rebuild/__init__.py index 78f30989ba02..6d7ad01baebd 100644 --- a/pkgs/by-name/ni/nixos-rebuild-ng/src/nixos_rebuild/__init__.py +++ b/pkgs/by-name/ni/nixos-rebuild-ng/src/nixos_rebuild/__init__.py @@ -1,6 +1,5 @@ import argparse import logging -import os import sys from subprocess import CalledProcessError, run from typing import Final, assert_never @@ -290,12 +289,7 @@ def execute(argv: list[str]) -> None: # Re-exec to a newer version of the script before building to ensure we get # the latest fixes - if ( - WITH_REEXEC - and can_run - and not args.no_reexec - and not os.environ.get("_NIXOS_REBUILD_REEXEC") - ): + if WITH_REEXEC and can_run and not args.no_reexec: services.reexec(argv, args, build_flags, flake_build_flags) profile = Profile.from_arg(args.profile_name) diff --git a/pkgs/by-name/ni/nixos-rebuild-ng/src/nixos_rebuild/services.py b/pkgs/by-name/ni/nixos-rebuild-ng/src/nixos_rebuild/services.py index 0e47f5f0cd50..b145f735c283 100644 --- a/pkgs/by-name/ni/nixos-rebuild-ng/src/nixos_rebuild/services.py +++ b/pkgs/by-name/ni/nixos-rebuild-ng/src/nixos_rebuild/services.py @@ -4,7 +4,6 @@ import logging import os import sys from pathlib import Path -from subprocess import CalledProcessError from typing import Final from . import nix, tmpdir @@ -14,6 +13,7 @@ from .process import Remote, cleanup_ssh from .utils import Args, tabulate NIXOS_REBUILD_ATTR: Final = "config.system.build.nixos-rebuild" +NIXOS_REBUILD_REEXEC_ENV: Final = "_NIXOS_REBUILD_REEXEC" logger: Final = logging.getLogger(__name__) logger.setLevel(logging.INFO) @@ -25,27 +25,26 @@ def reexec( build_flags: Args, flake_build_flags: Args, ) -> None: + if os.environ.get(NIXOS_REBUILD_REEXEC_ENV): + return + drv = None - try: - # Parsing the args here but ignore ask_sudo_password since it is not - # needed and we would end up asking sudo password twice - if flake := Flake.from_arg(args.flake, Remote.from_arg(args.target_host, None)): - drv = nix.build_flake( - NIXOS_REBUILD_ATTR, - flake, - flake_build_flags | {"no_link": True}, - ) - else: - build_attr = BuildAttr.from_arg(args.attr, args.file) - drv = nix.build( - NIXOS_REBUILD_ATTR, - build_attr, - build_flags | {"no_out_link": True}, - ) - except CalledProcessError: - logger.warning( - "could not build a newer version of nixos-rebuild, using current version", - exc_info=logger.isEnabledFor(logging.DEBUG), + # Parsing the args here but ignore ask_sudo_password since it is not + # needed and we would end up asking sudo password twice + if flake := Flake.from_arg( + args.flake, Remote.from_arg(args.target_host, ask_sudo_password=None) + ): + drv = nix.build_flake( + NIXOS_REBUILD_ATTR, + flake, + flake_build_flags | {"no_link": True}, + ) + else: + build_attr = BuildAttr.from_arg(args.attr, args.file) + drv = nix.build( + NIXOS_REBUILD_ATTR, + build_attr, + build_flags | {"no_out_link": True}, ) if drv: @@ -62,7 +61,7 @@ def reexec( cleanup_ssh() tmpdir.TMPDIR.cleanup() try: - os.execve(new, argv, os.environ | {"_NIXOS_REBUILD_REEXEC": "1"}) + os.execve(new, argv, os.environ | {NIXOS_REBUILD_REEXEC_ENV: "1"}) except Exception: # Possible errors that we can have here: # - Missing the binary @@ -74,7 +73,7 @@ def reexec( ) # We already run clean-up, let's re-exec in the current version # to avoid issues - os.execve(current, argv, os.environ | {"_NIXOS_REBUILD_REEXEC": "1"}) + os.execve(current, argv, os.environ | {NIXOS_REBUILD_REEXEC_ENV: "1"}) def _validate_image_variant(image_variant: str, variants: ImageVariants) -> None: diff --git a/pkgs/by-name/ni/nixos-rebuild-ng/src/tests/test_services.py b/pkgs/by-name/ni/nixos-rebuild-ng/src/tests/test_services.py index 15907f21fe3c..655c127c2744 100644 --- a/pkgs/by-name/ni/nixos-rebuild-ng/src/tests/test_services.py +++ b/pkgs/by-name/ni/nixos-rebuild-ng/src/tests/test_services.py @@ -39,7 +39,7 @@ def test_reexec(mock_build: Mock, mock_execve: Mock, monkeypatch: MonkeyPatch) - mock_execve.assert_called_once_with( Path("/path/new/bin/nixos-rebuild-ng"), ["/path/bin/nixos-rebuild-ng", "switch", "--no-flake"], - {"_NIXOS_REBUILD_REEXEC": "1"}, + {s.NIXOS_REBUILD_REEXEC_ENV: "1"}, ) mock_execve.reset_mock() @@ -50,7 +50,7 @@ def test_reexec(mock_build: Mock, mock_execve: Mock, monkeypatch: MonkeyPatch) - mock_execve.assert_any_call( Path("/path/bin/nixos-rebuild-ng"), ["/path/bin/nixos-rebuild-ng", "switch", "--no-flake"], - {"_NIXOS_REBUILD_REEXEC": "1"}, + {s.NIXOS_REBUILD_REEXEC_ENV: "1"}, ) @@ -81,7 +81,7 @@ def test_reexec_flake( mock_execve.assert_called_once_with( Path("/path/new/bin/nixos-rebuild-ng"), ["/path/bin/nixos-rebuild-ng", "switch", "--flake"], - {"_NIXOS_REBUILD_REEXEC": "1"}, + {s.NIXOS_REBUILD_REEXEC_ENV: "1"}, ) mock_execve.reset_mock() @@ -92,5 +92,18 @@ def test_reexec_flake( mock_execve.assert_any_call( Path("/path/bin/nixos-rebuild-ng"), ["/path/bin/nixos-rebuild-ng", "switch", "--flake"], - {"_NIXOS_REBUILD_REEXEC": "1"}, + {s.NIXOS_REBUILD_REEXEC_ENV: "1"}, ) + + +@patch.dict(os.environ, {s.NIXOS_REBUILD_REEXEC_ENV: "1"}, clear=True) +@patch("os.execve", autospec=True) +@patch(get_qualified_name(s.nix.build_flake), autospec=True) +def test_reexec_skip_if_already_reexec(mock_build: Mock, mock_execve: Mock) -> None: + argv = ["/path/bin/nixos-rebuild-ng", "switch", "--flake"] + args, _ = n.parse_args(argv) + mock_build.return_value = Path("/path") + + s.reexec(argv, args, {"build": True}, {"flake": True}) + mock_build.assert_not_called() + mock_execve.assert_not_called() diff --git a/pkgs/by-name/ru/ruff/package.nix b/pkgs/by-name/ru/ruff/package.nix index 46cc44236a8f..91f01c964b9b 100644 --- a/pkgs/by-name/ru/ruff/package.nix +++ b/pkgs/by-name/ru/ruff/package.nix @@ -16,18 +16,18 @@ rustPlatform.buildRustPackage (finalAttrs: { pname = "ruff"; - version = "0.13.1"; + version = "0.14.0"; src = fetchFromGitHub { owner = "astral-sh"; repo = "ruff"; tag = finalAttrs.version; - hash = "sha256-dCxCpJLG2qjfrMxDJOL4rCwdVYfrz3P+4kDQ9d9Mbus="; + hash = "sha256-Vueccz5lkUTdgqqZl/+PB0kVYezvPKIVxee8EJYcz4g="; }; cargoBuildFlags = [ "--package=ruff" ]; - cargoHash = "sha256-WtRryq8bmKfL3EL2kRFFokmG2f0lnS6zRMbUzGeYLDM="; + cargoHash = "sha256-bnSTiQzlZrS2tqQiRHr6gNDq40Naqxrxcyc8zcVlt7A="; nativeBuildInputs = [ installShellFiles ]; diff --git a/pkgs/os-specific/linux/kernel/kernels-org.json b/pkgs/os-specific/linux/kernel/kernels-org.json index 8bd7fe2a01cf..ba339f14a98c 100644 --- a/pkgs/os-specific/linux/kernel/kernels-org.json +++ b/pkgs/os-specific/linux/kernel/kernels-org.json @@ -25,23 +25,23 @@ "lts": true }, "6.6": { - "version": "6.6.110", - "hash": "sha256:07gv37ralrhf709plqj1hzk1adwilh6znmay6agpbf23anphvwhv", + "version": "6.6.111", + "hash": "sha256:1is6nrm5x54bw8zn8l5akp8ign185i19biks442yynfn63hp1i04", "lts": true }, "6.12": { - "version": "6.12.51", - "hash": "sha256:08bj3b6a6jwvrpjl5sxvmzwwnc00clq98rjwb61fznd7khaasm9d", + "version": "6.12.52", + "hash": "sha256:1ccyd9h9i3xia1gqq0mggis5yv04c9ys44xp707wfcm0f3v0r1dl", "lts": true }, "6.16": { - "version": "6.16.11", - "hash": "sha256:0yxsinhly689327jbvwm2nfr6cx7ynj9sd87a9var1rx8l64yc2z", + "version": "6.16.12", + "hash": "sha256:0vm257d76hmimnac8hzg66gd1mdg330sai39lywfn4m9bjydx93w", "lts": false }, "6.17": { - "version": "6.17.1", - "hash": "sha256:182d9xf7j0n4cn61rsqs87al9xc83rawri8p3yk246a984zvwgd5", + "version": "6.17.2", + "hash": "sha256:0zzmcjkmxmcn45y20g8hz7dxs355rmczp9k8vjwc3xb5a03cpszx", "lts": false } }