NixDaemon

NixOS pentest workstation as one flake — IceBreaker's successor
git clone https://git.daemon-sec.xyz/NixDaemon.git
Log | Files | Refs | README

_overlay.nix (4284B)


      1 # modules/features/pentest/_overlay.nix — fixes this toolkit needs from nixpkgs
      2 # itself. Applied to both the system (nixpkgs.overlays) and the flake's
      3 # perSystem pkgs, so `nix flake check` and `nh os switch` agree.
      4 #
      5 # Keep every entry justified and dated: an overlay is a fork, and each one is a
      6 # thing to delete when nixpkgs catches up.
      7 final: prev:
      8 {
      9   # 2026-10-10 — ligolo-ng 0.9.1 -> 0.9.2 (upstream's current release). Done
     10   # here, for the whole system, rather than only in payloads.nix: the proxy
     11   # you run (pivot.nix) and the agents you drop (payloads.nix) must be the
     12   # same version, and an overlay is the one place both read. Same go.sum, so
     13   # the vendorHash is unchanged. Delete when nixpkgs reaches 0.9.2.
     14   ligolo-ng = prev.ligolo-ng.overrideAttrs (_: {
     15     version = "0.9.2";
     16     src = prev.fetchFromGitHub {
     17       owner = "nicocha30";
     18       repo = "ligolo-ng";
     19       tag = "v0.9.2";
     20       hash = "sha256-y7q4XhZpmzxQM/fKd3ReRxjMGtda9GUJPsT5az6G784=";
     21     };
     22   });
     23 
     24   # 2026-10-08 — anyio 4.14.2 fails 5 of 2596 tests on python 3.12 in nixpkgs:
     25   # tests/streams/test_tls.py::test_tls_connectable raises
     26   # ValueError('server_hostname can only be specified in client mode') on every
     27   # backend, and TestDropwhile::test_checkpoints_empty_results trips unraisable
     28   # warnings under uvloop. Both are test-harness problems, not library faults.
     29   #
     30   # Without this netexec cannot build at all — netexec -> certipy-ad/proxy-py ->
     31   # httpx -> httpcore -> anyio — and `nxc` is the most used tool in CPTS. The
     32   # deselect is narrow and named rather than a blanket doCheck = false, which
     33   # would hide a real regression.
     34   #
     35   # Two things about the mechanism, both learned the hard way:
     36   #
     37   #  1. It must be pythonPackagesExtensions, not
     38   #     `python312.override { packageOverrides = ... }`. netexec's own
     39   #     package.nix does its own `python312.override { packageOverrides = ... }`
     40   #     to pin impacket, and that REPLACES an overlay's packageOverrides rather
     41   #     than composing with it — the fix vanished silently and netexec's
     42   #     derivation came out byte-identical. Extensions are applied wherever a
     43   #     python package set is constructed, so they survive that.
     44   #
     45   #  2. It must be scoped to 3.12. An unscoped extension applies to every
     46   #     python set and invalidates the binary cache for everything downstream of
     47   #     anyio in all of them: the first attempt had python3.14-twisted
     48   #     rebuilding from source with its full test suite for no reason. Only
     49   #     3.12's anyio is broken; 3.14 (the default, used by impacket) is fine.
     50   pythonPackagesExtensions = prev.pythonPackagesExtensions ++ [
     51     # 2026-10-08 — masky dies the moment you run it with
     52     # "ModuleNotFoundError: No module named 'pkg_resources'". Installing
     53     # setuptools does NOT fix it: setuptools 83 (this nixpkgs) removed
     54     # pkg_resources altogether, so the module simply no longer exists for any
     55     # python here. masky has exactly one use of it — `resource_filename` to
     56     # locate its bundled Masky.exe — so it is rewritten to the importlib
     57     # equivalent, which is what upstream would do.
     58     #
     59     # Caught by the smokeBins run in _sets.nix. `command -v masky` always
     60     # succeeded, which is precisely why that run now exists.
     61     # Narrow: touches masky only.
     62     (
     63       pyfinal: pyprev:
     64       prev.lib.optionalAttrs (pyprev ? masky) {
     65         masky = pyprev.masky.overridePythonAttrs (o: {
     66           postPatch = (o.postPatch or "") + ''
     67             substituteInPlace masky/lib/smb.py \
     68               --replace-fail \
     69                 'from pkg_resources import resource_filename' \
     70                 'from importlib.resources import files as _ir_files' \
     71               --replace-fail \
     72                 'resource_filename("masky.bin", "Masky.exe")' \
     73                 'str(_ir_files("masky.bin") / "Masky.exe")'
     74           '';
     75         });
     76       }
     77     )
     78     (
     79       pyfinal: pyprev:
     80       prev.lib.optionalAttrs (pyprev ? anyio && (pyprev.python.pythonVersion or "") == "3.12") {
     81         anyio = pyprev.anyio.overridePythonAttrs (o: {
     82           disabledTests = (o.disabledTests or [ ]) ++ [
     83             "test_tls_connectable"
     84             "test_checkpoints_empty_results"
     85           ];
     86         });
     87       }
     88     )
     89   ];
     90 }