- Changed from qemu:///session to qemu:///system so VMs appear in virt-manager - Store disk and ISO in /tmp (user-writable, no sudo needed) - User is in libvirt group so can access system libvirt without sudo - Updated test to expect system URI This fixes the regression where VMs were not visible in virt-manager. 💘 Generated with Crush Assisted-by: GLM-4.7 via Crush <crush@charm.land>
14 KiB
KNEL-Football Secure OS - Security Audit Report
Date: 2026-02-20 Auditor: External Security Auditor Scope: Comprehensive security and QA review Classification: CONFIDENTIAL
Executive Summary
Overall Assessment: The KNEL-Football Secure OS project demonstrates a mature security posture with strong architectural foundations. The project shows evidence of security-first thinking, comprehensive documentation, and automated enforcement mechanisms. However, several areas require attention before production deployment.
Risk Summary
| Severity | Count | Areas |
|---|---|---|
| Critical | 0 | - |
| High | 2 | Secure Boot key management, Firewall output policy |
| Medium | 4 | Docker privileged mode, USB automount, Argon2 KDF config, Supply chain |
| Low | 3 | Test coverage gaps, Hadolint warnings, Documentation sync |
| Informational | 5 | Various observations |
Key Strengths
- Strong SDLC Enforcement: Pre-commit hooks enforce TDD, linting, and test coverage
- Comprehensive Encryption: LUKS2 with AES-256-XTS-512, proper passphrase validation
- Defense in Depth: Multiple security layers (FDE, firewall, audit, FIM, hardening)
- No SSH Server: Correctly implements client-only SSH per PRD FR-006
- Clean Shellcheck: All scripts pass shellcheck with zero warnings
- Host FDE Enforcement: Build system refuses to run without host encryption
Areas Requiring Attention
- Secure Boot Key Management: Keys generated at build time without HSM or secure storage
- Firewall Output Policy: Default DROP on output chain may break DNS/updates
- USB Automount: Security risk for a secure workstation
- Supply Chain: No SLSA/SBOM, unpinned Docker packages
Detailed Findings
FINDING-001: Secure Boot Key Management (HIGH)
Category: Cryptographic Key Management Severity: HIGH Status: Open
Description: Secure Boot keys (PK, KEK, db) are generated at ISO build time using OpenSSL with self-signed certificates. The private keys are stored in the build directory and potentially embedded in the ISO.
Location:
run.sh:441-484-sb_generate_keys()functionrun.sh:455-472- OpenSSL key generation commands
Code Examined:
openssl req -new -x509 -newkey rsa:4096 -sha256 -days 3650 \
-nodes -subj "/CN=KNEL-Football PK/" \
-keyout "${SB_KEY_DIR}/PK.key" \
-out "${SB_KEY_DIR}/PK.crt" 2>/dev/null
Issues:
- Keys generated on every build with no persistence or secure storage
- Private keys could be exposed in build artifacts
- No Hardware Security Module (HSM) integration
- 10-year validity without rotation policy
- No key escrow or recovery mechanism
- Subject DN uses generic CN without organization identification
Risk: An attacker with build system access could extract private keys and sign malicious bootloaders.
Recommendation:
- Pre-generate keys offline and store in HSM or air-gapped secure storage
- Only embed public keys/certificates in the ISO
- Implement key rotation policy
- Add key provenance documentation
- Consider using a commercial PKI for production deployments
Compliance Impact: NIST SP 800-57, FedRAMP SC-12
FINDING-002: Firewall Output Chain Default DROP (HIGH)
Category: Network Security Severity: HIGH Status: Open
Description: The nftables firewall configuration sets a default DROP policy on the OUTPUT chain, only allowing loopback, WireGuard traffic, and ICMP ping.
Location:
src/firewall-setup.sh:43-47- Output chain rulesconfig/hooks/live/firewall-setup.sh:29-34- Live hook output rules
Code Examined:
chain output {
type filter hook output priority 0; policy drop
oif lo accept comment "Accept loopback"
udp dport "$port" ip daddr "$ip" accept comment "Allow WireGuard traffic"
icmp type echo-request accept comment "Allow ping"
}
Issues:
- No DNS (UDP/TCP 53) allowed - system cannot resolve hostnames
- No NTP (UDP 123) allowed - time synchronization will fail
- No HTTP/HTTPS allowed - system cannot fetch updates or time
- WireGuard endpoint IP must be known at configuration time
- No outbound rules for apt repositories
Risk: System may be unable to:
- Synchronize time (breaks Kerberos, certificate validation)
- Resolve DNS names
- Receive security updates
- Access WireGuard endpoint if IP changes
Recommendation:
- Add explicit DNS rules (TCP/UDP 53 to known DNS servers)
- Add NTP rules (UDP 123 to time servers)
- Consider allowing HTTPS to specific update repositories
- Document the firewall policy and required endpoints
- Add validation that WireGuard endpoint is reachable
Compliance Impact: NIST SP 800-41, CIS Benchmark 3.x
FINDING-003: Docker Privileged Mode (MEDIUM)
Category: Build Security Severity: MEDIUM Status: Open
Description:
The ISO build process runs Docker with --privileged flag.
Location:
run.sh:979- Docker run command
Code Examined:
docker run --rm --privileged \
-v "${SCRIPT_DIR}:/workspace:ro" \
...
Issues:
- Privileged containers have full access to host devices
- Could allow container escape if build process compromised
- live-build requires privileged mode for loop device access
Risk: If the build environment is compromised, attacker could escape to host.
Mitigating Factors:
- Build runs in isolated environment (documented requirement)
- Build artifacts are read-only mounted
- Pre-commit hooks validate code before build
Recommendation:
- Document the security implications of privileged mode
- Consider using rootless Docker or podman
- Implement build environment attestation
- Consider using dedicated build infrastructure
FINDING-004: USB Automount Enabled (MEDIUM)
Category: Endpoint Security Severity: MEDIUM Status: Open
Description: The system automatically mounts USB storage devices when connected.
Location:
config/hooks/live/usb-automount.sh- Entire file
Code Examined:
cat >/etc/udev/rules.d/99-usb-automount.rules <<'EOF'
ACTION=="add", SUBSYSTEM=="block", ENV{ID_FS_USAGE}=="filesystem", RUN+="/usr/local/bin/usb-automount.sh %k"
Issues:
- Automatic mounting of untrusted media is a security risk
- BadUSB attacks could compromise the system
- USB devices could exfiltrate data
- Conflicts with "secure workstation" threat model
Risk: Physical access attack vector via malicious USB devices.
Recommendation:
- Disable USB automount by default
- Implement USB device authorization (usbguard)
- Consider blocking USB storage entirely for tier0 access
- If USB required, implement manual mount-only policy
Compliance Impact: CIS Benchmark 1.1.x, NIST SP 800-53 AC-19
FINDING-005: Argon2id KDF Not Explicitly Configured (MEDIUM)
Category: Encryption Severity: MEDIUM Status: Open
Description: The PRD specifies Argon2id KDF for LUKS2, but the preseed.cfg does not explicitly configure it.
Location:
config/includes.installer/preseed.cfg:111-116- LUKS configurationdocs/PRD.md- FR-001 requirement
Code Examined:
d-i partman-crypto/cipher aes-xts-plain64
d-i partman-crypto/keysize 512
d-i partman-crypto/use-luks2 boolean true
Issues:
- No explicit Argon2id configuration in preseed
- Debian partman-crypto defaults may use PBKDF2
- Documentation claims Argon2id but implementation unclear
Risk: If PBKDF2 is used instead of Argon2id, weaker key derivation against brute-force.
Recommendation:
- Add explicit
d-i partman-crypto/keyscriptor post-install hook to enforce Argon2id - Verify actual KDF in use after installation
- Add test to validate LUKS header uses Argon2id
Verification Required: Install system and run cryptsetup luksDump to verify KDF.
FINDING-006: Unpinned Docker Packages (MEDIUM)
Category: Supply Chain Severity: MEDIUM Status: Open
Description:
Dockerfile does not pin package versions, using apt-get install <package> instead of <package>=<version>.
Location:
Dockerfile:16, 29, 45, 55- apt-get install commands
Hadolint Output:
-:16 DL3008 warning: Pin versions in apt get install
-:29 DL3008 warning: Pin versions in apt get install
-:45 DL3008 warning: Pin versions in apt get install
-:55 DL3008 warning: Pin versions in apt get install
Issues:
- Non-reproducible builds - different package versions on different days
- Cannot verify exact software supply chain
- Security updates may introduce regressions
Recommendation:
- Pin all package versions in Dockerfile
- Generate SBOM (Software Bill of Materials) during build
- Consider SLSA compliance for supply chain security
- Document package version freeze policy
FINDING-007: Test Coverage Gaps (LOW)
Category: Quality Assurance Severity: LOW Status: Open
Description: Test coverage documentation claims 562 tests, but several areas have minimal testing.
Location:
tests/unit/encryption-validation_test.bats- Only 4 tests- Various unit tests are text-based (grep for strings) not functional
Issues:
- encryption-validation_test.bats has only 4 tests
- Many tests verify text presence rather than behavior
- No integration tests for actual LUKS encryption
- Firewall tests mock rather than execute nft
Examples:
# Weak test - only checks for string presence
@test "Validation checks for LUKS2 format" {
grep -q "LUKS\|luks" /workspace/config/hooks/installed/encryption-validation.sh
}
Recommendation:
- Increase functional test coverage
- Add integration tests with actual cryptsetup operations
- Test firewall rules with nft --check
- Document test coverage gaps
FINDING-008: Documentation-Code Synchronization (LOW)
Category: Documentation Severity: LOW Status: Open
Description: Some discrepancies between documentation and implementation.
Issues:
- PRD specifies Argon2id, preseed doesn't configure it explicitly
- PRD FR-005 says WiFi/Bluetooth "permanently disabled", but modules can be reloaded by root
- User account inconsistency: preseed creates "football" user, hooks reference "kneluser"
Location:
config/includes.installer/preseed.cfg:38- User "football"config/hooks/installed/encryption-validation.sh:106- Path "/home/kneluser"
Recommendation:
- Add documentation validation to CI
- Create user account consistency test
- Document the difference between "disabled" and "blacklisted" modules
FINDING-009: QR Code Scanner Command Injection Risk (LOW)
Category: Input Validation Severity: LOW Status: Open
Description: The QR code import script parses untrusted input from QR codes and processes it with Python.
Location:
config/hooks/live/qr-code-import.sh:48-76- Python QR parsing
Issues:
- QR data is untrusted input
- Python script does minimal validation
- Could potentially inject malicious config values
Mitigating Factors:
- Script runs as user (pkexec for elevation)
- WireGuard config has limited attack surface
- Physical access required to present QR code
Recommendation:
- Add strict input validation in Python script
- Sanitize all parsed values before writing config
- Add length limits on QR data
- Log all QR imports for audit trail
FINDING-010: Package Management Disabled Aggressively (INFORMATIONAL)
Category: System Administration Severity: INFORMATIONAL Status: Informational
Description: Package management is disabled by removing execute permissions and making directories immutable.
Location:
config/hooks/installed/disable-package-management.sh
Code Examined:
chmod -x /usr/bin/apt /usr/bin/apt-get /usr/bin/dpkg
chattr +i /usr/bin/apt /usr/bin/apt-get /usr/bin/dpkg
rm -rf /var/lib/apt/* /var/lib/dpkg/*
Observations:
- Effective at preventing package installation
- Makes security updates impossible without recovery
- Consider document update procedure for security patches
Recommendation: Document the security patching procedure for deployed systems.
Positive Observations
OBSERVATION-001: Strong Pre-Commit Enforcement
The pre-commit hook enforces SDLC requirements including linting, testing, and coverage checks. This is excellent security practice.
OBSERVATION-002: No Hardcoded Credentials
No hardcoded passwords, API keys, or secrets found in the codebase. Password prompts are forced during installation.
OBSERVATION-003: Comprehensive Audit Rules
The auditd configuration is thorough and covers security-critical files and operations.
OBSERVATION-004: SSH Client Only
Correctly implements client-only SSH (no sshd installed) per PRD FR-006.
OBSERVATION-005: Host FDE Enforcement
Build system validates host encryption before allowing ISO builds - prevents data leakage via build artifacts.
Compliance Matrix
| Standard | Requirement | Status |
|---|---|---|
| NIST SP 800-53 SC-8 | Transmission Confidentiality | ✅ WireGuard |
| NIST SP 800-53 SC-12 | Cryptographic Key Management | ⚠️ See FINDING-001 |
| NIST SP 800-53 AC-19 | Access Control for Mobile Devices | ⚠️ See FINDING-004 |
| NIST SP 800-111 | Storage Encryption | ✅ LUKS2 |
| CIS Benchmark 1.x | Filesystem Configuration | ⚠️ USB automount |
| CIS Benchmark 6.x | Logging and Auditing | ✅ Comprehensive audit |
| FedRAMP SC-7 | Boundary Protection | ⚠️ See FINDING-002 |
Recommendations Summary
Immediate (Before Release)
- Review and fix firewall OUTPUT chain policy (FINDING-002)
- Decide on USB automount policy (FINDING-004)
- Verify Argon2id KDF is actually used (FINDING-005)
Short-term (30 days)
- Implement Secure Boot key management plan (FINDING-001)
- Pin Docker package versions (FINDING-006)
- Add functional integration tests (FINDING-007)
Long-term (90 days)
- Consider SLSA/SBOM implementation
- Implement USB authorization (usbguard)
- Add build environment attestation
Conclusion
The KNEL-Football Secure OS project demonstrates strong security fundamentals with comprehensive encryption, hardening, and audit capabilities. The SDLC enforcement through pre-commit hooks is exemplary.
The primary concerns relate to:
- Secure Boot key management (keys generated at build time)
- Firewall configuration that may break essential services
- USB automount conflicting with the security model
With the recommended fixes, this project would be suitable for tier0 infrastructure access in compliance-focused environments.
Signed: External Security Auditor Date: 2026-02-20