bump deps, mitigate CA leakage

This commit is contained in:
Henry Hiles 2026-10-20 12:46:57 -04:00
commit ad5bfb2262
Signed by: Henry-Hiles
SSH key fingerprint: SHA256:VKQUdS31Q90KvX7EkKMHMBpUspcmItAh86a+v7PGiIs
5 changed files with 362 additions and 33 deletions

View file

@ -5,7 +5,7 @@
...
}:
let
s3Domain = "http://127.0.0.1${config.services.minio.listenAddress}";
s3Domain = "http://127.0.0.1${config.services.minio-vendored.listenAddress}";
cfg = config.services.lasuite-docs;
in
{
@ -76,7 +76,7 @@ in
environmentFile = config.age.secrets."lasuiteSecrets.age".path;
};
minio = {
minio-vendored = {
enable = true;
rootCredentialsFile = config.age.secrets."minioCredentials.age".path;
};
@ -135,5 +135,6 @@ in
nixpkgs.config.permittedInsecurePackages = [
"minio-2025-10-15T17-29-55Z"
"minio-client-2025-08-13T08-35-41Z"
];
}

View file

@ -0,0 +1,317 @@
# MinIO package and module, vendored from nixpkgs 6510408d147d8c5e6d76043e899e9251756f6a75
# (nixos/modules/services/web-servers/minio.nix and pkgs/by-name/mi/minio/package.nix), since
# both were removed upstream because MinIO was abandoned. Only here until lasuite-docs is
# migrated to another S3 server.
#
# Changes from upstream:
# - The option is `services.minio-vendored`, since nixpkgs still reserves `services.minio` to
# show a removal message. The unit, user and paths are unchanged, so existing data keeps working.
# - The package is defined here, as `pkgs.minio` now throws, and without `passthru.tests`, as
# `nixosTests.minio` was removed too.
{
config,
lib,
pkgs,
...
}:
with lib;
let
cfg = config.services.minio-vendored;
minio = pkgs.callPackage (
{
lib,
buildGoModule,
fetchFromGitHub,
}:
let
# The web client verifies, that the server version is a valid datetime string:
# https://github.com/minio/minio/blob/3a0e7347cad25c60b2e51ff3194588b34d9e424c/browser/app/js/web.js#L51-L53
#
# Example:
# versionToTimestamp "2021-04-22T15-44-28Z"
# => "2021-04-22T15:44:28Z"
versionToTimestamp =
version:
let
splitTS = builtins.elemAt (builtins.split "(.*)(T.*)" version) 1;
in
builtins.concatStringsSep "" [
(builtins.elemAt splitTS 0)
(builtins.replaceStrings [ "-" ] [ ":" ] (builtins.elemAt splitTS 1))
];
# CopyrightYear will be printed to the CLI UI.
# Example:
# versionToYear "2021-04-22T15-44-28Z"
# => "2021"
versionToYear = version: builtins.elemAt (lib.splitString "-" version) 0;
in
buildGoModule (finalAttrs: {
pname = "minio";
version = "2025-10-15T17-29-55Z";
src = fetchFromGitHub {
owner = "minio";
repo = "minio";
rev = "RELEASE.${finalAttrs.version}";
hash = "sha256-HbjmCJYkWyRRHKriLP6QohaXYLk3QEVfi32Krq3ujjo=";
};
vendorHash = "sha256-BFnTJE9QFWmPsx90hDTG8MusdnwaBPYJxM5bCFk3hew=";
doCheck = false;
subPackages = [ "." ];
env.CGO_ENABLED = 0;
tags = [ "kqueue" ];
ldflags =
let
t = "github.com/minio/minio/cmd";
in
[
"-s"
"-w"
"-X ${t}.Version=${versionToTimestamp finalAttrs.version}"
"-X ${t}.CopyrightYear=${versionToYear finalAttrs.version}"
"-X ${t}.ReleaseTag=RELEASE.${finalAttrs.version}"
"-X ${t}.CommitID=${finalAttrs.src.rev}"
];
meta = {
homepage = "https://www.minio.io/";
description = "S3-compatible object storage server";
changelog = "https://github.com/minio/minio/releases/tag/RELEASE.${finalAttrs.version}";
maintainers = with lib.maintainers; [
bachp
ryan4yin
];
license = lib.licenses.agpl3Plus;
mainProgram = "minio";
knownVulnerabilities = [
"CVE-2026-40344: MinIO has an Unauthenticated Object Write via Missing Signature Verification in Unsigned-Trailer Uploads"
"CVE-2026-41145: Unauthenticated Object Write via Query-String Credential Signature Bypass in Unsigned-Trailer Uploads"
"CVE-2026-33322: JWT Algorithm Confusion in OIDC Authentication"
"CVE-2026-33419: LDAP login brute-force via user enumeration and missing rate limit"
"CVE-2026-34204: SSE Metadata Injection via Replication Headers"
"CVE-2026-39414: DoS via Unbounded Memory Allocation in S3 Select CSV Parsing"
"minio has been abandoned by upstream and security issues won't be fixed. Users should migrate to alternatives such as Garage, SeaweedFS, or Ceph. S3-compatible clients such as rclone can be used to move data."
];
};
})
) { };
legacyCredentials =
cfg:
pkgs.writeText "minio-legacy-credentials" ''
MINIO_ROOT_USER=${cfg.accessKey}
MINIO_ROOT_PASSWORD=${cfg.secretKey}
'';
in
{
options.services.minio-vendored = {
enable = mkEnableOption "Minio Object Storage";
listenAddress = mkOption {
default = ":9000";
type = types.str;
description = "IP address and port of the server.";
};
consoleAddress = mkOption {
default = ":9001";
type = types.str;
description = "IP address and port of the web UI (console).";
};
dataDir = mkOption {
default = [ "/var/lib/minio/data" ];
type = types.listOf (types.either types.path types.str);
description = "The list of data directories or nodes for storing the objects. Use one path for regular operation and the minimum of 4 endpoints for Erasure Code mode.";
};
configDir = mkOption {
default = "/var/lib/minio/config";
type = types.path;
description = "The config directory, for the access keys and other settings.";
};
certificatesDir = mkOption {
default = "/var/lib/minio/certs";
type = types.path;
description = "The directory where TLS certificates are stored.";
};
accessKey = mkOption {
default = "";
type = types.str;
description = ''
Access key of 5 to 20 characters in length that clients use to access the server.
This overrides the access key that is generated by minio on first startup and stored inside the
`configDir` directory.
'';
};
secretKey = mkOption {
default = "";
type = types.str;
description = ''
Specify the Secret key of 8 to 40 characters in length that clients use to access the server.
This overrides the secret key that is generated by minio on first startup and stored inside the
`configDir` directory.
'';
};
rootCredentialsFile = mkOption {
type = types.nullOr types.path;
default = null;
description = ''
File containing the MINIO_ROOT_USER, default is "minioadmin", and
MINIO_ROOT_PASSWORD (length >= 8), default is "minioadmin"; in the format of
an EnvironmentFile=, as described by {manpage}`systemd.exec(5)`.
'';
example = "/etc/nixos/minio-root-credentials";
};
region = mkOption {
default = "us-east-1";
type = types.str;
description = ''
The physical location of the server. By default it is set to us-east-1, which is same as AWS S3's and Minio's default region.
'';
};
browser = mkOption {
default = true;
type = types.bool;
description = "Enable or disable access to web UI.";
};
package = mkOption {
type = types.package;
default = minio;
defaultText = literalMD "MinIO 2025-10-15T17-29-55Z, vendored above";
description = "The MinIO package to use.";
};
};
config = mkIf cfg.enable {
warnings =
optional ((cfg.accessKey != "") || (cfg.secretKey != ""))
"services.minio-vendored.`accessKey` and services.minio-vendored.`secretKey` are deprecated, please use services.minio-vendored.`rootCredentialsFile` instead.";
systemd = lib.mkMerge [
{
tmpfiles.rules = [
"d '${cfg.configDir}' - minio minio - -"
]
++ (map (x: "d '" + x + "' - minio minio - - ") (builtins.filter lib.types.path.check cfg.dataDir));
services.minio = {
description = "Minio Object Storage";
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
ExecStart = "${cfg.package}/bin/minio server --json --address ${cfg.listenAddress} --console-address ${cfg.consoleAddress} --config-dir=${cfg.configDir} --certs-dir=${cfg.certificatesDir} ${toString cfg.dataDir}";
Type = "simple";
User = "minio";
Group = "minio";
LimitNOFILE = 65536;
EnvironmentFile =
if (cfg.rootCredentialsFile != null) then
cfg.rootCredentialsFile
else if ((cfg.accessKey != "") || (cfg.secretKey != "")) then
(legacyCredentials cfg)
else
null;
# hardening
DevicePolicy = "closed";
CapabilityBoundingSet = "";
RestrictAddressFamilies = [
"AF_INET"
"AF_INET6"
"AF_NETLINK"
"AF_UNIX"
];
DeviceAllow = "";
NoNewPrivileges = true;
PrivateDevices = true;
PrivateMounts = true;
PrivateTmp = true;
PrivateUsers = true;
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
MemoryDenyWriteExecute = true;
LockPersonality = true;
RemoveIPC = true;
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
SystemCallArchitectures = "native";
SystemCallFilter = [
"@system-service"
"~@privileged"
];
ProtectProc = "invisible";
ProtectHostname = true;
UMask = "0077";
# minio opens /proc/mounts on startup
ProcSubset = "all";
};
environment = {
MINIO_REGION = "${cfg.region}";
MINIO_BROWSER = "${if cfg.browser then "on" else "off"}";
};
};
}
(lib.mkIf (cfg.rootCredentialsFile != null) {
# The service will fail if the credentials file is missing
services.minio.unitConfig.ConditionPathExists = cfg.rootCredentialsFile;
# The service will not restart if the credentials file has
# been changed. This can cause stale root credentials.
paths.minio-root-credentials = {
wantedBy = [ "multi-user.target" ];
pathConfig = {
PathChanged = [ cfg.rootCredentialsFile ];
Unit = "minio-restart.service";
};
};
services.minio-restart = {
description = "Restart MinIO";
script = ''
systemctl restart minio.service
'';
serviceConfig = {
Type = "oneshot";
Restart = "on-failure";
RestartSec = 5;
};
};
})
];
users.users.minio = {
group = "minio";
uid = config.ids.uids.minio;
};
users.groups.minio.gid = config.ids.uids.minio;
};
}

60
flake.lock generated
View file

@ -23,11 +23,11 @@
]
},
"locked": {
"lastModified": 1790734419,
"narHash": "sha256-n7wew722m1OTBT9DOIMxNX/NF4zfsSUABAO5eW3wikE=",
"lastModified": 1792507013,
"narHash": "sha256-8tKjSQajD3mUND1GaAuaWTcuyUpgcGsh5V+l4ibzC7U=",
"owner": "ryantm",
"repo": "agenix",
"rev": "3daa710894355fa2fad8243380af373a2b4046ef",
"rev": "5e5b88a0c8e56f291a108c2fe9934054d9745b2e",
"type": "github"
},
"original": {
@ -163,11 +163,11 @@
"treefmt-nix": "treefmt-nix"
},
"locked": {
"lastModified": 1792171958,
"narHash": "sha256-ZpJe7MK24KnEfpbC4IsKzl1MLusbcDB3PB1SaFd0GSI=",
"lastModified": 1792473472,
"narHash": "sha256-kGZbWSNyp7DWhSo1DmF83LVxp/Gp/4qHXuylJgE7UO4=",
"ref": "refs/heads/main",
"rev": "b0a5caf57606b34baa94afc5f348d0484f5c0f3b",
"revCount": 7962,
"rev": "2f93711a0969bb858fe5faa032c683096c82c333",
"revCount": 7964,
"type": "git",
"url": "https://forgejo.ellis.link/continuwuation/continuwuity"
},
@ -241,11 +241,11 @@
]
},
"locked": {
"lastModified": 1789770686,
"narHash": "sha256-uZkBR7yHdIKUFB5SZdfgh1qkGfI3XmYmI/lTiquxbck=",
"lastModified": 1792505528,
"narHash": "sha256-BsLGrgqKJg2o9IsjU4Xvzo8RZV9Fn1GajEasifBwqsI=",
"owner": "nix-community",
"repo": "disko",
"rev": "725ea35e410ad83be4931d1bff7e090eacaf3563",
"rev": "7fdf779611daf0e250889cb27e4f1f602147a8f2",
"type": "github"
},
"original": {
@ -306,11 +306,11 @@
"rust-overlay": []
},
"locked": {
"lastModified": 1792507568,
"narHash": "sha256-RGXq8SkxpxU0TaMk3oXbJ5SwkRDY90tvN2zIiofAVMQ=",
"lastModified": 1792509123,
"narHash": "sha256-beuuyEmQTfgLd7smvvSeVhsLF5wBgPnUeCeJpd2QD+M=",
"owner": "nferhat",
"repo": "fht-compositor",
"rev": "458dc48d96aa6d8aa0b834a8052f33c09700ffe8",
"rev": "a9b6a8cc2714288b3f5b2752ea7871eee21e927b",
"type": "github"
},
"original": {
@ -322,11 +322,11 @@
"firefox-gnome-theme": {
"flake": false,
"locked": {
"lastModified": 1791905368,
"narHash": "sha256-K8fIXFKovw6zOwWE96wKRyADLB+vIkf+rVGPUqdSd1g=",
"lastModified": 1792416163,
"narHash": "sha256-0M5/QfbfHwI7gP+q6IGdidxl5caGXMaEalNj2E2Rxyg=",
"owner": "rafaelmardojai",
"repo": "firefox-gnome-theme",
"rev": "6841588955c23c8fc0f3e067fe1a1009113f7fd2",
"rev": "fdc1af075073f93dc63e43b28a499b2251bcfcc2",
"type": "github"
},
"original": {
@ -724,11 +724,11 @@
]
},
"locked": {
"lastModified": 1792098797,
"narHash": "sha256-u4DIIZgznEGzByxXrxWCXK19VcMtTBmi/M9gZ7Jk9bM=",
"lastModified": 1792495086,
"narHash": "sha256-TyoYH983Nsc++1scw0SoOEKshPSJWJDxK7tTmuZ974M=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "640725978b99076e18e069f6e7d2959124584f8f",
"rev": "ec80131710bffcdf3b8498cf41f3a0579833b023",
"type": "github"
},
"original": {
@ -800,11 +800,11 @@
]
},
"locked": {
"lastModified": 1792268367,
"narHash": "sha256-CsB/G1ut2CossRJ2dWg1G/RI1DA6F2F/qUcYT3ovk6k=",
"lastModified": 1792459113,
"narHash": "sha256-boQ5vhKJyoQJsozBrFVTJGiKXxcApJnc0tPdwT5iBRo=",
"ref": "refs/heads/main",
"rev": "a6fe80fea294588fee8bfeb319bed70d2160bb8b",
"revCount": 1052,
"rev": "a2906746b9273f04833a1bdea36d8ffc87b2c2ec",
"revCount": 1066,
"submodules": true,
"type": "git",
"url": "https://git.federated.nexus/Nexus/nexus"
@ -1043,11 +1043,11 @@
},
"nixpkgs_2": {
"locked": {
"lastModified": 1791956154,
"narHash": "sha256-jBYGPi4udQ9uo4KQp9m2J0546nJVQitG15gvZSaVVAs=",
"lastModified": 1792210252,
"narHash": "sha256-Mh0PUaIv4nFY+8wAGonaEh8iBzwsmdNlwjVHmFg1Biw=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "55bfb4d7437bd4e09ab7cba58a43bd68eb310044",
"rev": "09063bd1f2b36fd9fd793c36dfade7bd40a93dfc",
"type": "github"
},
"original": {
@ -1213,11 +1213,11 @@
]
},
"locked": {
"lastModified": 1792276809,
"narHash": "sha256-ocLR3Nn5LaZflG1wZeslUwDt7Roh5kg9ZEQ9FTV13e4=",
"lastModified": 1792505713,
"narHash": "sha256-gYLowB8hLLje3rKZhLhB0VZhUqgOOgDG3HYYaWa+fUU=",
"ref": "refs/heads/main",
"rev": "0cb286a792f23f2506d5c973c074386f79d9a9f7",
"revCount": 6380,
"rev": "ef92a87d1ead6859518b532c5e4cd02e91046d99",
"revCount": 6528,
"type": "git",
"url": "https://git.sable.moe/SableClient/sable-next"
},

View file

@ -0,0 +1,11 @@
{
security.pki.caCertificateBlacklist = [
# CVE-2026-111943
"Comodo AAA Services root"
# https://hg-edge.mozilla.org/projects/nss/rev/26d38a0c3fb81e7fb2acedbaf4c42dd21dce0517
"emSign ECC Root CA - G3"
# https://hg-edge.mozilla.org/projects/nss/rev/8159223c48ceeb1273a1915bca95a517294ab0e0
"emSign Root CA - C1"
"emSign ECC Root CA - C3"
];
}

View file

@ -53,7 +53,7 @@
plugins = [
"github.com/ggicci/caddy-jwt@v1.3.0"
];
hash = "sha256-NagDw+U1aV+NgW+gx5Sr996ZUEHZefuFIfDPu2bsD0Q=";
hash = "sha256-59TJxJMOuVzS5H9jmo3+esDFP1HLI1ov+BGC5ozgDuA=";
};
globalConfig = ''