🕵️ SicherheitslückenHak5: Hackers Just Poisoned the Rust Supply Chain | Threat Wire(01.09.2026 um 14:00 Uhr)
🕵️ SicherheitslückenHak5: Hackers Found a Way Into Humanoid Robots | Threat Wire(04.09.2026 um 15:04 Uhr)
🔧 AI Nachrichten Bits und so #1021 (Passwort für Laufwerk)(31.08.2026 um 22:15 Uhr)
🔧 AI Nachrichten Bits und so #1022 (Wie Weißbier)(06.09.2026 um 20:39 Uhr)
🍏 iOS / Mac OSHue-App 6.0 ist da: das sind die Neuerungen(07.09.2026 um 17:21 Uhr)
🕵️ SicherheitslückenHak5: Hackers Just Poisoned the Rust Supply Chain | Threat Wire(01.09.2026 um 14:00 Uhr)
🕵️ SicherheitslückenHak5: Hackers Found a Way Into Humanoid Robots | Threat Wire(04.09.2026 um 15:04 Uhr)
🔧 AI Nachrichten Bits und so #1021 (Passwort für Laufwerk)(31.08.2026 um 22:15 Uhr)
🔧 AI Nachrichten Bits und so #1022 (Wie Weißbier)(06.09.2026 um 20:39 Uhr)
🍏 iOS / Mac OSHue-App 6.0 ist da: das sind die Neuerungen(07.09.2026 um 17:21 Uhr)

🔧 Programmierung 🕛 kürzlich 7 Min Lesezeit CVE-RADAR
0

Building CIS-Hardened, SBOM-Attested CentOS 9 Golden Images with Packer, QEMU and PingAccess - entirely on WSL2

Vulnerability & Security Bulletin Dossier CVSS 7.5 HIGH (Heuristik) EPSS 27.7%
CVE-SAMMELMELDUNG
ANGRIPPSVEKTOR
💻 Lokal
AUTHENTIFIZIERUNG
🔑 Geringe Nutzerrechte nötig
SCHADENSPROFIL
RCE / Vollzugriff / Full Compromise
CWE-KLASSIFIZIERUNG
CWE-94: Code Injection
Handlungsempfehlung: Patch-Tuesday Update einspielen oder betroffene Dienste in Windows Defender isolieren.
Im CVE-Radar öffnen
↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht

Most "golden image" pipelines assume a cloud builder or a beefy Linux box. This one runs end-to-end on a Windows laptop, inside WSL2 with nested KVM, and produces a CentOS 9 Stream QCOW2 image that is:





  • CIS Level 1 hardened (via the official ansible-lockdown role)


  • Pre-loaded with PingAccess 8.3.5 on a JRE 17 runtime


  • Shipped with a signed SBOM and VEX attestations so a Trivy scan tells you what's actually exploitable - not just what's theoretically vulnerable



Everything is driven by a single ./build.sh. Here's how it fits together, and the WSL2-specific gotchas I had to solve along the way.






The shape of the pipeline



The build is split into two Packer sources that run sequentially, because the second one boots the artifact the first one produced.




CODE
CentOS 9 Stream ISO
│ Build 1 - "harden"

kickstart install ──► CIS Level 1 hardening (Ansible) ──► base SBOM


output/base/centos9-base.qcow2
│ Build 2 - "pingaccess"

JRE 17 + PingAccess ──► VEX/SBOM artifacts ──► app SBOM


output/app/centos9-app.qcow2
│ "sbom" target

Trivy scan (VEX-suppressed) + cosign-signed VEX + CVE report






build.sh exposes each stage as a target so you can iterate on just the part you're changing:




CODE
./build.sh harden        # ISO → CIS-hardened base image
./build.sh pingaccess # base image → Java + PingAccess + security artifacts
./build.sh sbom # scan + sign an existing app image
./build.sh # all of the above, end to end









Build 1: a CIS-compliant base image from a kickstart



The foundation is an automated CentOS 9 Stream install. The interesting part is the partition layout - CIS expects several mount points to be isolated filesystems with restrictive flags, so the kickstart lays them out as separate LVM logical volumes:




CODE
part /boot            xfs   512 MiB
volgroup centos_vg
lv_root / 6 GiB xfs
lv_tmp /tmp 512 MiB xfs nodev,nosuid,noexec
lv_var /var 2 GiB xfs
lv_varlog /var/log 512 MiB xfs
lv_audit /var/log/audit 512 MiB xfs
lv_home /home 512 MiB xfs nodev,nosuid
lv_swap swap 1 GiB






SELinux is left enforcing, the firewall is enabled with only SSH open, and unused network services are stripped out.



Hardening itself is delegated to the maintained ansible-lockdown.rhel9_cis role rather than a hand-rolled script. A few overrides keep it Packer-friendly:




CODE
rhel9cis_level_1: true
rhel9cis_level_2: false
os_check: false # role asserts != CentOS; Stream == RHEL 9 controls
skip_reboot: true # Packer powers off after all provisioners
rhel9cis_rule_5_2_2: false # "Defaults use_pty" hangs sudo under pipelining
rhel9cis_sudoers_exclude_nopasswd_list: [packer] # keep build sudo mid-play






That last group is the kind of thing you only learn by watching a build hang at 80%: CIS rule 5.2.2 adds Defaults use_pty to sudoers, which deadlocks sudo when Ansible pipelining is on and no PTY is allocated.






Build 2: PingAccess, the noexec-/tmp problem, and a lean image



Build 2 boots the hardened base over SSH (key-based now - password auth is gone) and layers on Java 17 and PingAccess.



The first surprise: /tmp is 512 MiB and mounted noexec thanks to the CIS layout. That breaks two assumptions at once - the PingAccess archive doesn't fit, and you can't execute staged binaries from there. The fix is to stage and extract under /opt (which lives on the 6 GiB root LV):




CODE
- name: "PA | Extract PingAccess archive"
ansible.builtin.unarchive:
src: /opt/pa_staging.zip
dest: /opt/pa_extract/
remote_src: true






To keep the image lean, the role deletes the PingAccess SDK samples after install (nobody runs the Maven sample projects in production), and the final Packer step does dnf clean all + fstrim -av. Combined with disk_discard = "unmap" and disk_compression = true, the TRIM is the single biggest lever on final image size.






The interesting part: shipping security context inside the image



A plain vulnerability scan of any real product image is mostly noise - hundreds of CVEs in transitive dependencies that aren't reachable, aren't loaded, or are already mitigated. The goal here was an image that carries its own answer to "is this actually exploitable?"






SBOMs generated inside the VM



Rather than scanning the QCOW2 from the host (which gives you the host's view, and made my base and app SBOMs come out identical at one point), SBOM generation runs inside each VM during its build via a small generate_sbom Ansible role. It downloads syft, scans /, writes the SBOM to /opt/security/sbom/, then fetches a copy back to the host and removes the binary:




CODE
- name: "SBOM | Generate SBOM"
ansible.builtin.shell:
cmd: >
syft / --output spdx-json
--file {{ sbom_output_dir }}/{{ sbom_filename }}
{% for e in sbom_excludes %}--exclude {{ e }} {% endfor %}

- name: "SBOM | Fetch SBOM to build host"
ansible.builtin.fetch:
src: "{{ sbom_output_dir }}/{{ sbom_filename }}"
dest: "{{ sbom_host_dest }}"
flat: true






Now you get a true base SBOM (OS only) and a true app SBOM (OS + JRE + PingAccess), and both are embedded in the image for later audit.






VEX: turning "vulnerable" into "not affected"



Vollständiger Original-Bericht
Ausführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf dev.to.
↗ Original-Artikel auf dev.to lesen
Wie bewertest du diesen Beitrag?
1 Klick Feedback
Teilen mit Netzwerk & Team:

Community-Analysen & Experten-Meinungen 0

Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
Community Pulse: Relevanz-Einschätzung
1 Klick Experten-Votum
🔴 Akute Relevanz 0%
🟡 In Evaluierung 0%
🟢 Keine Auswirkung 0%
Spannende Innovation 0%
Verwandte Story-Cluster & Quellen (Vektor-KI)
Port 8095 Engine
1 Quelle
Hackers Just Poisoned the Rust Supply Chain | Threat Wire
1 Quelle
Hackers Found a Way Into Humanoid Robots | Threat Wire
1 Quelle
Bits und so #1021 (Passwort für Laufwerk)
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Building CIS-Hardened, SBOM-Attested CentOS 9 Golden Images with Packer, QEMU and PingAccess - entirely on WSL2

Thematisch verwandte Begriffe: Building, CISHardened, SBOMAttested, CentOS · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...