Security Finding
Severity: low
Type: unsafe-pattern (hardcoded credential, latent)
files/kde-linux-system/generate-initramfs/modules/50-repart/gen-recovery-key.sh emits a fixed string as the disk-encryption recovery passphrase:
#!/bin/bash
set -eu
umask 0077
if [[ "$#" -ge 1 ]]; then
exec >"${1}"
fi
echo -n "ihavenotsetarecoverykey"
It is wired to the encryption path:
50-repart/enable-encryption.service (initramfs, ConditionSecurity=tpm2) runs /usr/bin/gen-recovery-key /run/recovery-password
50-repart/gnomeos.conf overrides systemd-repart.service with --key-file=/run/recovery-password
files/secure-repart-config/main/50-root.conf declares Encrypt=key-file+tpm2 for the root partition
So on any system provisioned through this path, systemd-repart creates the root LUKS2 volume with a keyslot holding a constant, publicly readable passphrase, plus a TPM2 enrollment. The TPM2 binding does not help: the passphrase keyslot unlocks the volume on its own, from any machine.
This is not reachable in the images this repository currently publishes. The module's install() is gated:
install() {
if [ "${INITRD_MODE-sysupdate}" != sysupdate ]; then
exit 0
fi
and the only element that runs generate-initramfs — elements/oci/initramfs.bst — sets INITRD_MODE: oci, so 50-repart (and with it gen-recovery-key, enable-encryption.service and the repart drop-in) is never installed into the shipped initramfs. Filed as low for that reason, not because the constant is harmless.
Impact
The failure mode is the fallback direction of that gate: ${INITRD_MODE-sysupdate} defaults to the vulnerable mode. Any future initramfs build that forgets to set INITRD_MODE, or that deliberately selects sysupdate, silently ships full-disk encryption whose recovery keyslot is a string published in this repository. Every machine installed that way shares it, and anyone holding the disk — a stolen laptop, a resold drive, a disk image — unlocks it. Nothing at runtime signals the difference from real encryption.
The string is upstream GNOME OS's placeholder, so the bug is inherited rather than introduced here, but this repository vendors the module and would ship the result.
Recommendation
- Make the helper fail closed instead of emitting a constant — generate a real key, e.g.:
dd if=/dev/urandom bs=32 count=1 status=none | basenc --base32 | head -c 55
(dd and basenc are already installed by module.sh for exactly this kind of use), and surface the generated passphrase to the user through first-boot setup so it can be recorded. If no such flow exists yet, exit 1 is a better outcome than encrypting with a known key.
-
Invert the gate so the encrypting mode is opt-in: if [ "${INITRD_MODE:-oci}" != sysupdate ]; then exit 0; fi, and set INITRD_MODE explicitly at every call site.
-
If the sysupdate/repart install path is not planned for Tromsø, drop the 50-repart module and files/secure-repart-config/ rather than carrying a disabled encryption path that looks functional.
Filed by sec-check agent (ACMM L6 — full mode)
— hive: agent=sec-check backend=claude model=claude-opus-5 claude=2.1.226
Security Finding
Severity: low
Type: unsafe-pattern (hardcoded credential, latent)
files/kde-linux-system/generate-initramfs/modules/50-repart/gen-recovery-key.shemits a fixed string as the disk-encryption recovery passphrase:It is wired to the encryption path:
50-repart/enable-encryption.service(initramfs,ConditionSecurity=tpm2) runs/usr/bin/gen-recovery-key /run/recovery-password50-repart/gnomeos.confoverridessystemd-repart.servicewith--key-file=/run/recovery-passwordfiles/secure-repart-config/main/50-root.confdeclaresEncrypt=key-file+tpm2for the root partitionSo on any system provisioned through this path,
systemd-repartcreates the root LUKS2 volume with a keyslot holding a constant, publicly readable passphrase, plus a TPM2 enrollment. The TPM2 binding does not help: the passphrase keyslot unlocks the volume on its own, from any machine.This is not reachable in the images this repository currently publishes. The module's
install()is gated:and the only element that runs
generate-initramfs—elements/oci/initramfs.bst— setsINITRD_MODE: oci, so50-repart(and with itgen-recovery-key,enable-encryption.serviceand the repart drop-in) is never installed into the shipped initramfs. Filed as low for that reason, not because the constant is harmless.Impact
The failure mode is the fallback direction of that gate:
${INITRD_MODE-sysupdate}defaults to the vulnerable mode. Any future initramfs build that forgets to setINITRD_MODE, or that deliberately selectssysupdate, silently ships full-disk encryption whose recovery keyslot is a string published in this repository. Every machine installed that way shares it, and anyone holding the disk — a stolen laptop, a resold drive, a disk image — unlocks it. Nothing at runtime signals the difference from real encryption.The string is upstream GNOME OS's placeholder, so the bug is inherited rather than introduced here, but this repository vendors the module and would ship the result.
Recommendation
(
ddandbasencare already installed bymodule.shfor exactly this kind of use), and surface the generated passphrase to the user through first-boot setup so it can be recorded. If no such flow exists yet,exit 1is a better outcome than encrypting with a known key.Invert the gate so the encrypting mode is opt-in:
if [ "${INITRD_MODE:-oci}" != sysupdate ]; then exit 0; fi, and setINITRD_MODEexplicitly at every call site.If the
sysupdate/repart install path is not planned for Tromsø, drop the50-repartmodule andfiles/secure-repart-config/rather than carrying a disabled encryption path that looks functional.Filed by sec-check agent (ACMM L6 — full mode)
— hive: agent=sec-check backend=claude model=claude-opus-5 claude=2.1.226