• v1.6 c5d935421f

    v1.6 Stable

    pepper released this 2026-07-16 01:04:26 +00:00 | 20 commits to main since this release

    Sécurité

    • swag/conf/crowdsec/crowdsec-nginx-bouncer.conf en 644 — régénéré à chaque démarrage par le mod linuxserver/mods:swag-crowdsec, contient l'API_KEY du bouncer CrowdSec en clair, lisible par tout compte local. Découvert en creusant pourquoi un script custom-cont-init.d censé corriger ça au démarrage ne semblait avoir aucun effet.
    • 🔴 Bug latent découvert par ricochet : les scripts swag/conf/custom-cont-init.d/* n'ont jamais été exécutés depuis leur création — le script d'init du base-image LSIO (/etc/s6-overlay/s6-rc.d/init-custom-files/run) a le chemin SCRIPTS_DIR="/custom-cont-init.d" codé en dur (racine du conteneur), alors que le compose ne montait que ./swag/conf:/config → les scripts atterrissaient à /config/custom-cont-init.d, jamais scanné. Log confirmé : [custom-init] No custom files found, skipping.... Ça concernait aussi 60-fix-propagation (créé le 2026-07-04, jamais vraiment actif malgré le CHANGELOG antérieur qui le présentait comme fonctionnel). Fix en deux temps :
      1. Script 65-fix-crowdsec-perms ajouté (chmod 600 sur le conf bouncer, même pattern que 60-fix-propagation).
      2. Montage dédié /custom-cont-init.d:ro ajouté — mais un premier essai en le pointant sur ./swag/conf/custom-cont-init.d s'est révélé insuffisant : ce chemin restait aussi accessible en écriture via le mount /config (chevauchement, même inode des deux côtés), et une étape tardive du boot LSIO réinitialise silencieusement l'ownership à PUID:PGID sur tout /config — un chown root:root posé juste avant se faisait donc défaire après coup (le bandeau d'avertissement not owned by root du base-image disparaissait du log sans que la protection tienne réellement). Fix définitif : nouveau dossier swag/custom-cont-init.d/ hors de swag/conf/ (donc hors du mount RW), scripts copiés là en root:root 755, montage docker-compose.yml repointé dessus. Les fichiers originaux dans swag/conf/custom-cont-init.d/ renommés en .old (conservés, non exécutés) plutôt que supprimés.
        Validé : stat sur l'hôte confirme root:root maintenu après un boot complet (contrairement à la première tentative) ; logs complets sans bandeau d'avertissement ; les deux scripts exited 0 ; crowdsec-nginx-bouncer.conf repassé en 600 à chaque démarrage ; 20/20 conteneurs healthy ; whitelist qBittorrent retestée (nextcloud403, swag200, cf. entrée suivante) ; 6 sous-domaines HTTPS publics répondent normalement. Effet de bord observé et sans gravité : 60-fix-propagation relance désormais un certbot certonly complet (incluant les 120s d'attente DNS) à chaque redémarrage de swag — même date d'expiration de certificat obtenue à 3 reprises rapprochées lors des tests, donc pas de nouvelle émission distincte ni de risque de rate-limit Let's Encrypt observé, mais à surveiller si swag redémarre très fréquemment.
    • 🔴 qBittorrent : la whitelist de bypass d'authentification WebUI couvrait tout le réseau swag (172.22.0.0/24), pas seulement SWAGWebUI\AuthSubnetWhitelistEnabled=true + WebUI\AuthSubnetWhitelist=172.22.0.0/24 dispensait de login toute requête provenant de n'importe quelle IP de ce /24. Or 7 autres conteneurs partagent ce réseau (nextcloud, forgejo, grafana, jellyfin, authentik-server, wireguard, swag lui-même) — la protection Authentik (forward-auth @goauthentik_proxy_signin) n'étant appliquée que côté nginx dans SWAG, pas par qBittorrent, n'importe lequel de ces conteneurs compromis (RCE applicative) pouvait joindre directement l'IP de qBittorrent sur le réseau docker et administrer entièrement le client torrent sans aucune authentification — y compris sa fonctionnalité "exécuter une commande externe" (exécution de code dans le conteneur). Fix : IP fixe pour swag sur le réseau swag (ipv4_address: 172.22.0.5 dans docker-compose.yml, backup.sh ne fait pas tourner down/up en automatique donc pas de risque de dérive d'IP) + whitelist qBittorrent réduite à 172.22.0.5/32. Édition du fichier de conf faite pendant que le conteneur était arrêté (évite qu'il réécrive l'ancienne valeur en mémoire au shutdown). Validé par cycle down -v && up -d complet (20/20 conteneurs healthy) + test direct : requête depuis nextcloud vers l'API qBittorrent → 403 Forbidden (bloqué, comme attendu) ; même requête depuis swag200 (flux légitime intact) ; les 6 sous-domaines HTTPS publics répondent normalement (302 SSO ou 200). Seules anomalies de logs : résolutions DNS transitoires de forgejo au tout début du démarrage de renovate (auto-résolues, run Renovate terminé avec succès juste après) — sans rapport avec ce fix.
    • sshd_config : AllowUsers free debianAllowUsers debianfree ne correspond à aucun compte local (getent passwd free : absent). C'est un résidu de config (le nom coïncide avec le compte free utilisé côté serveur distant pour le montage sshfs hors-site de backup.sh, mais ce montage est sortant — ce serveur se connecte vers le distant en tant que free, aucun rapport avec les connexions SSH entrantes gérées par AllowUsers ici). Risque : dormant tant que free n'existe pas localement, mais si un compte free était recréé un jour sans qu'on y pense, il hériterait automatiquement de l'autorisation SSH. Atténué en plus par PasswordAuthentication no (clé obligatoire). Backup de sshd_config fait avant modif, syntaxe validée (sshd -t), rechargé à chaud (systemctl reload sshd, pas de coupure de session).
    Downloads