DeepReport-2026-05-08.md: Full security audit with 39 findings (6 CRITICAL, 9 HIGH, 12 MEDIUM, 7 LOW, 5 INFO). STATUS.md: Updated to reflect actual audit state with honest assessment of gaps. Removed inflated compliance claims. Added remediation progress tracker. Compliance claims acknowledged as aspirational by project owner. Session 8 will focus on fixing all technical findings. 💘 Generated with Crush Assisted-by: GLM-5.1 via Crush <crush@charm.land>
550 lines
26 KiB
Markdown
550 lines
26 KiB
Markdown
# KNEL-Football Secure OS — Deep Security Audit Report
|
|
|
|
**Date**: 2026-05-08
|
|
**Auditor**: Senior Security Engineer / Technical Operations Manager
|
|
**Scope**: Full codebase, build system, test suite, documentation, git history
|
|
**Classification**: CONFIDENTIAL — For Owner Review Only
|
|
|
|
---
|
|
|
|
## Executive Verdict: **NOT PRODUCTION READY — DO NOT DEPLOY**
|
|
|
|
**Overall Risk Rating: 🔴 HIGH RISK**
|
|
|
|
This system has **6 critical**, **9 high**, **12 medium**, and **7 low** severity findings across the codebase. The most damaging issues are:
|
|
|
|
1. **The encryption you're trusting your tier0 access to doesn't work as documented** — Argon2id is not used; systems ship with PBKDF2
|
|
2. **The host FDE mandatory check that PRD FR-011 calls "cannot be bypassed" is never called** — security theater
|
|
3. **USB devices can execute arbitrary code** — missing `noexec,nosuid,nodev` on automount
|
|
4. **Secure Boot private keys are generated unencrypted** — the root of trust is unprotected
|
|
5. **The test suite provides false confidence** — ~85% of tests are `grep` pattern matching, not behavioral tests
|
|
6. **Compliance claims (CMMC L3, FedRAMP, ISO 27001) are fabricated** — no organizational controls exist
|
|
|
|
The engineering shows real security thinking and honest effort. The JOURNAL.md is commendable. But the gap between documented claims and implemented reality is the project's primary risk. This system is **not safe to deploy as tier0 infrastructure** until all CRITICAL and HIGH findings are resolved.
|
|
|
|
---
|
|
|
|
## Project Metrics (Measured)
|
|
|
|
| Metric | Value |
|
|
|--------|-------|
|
|
| Source scripts (`src/`) | 3 files |
|
|
| Hook scripts (`config/hooks/`) | 14 files |
|
|
| Test files (`tests/`) | 26 files |
|
|
| Config files | 7 files |
|
|
| Total lines (all source) | ~8,357 |
|
|
| ISO size | 824 MB |
|
|
| ISO SHA256 | `df683e04a66f0fa69c6e2584e7d08913d0dde9367a347a2661ce120a464d0854` |
|
|
| Build date | 2026-05-07 |
|
|
|
|
---
|
|
|
|
## Findings Summary
|
|
|
|
| Severity | Count | Description |
|
|
|----------|-------|-------------|
|
|
| **CRITICAL** | 6 | System is fundamentally insecure; must fix before any deployment |
|
|
| **HIGH** | 9 | Significant security gaps; serious risk in production |
|
|
| **MEDIUM** | 12 | Important issues that weaken security posture |
|
|
| **LOW** | 7 | Minor issues; should fix but not blockers |
|
|
| **INFO** | 5 | Observations for improvement |
|
|
| **Total** | **39** | |
|
|
|
|
---
|
|
|
|
## CRITICAL Findings (Must Fix Before Any Deployment)
|
|
|
|
### C-01: Argon2id KDF NOT Actually Enforced — Systems Ship with PBKDF2
|
|
|
|
**PRD Claim**: FR-001 mandates *"Argon2id key derivation"*
|
|
**Reality**: All installed systems use PBKDF2
|
|
|
|
- `config/includes.installer/preseed.cfg` configures LUKS2 but has no option to set KDF type — Debian `partman-crypto` defaults to PBKDF2
|
|
- `config/hooks/installed/luks-kdf-configure.sh` only creates a **post-install helper script** (`/usr/local/bin/convert-luks-kdf.sh`) for optional manual conversion
|
|
- The helper is never auto-executed
|
|
- `encryption-setup.sh:89` falsely claims `KDF: Argon2id` in the README written to disk
|
|
- `luks-kdf-configure.sh:133` patches the README to say "run convert-luks-kdf.sh to enable" — admitting it's not enabled
|
|
|
|
**Impact**: PBKDF2 is significantly weaker than Argon2id against GPU-based brute force. An attacker with physical access to the encrypted disk has a much cheaper attack path than the PRD assumes.
|
|
|
|
**Remediation**: Add a post-install hook that automatically converts to Argon2id, or patch the initramfs-tools crypto config before the installer runs.
|
|
|
|
---
|
|
|
|
### C-02: Host FDE Mandatory Check Is NEVER Enforced — PRD FR-011 Completely Violated
|
|
|
|
**PRD Claim**: FR-011 *"No Bypass - This check cannot be disabled or bypassed"*
|
|
**Reality**: The check function exists but is never called
|
|
|
|
- `run.sh:47-118` defines `check_host_fde()` — comprehensive, well-written
|
|
- `run.sh:1049-1059` — the `iso`/`iso:demo` build path skips it entirely:
|
|
```bash
|
|
log_warn "Host FDE check: ${KNEL_BUILD_MODE} build on potentially unencrypted host"
|
|
log_warn "PRD FR-011 requires host FDE - proceeding with build anyway"
|
|
```
|
|
- The function is defined, tested, documented, and **completely inert**
|
|
- An unencrypted host means Secure Boot private keys, the ISO, and all build artifacts are written to plaintext storage
|
|
|
|
**Impact**: Build chain compromise. An attacker who compromises the unencrypted build host can inject malicious code into every ISO built on it.
|
|
|
|
**Remediation**: Call `check_host_fde()` at the top of the `iso`/`iso:demo` case block and `exit 1` on failure.
|
|
|
|
---
|
|
|
|
### C-03: Docker Build Runs `--privileged` With Full Host Access
|
|
|
|
**File**: `run.sh:1065-1067`
|
|
```bash
|
|
docker run --rm \
|
|
--privileged \
|
|
--user root \
|
|
```
|
|
|
|
`--privileged` grants the container: all devices, all kernel capabilities, mount permissions, seccomp/AppArmor bypass. Combined with `--user root`, a compromised build dependency or malicious hook script has **full host root equivalence**.
|
|
|
|
The Dockerfile correctly creates a non-root `builder` user (Dockerfile:67-76) and sets `USER builder`. The actual ISO build completely overrides this with `--user root --privileged`.
|
|
|
|
**Impact**: Container escape is trivial. Build supply chain compromise leads to host compromise.
|
|
|
|
**Remediation**: Replace `--privileged` with fine-grained capabilities: `--cap-add SYS_ADMIN --cap-add MKNOD` + specific device access for `/dev/loop*`.
|
|
|
|
---
|
|
|
|
### C-04: Secure Boot Private Keys Generated Unencrypted (`-nodes`)
|
|
|
|
**Files**: `run.sh:511-528, 762-777, 1141-1156`
|
|
|
|
```bash
|
|
openssl req -new -x509 -newkey rsa:4096 -sha256 -days 3650 \
|
|
-nodes -subj "/CN=KNEL-Football PK/" \
|
|
-keyout "${SB_KEY_DIR}/PK.key" \
|
|
```
|
|
|
|
The `-nodes` flag generates private keys **without passphrase encryption**. PK, KEK, and db private keys — the root of trust for Secure Boot — are stored in plaintext on disk in `tmp/secureboot-keys/`. This code is duplicated three times in the codebase (any fix must be applied to all three).
|
|
|
|
Additionally, the key lifecycle is broken:
|
|
- If `config/secureboot-keys/` exists, the same keys are reused (good for consistency, but private keys could be in git)
|
|
- If it doesn't exist, new keys are generated each build (previously deployed systems won't trust the new ISO)
|
|
|
|
**Impact**: An attacker who accesses the build host can extract PK.key, KEK.key, db.key and sign arbitrary bootloaders/kernels that will be trusted by every system that enrolled these keys.
|
|
|
|
**Remediation**: Generate keys once with a strong passphrase. Store in an HSM or at minimum a passphrase-protected PKCS#12. Never store unencrypted private keys on disk.
|
|
|
|
---
|
|
|
|
### C-05: USB Automount Missing `noexec,nosuid,nodev` — Allows Code Execution from USB
|
|
|
|
**File**: `config/hooks/live/usb-automount.sh:30-38`
|
|
```bash
|
|
mount -t vfat -o rw,uid=1000,gid=1000,dmask=000,fmask=111 "${DEVICE}" "${MOUNT_BASE}"
|
|
mount -t ntfs-3g -o rw,uid=1000,gid=1000,dmask=000,fmask=111 "${DEVICE}" "${MOUNT_BASE}"
|
|
mount -t ext4 -o rw "${DEVICE}" "${MOUNT_BASE}"
|
|
mount -t auto -o rw,uid=1000,gid=1000 "${DEVICE}" "${MOUNT_BASE}"
|
|
```
|
|
|
|
**PRD FR-008** explicitly requires *"No automatic program execution"* and *"No device special files from USB"*. None of the mount commands include `noexec`, `nosuid`, or `nodev`. Additionally, `dmask=000` makes all directories world-readable.
|
|
|
|
**Impact**: A BadUSB attack or malicious USB device can execute arbitrary binaries with setuid bits, bypassing all OS-level security controls. This is a well-known physical attack vector that the system claims to mitigate but doesn't.
|
|
|
|
**Remediation**: Add `noexec,nosuid,nodev` to all mount options. Change `dmask=000` to `dmask=077`.
|
|
|
|
---
|
|
|
|
### C-06: Plaintext Credentials in Git History (Permanent Exposure)
|
|
|
|
**File**: `config/includes.installer/demo.preseed.cfg:38-45, 98-103`
|
|
|
|
```
|
|
# football user: Kn3l-F00tball-D3m0!
|
|
d-i passwd/user-password-again string Kn3l-F00tball-D3m0!
|
|
d-i passwd/root-password-again string Kn3l-R00t-D3m0!
|
|
d-i partman-crypto/passphrase password Kn3l-D3m0-LUKS!
|
|
```
|
|
|
|
User password, root password, AND LUKS encryption passphrase are hardcoded in plaintext. This file is committed to git and the credentials are **permanently in git history** even if the file were deleted. If this repo is ever public or shared, these become exploitable.
|
|
|
|
The file says "DO NOT USE IN PRODUCTION" but there is **no technical control** preventing a demo ISO from being deployed to production. The `iso:demo` build path only prints a warning.
|
|
|
|
**Also in `TODO.md:22`**: `Hardcode encryption passphrase: TestPassphrase2026!Secure` — a future test passphrase documented in the backlog.
|
|
|
|
**Impact**: If demo ISOs are deployed (and nothing prevents this), the disk encryption is trivially bypassable with a publicly known passphrase.
|
|
|
|
**Remediation**:
|
|
1. Use `git filter-repo` or BFG Repo-Cleaner to scrub credentials from history
|
|
2. Add a build-time guard that refuses to build demo ISOs without an explicit `--i-understand-this-is-insecure` flag
|
|
3. Rotate all credentials in demo.preseed.cfg
|
|
|
|
---
|
|
|
|
## HIGH Findings (Serious Risk — Fix Before Production)
|
|
|
|
### H-01: SSH `StrictHostKeyChecking ask` Allows MITM on First Connection
|
|
|
|
**Files**: `src/security-hardening.sh:80`, `config/hooks/live/security-hardening.sh:60`
|
|
|
|
PRD FR-006 says *"strict host key checking"*. `ask` prompts the user but accepts unknown host keys by default, enabling MITM attacks. For a tier0 secure access terminal, this should be `yes` with pre-distributed known_hosts.
|
|
|
|
---
|
|
|
|
### H-02: SSH Server Config Written Despite "Client Only" Requirement
|
|
|
|
**Files**: `src/security-hardening.sh:87-114`, `config/hooks/live/security-hardening.sh:64-75`
|
|
|
|
PRD FR-006: *"No SSH server, no inbound SSH access"*. Yet `sshd_config` is generated and written to disk as "defense-in-depth." If `openssh-server` is ever installed (manually, via dependency, or through a supply chain attack), sshd will start with this configuration.
|
|
|
|
---
|
|
|
|
### H-03: `src/firewall-setup.sh` Missing `ct state established,related` — Breaks WireGuard
|
|
|
|
**File**: `src/firewall-setup.sh:26-49`
|
|
|
|
The `src/` firewall output chain does NOT include `ct state established,related accept`. Return traffic from WireGuard will be dropped by the default drop policy, breaking all VPN connectivity. The live hook version and `install-scripts.sh` version correctly include this rule. Three divergent implementations of the same firewall.
|
|
|
|
---
|
|
|
|
### H-04: QR Code Scanner Leaks WireGuard Private Key via Insecure Temp File
|
|
|
|
**File**: `config/hooks/live/qr-code-import.sh:26`
|
|
|
|
`mktemp` creates a file that will contain the WireGuard private key. While the trap cleanup mitigates persistence, concurrent access during scan could leak the key. Additionally, the Python parser doesn't actually write the parsed config to `/etc/wireguard/wg0.conf` — the feature is non-functional.
|
|
|
|
---
|
|
|
|
### H-05: Encryption Key Management Has Broken cryptsetup Syntax
|
|
|
|
**File**: `config/hooks/installed/encryption-setup.sh:204`
|
|
```bash
|
|
echo "$existing_pass" | cryptsetup luksAddKey /dev/sda3 <<< "$new_pass"
|
|
```
|
|
|
|
Uses BOTH pipe (`echo |`) and heredoc (`<<<`) simultaneously. Only one stdin source works. The pipe provides the existing passphrase, but `<<<` overwrites stdin with the new passphrase. This command may fail silently or expose passphrases in `/proc/*/cmdline`.
|
|
|
|
---
|
|
|
|
### H-06: Hardcoded `/dev/sda3` Device Path Throughout Encryption Scripts
|
|
|
|
**Files**: `encryption-setup.sh:102,142,145,204,208,233,238`, `encryption-validation.sh:80`
|
|
|
|
LUKS device hardcoded as `/dev/sda3`. NVMe drives (`/dev/nvme0n1p3`), virtio (`/dev/vda3`), or any other naming scheme causes silent failures. Only `luks-kdf-configure.sh:41` correctly checks multiple device paths.
|
|
|
|
---
|
|
|
|
### H-07: `sbverify` Returns Success Even When Verification Fails
|
|
|
|
**File**: `run.sh:696-702, 860-866, 1252-1256`
|
|
```bash
|
|
else
|
|
log_warn "UKI signed but verification uncertain"
|
|
return 0 # <-- STILL RETURNS SUCCESS
|
|
fi
|
|
```
|
|
|
|
UKI signature verification failure is non-fatal. The build proceeds as if signing succeeded. In a Secure Boot pipeline, this defeats the entire purpose.
|
|
|
|
---
|
|
|
|
### H-08: Docker-Embedded UKI Build Missing `module.sig_enforce=1`
|
|
|
|
**File**: `run.sh:843` (inside `get_secureboot_script`)
|
|
```bash
|
|
echo "quiet splash lockdown=confidentiality" > "$cmdline"
|
|
```
|
|
|
|
Missing `module.sig_enforce=1` from the kernel command line. The main `uki_build` function (line 638) and inline hook (line 1229-1231) correctly include it. One of three code paths is missing a critical security parameter.
|
|
|
|
---
|
|
|
|
### H-09: Build Cache Has No Integrity Verification
|
|
|
|
**File**: `run.sh:1114-1121, 1289-1293`
|
|
|
|
Docker volume cache stores bootstrap and package data between builds with no checksum or signature verification. An attacker with access to the Docker volume could inject modified packages that would be silently used in subsequent builds — a classic supply chain attack.
|
|
|
|
---
|
|
|
|
## MEDIUM Findings
|
|
|
|
### M-01: `apply_security_hardening()` Never Calls `configure_fim()` or `configure_ssh_client()`
|
|
**File**: `src/security-hardening.sh:327-339`
|
|
|
|
If `src/security-hardening.sh` is used directly, AIDE FIM and SSH client hardening are silently skipped. The live hook version includes them, creating divergent codebases.
|
|
|
|
### M-02: Sudo Group Conflict — Overly Broad Access
|
|
**File**: `config/hooks/installed/install-scripts.sh:222`
|
|
|
|
`usermod -a -G sudo football` grants full sudo access (all commands), overriding the carefully crafted `/etc/sudoers.d/99-knel-hardening` that limits the user to specific commands.
|
|
|
|
### M-03: PAM Not Configured for Password Enforcement
|
|
**File**: `config/hooks/live/security-hardening.sh:78-97`
|
|
|
|
Writing `pwquality.conf` alone does not enforce password requirements. PAM must be configured to use `pam_pwquality.so` in `/etc/pam.d/common-password`, which is never modified by any hook. The password policy is inert.
|
|
|
|
### M-04: Recovery Key Stored in Plaintext
|
|
**File**: `config/hooks/installed/encryption-setup.sh:238`
|
|
|
|
Recovery key written to `/var/backups/keys/` as plaintext. PRD FR-001 states *"No plaintext keys stored anywhere on the system."*
|
|
|
|
### M-05: Firewall Allows WireGuard to Any Endpoint
|
|
**File**: `config/hooks/live/firewall-setup.sh:54`
|
|
|
|
Live system allows UDP to ports 51820-51830 to any IP, contradicting PRD FR-004's "configured endpoints only." The `install-scripts.sh` version correctly locks to specific endpoint IPs.
|
|
|
|
### M-06: AIDE Database Never Initialized
|
|
**File**: `config/hooks/live/security-hardening.sh:99-132`
|
|
|
|
AIDE configuration is written but `aideinit` is never run. No database exists, no cron/timer runs checks. File integrity monitoring is non-functional.
|
|
|
|
### M-07: Mount Hardening Only Applies to Existing fstab Entries
|
|
**File**: `config/hooks/installed/mount-hardening.sh:23-43`
|
|
|
|
Only hardens entries that already exist in `/etc/fstab`. For a fresh LUKS+LVM install, `/tmp` and `/home` may not have separate entries.
|
|
|
|
### M-08: USB Automount Has No Audit Logging
|
|
**File**: `config/hooks/live/usb-automount.sh`
|
|
|
|
PRD FR-008 requires audit logging of USB insertion/removal. No `logger` command, no auditd rule. The script writes to stdout only.
|
|
|
|
### M-09: Build Not Reproducible
|
|
**File**: `run.sh:1078-1318`
|
|
|
|
No `SOURCE_DATE_EPOCH`, no fixed mirror snapshots, no `.buildinfo`. Two builds at different times produce different ISOs. PRD FR-010 claims "reproducible builds."
|
|
|
|
### M-10: No GPG Signing of ISO Artifacts
|
|
PRD DEP-001 requires "GPG signature verification." QA-003 requires "Signed release artifacts." No GPG signing is implemented anywhere.
|
|
|
|
### M-11: Base Image Not Digest-Pinned
|
|
**File**: `Dockerfile:7`
|
|
```dockerfile
|
|
FROM debian:13.3-slim AS base
|
|
```
|
|
Docker Hub can serve different image content for the same tag. Should use `@sha256:<digest>`.
|
|
|
|
### M-12: WiFi Blacklist Incomplete vs PRD
|
|
**File**: `src/security-hardening.sh:9-30`
|
|
|
|
Missing `rtl8xxxu`, `iwlmvm`, `brcmsmac`, `brcm80211`, `ath10k_sdio`, `ath11k*` — modern drivers not covered by the blacklist.
|
|
|
|
---
|
|
|
|
## LOW Findings
|
|
|
|
| ID | Issue | Location |
|
|
|----|-------|----------|
|
|
| L-01 | Serial console enabled in GRUB for all builds | `config/bootloaders/grub-pc/config.cfg:4-7` |
|
|
| L-02 | Production preseed enables root login | `config/includes.installer/preseed.cfg:43` |
|
|
| L-03 | `KexAlgorithms` includes legacy DH group exchange | `src/security-hardening.sh:70` |
|
|
| L-04 | VNC has no authentication (localhost only) | `vm/template.xml:42-44` |
|
|
| L-05 | `KNEL_BUILD_MODE` can be spoofed via environment | `run.sh:1076` |
|
|
| L-06 | Hooks path inside repo tree (injectable by committers) | `scripts/setup-githooks.sh:32` |
|
|
| L-07 | Build log at predictable `/tmp` path (symlink attack) | `run.sh:15` |
|
|
|
|
---
|
|
|
|
## INFO Findings
|
|
|
|
| ID | Issue |
|
|
|----|-------|
|
|
| I-01 | `Protocol 2` in sshd_config is redundant (OpenSSH 7.0+) |
|
|
| I-02 | Kernel headers included in build-iso.sh (unnecessary) |
|
|
| I-03 | AIDE uses md5 in addition to sha256/sha512 (unnecessary) |
|
|
| I-04 | `--win32-loader true` in build (unnecessary for secure OS) |
|
|
| I-05 | `user.max_user_namespaces = 100` is generous for single-user system |
|
|
|
|
---
|
|
|
|
## Test Suite Assessment: **🔴 FALSE CONFIDENCE**
|
|
|
|
### Test Quality Breakdown
|
|
|
|
| Category | Percentage | Assessment |
|
|
|----------|-----------|------------|
|
|
| `grep` pattern matching (not behavioral) | ~85% | Verifies text exists, not that it works |
|
|
| Behavioral tests (source + execute) | ~10% | Only in `*_comprehensive_test.bats` files |
|
|
| Always-pass tautologies (`|| true`, `skip`) | ~5% | Inflates pass count without testing anything |
|
|
|
|
### Critical Test Deficiencies
|
|
|
|
1. **Zero negative/adversarial testing**: No test verifies that bad things are rejected (wrong passwords, weak passphrases, unauthorized access)
|
|
2. **Zero runtime verification**: All VM/system tests are `skip` stubs. No CI pipeline runs them against a real ISO.
|
|
3. **Tautological tests that always pass**:
|
|
- `usb-automount_test.bats:181`: `true` — does nothing
|
|
- `execution_comprehensive_test.bats:39-54`: All loops use `|| true`
|
|
- `hooks_comprehensive_test.bats:121-155`: All "security" tests use `|| true`
|
|
4. **Assertions too broad**: `grep -q "512"` matches line numbers, comments, anything
|
|
5. **~40-50% test duplication**: Same checks copy-pasted across 5-9 files
|
|
6. **Pre-commit hook only runs unit tests**: Integration, security, and system tests are NOT run before commit
|
|
7. **Hook changes bypass coverage check**: Adding `config/hooks/installed/backdoor.sh` would pass pre-commit if `config_test.bats` exists
|
|
|
|
### Missing Test Categories (None Exist)
|
|
|
|
- Cryptographic validation (cipher strings, key sizes)
|
|
- Secure Boot chain validation (PK→KEK→db hierarchy)
|
|
- Preseed syntax validation
|
|
- nftables syntax validation (`nft -c -f`)
|
|
- Sysctl parameter validity
|
|
- Idempotency testing
|
|
- Build reproducibility
|
|
- Supply chain integrity
|
|
- Privilege escalation prevention
|
|
- Network isolation verification
|
|
|
|
---
|
|
|
|
## Documentation Assessment: **ASPIRATIONAL, NOT ACCURATE**
|
|
|
|
### Compliance Claims vs Reality
|
|
|
|
| Claim | File | Reality |
|
|
|-------|------|---------|
|
|
| CMMC Level 3 | `COMPLIANCE.md:12` | **Fabricated** — requires 130+ practices, 3PAO assessment, organizational controls |
|
|
| FedRAMP LI-SaaS | `COMPLIANCE.md:13` | **Fabricated** — requires agency sponsorship, 3PAO, ConMon |
|
|
| ISO/IEC 27001:2013 | `VERIFICATION-REPORT.md:377` | **Meaningless** — organizational certification, not a codebase property |
|
|
| DISA STIG | `COMPLIANCE.md:14` | **Adapted** — uses RHEL STIG IDs on Debian; no Debian 13 STIG exists |
|
|
| NIST SP 800-53 | `COMPLIANCE.md` | **Partial** — maps ~12 controls; 800-53 has 1,000+ |
|
|
| FIPS 140-2 | `PRD CR-002` | **Claimed** — no FIPS-validated modules, uses `/dev/urandom` for keys |
|
|
|
|
### Documentation Contradictions
|
|
|
|
- `VERIFICATION-REPORT.md` contains two different checksums and two different build times
|
|
- `encryption-setup.sh:89` claims `KDF: Argon2id` — actually PBKDF2
|
|
- `COMPLIANCE.md:85` references `/usr/local/bin/knel-compliance-check.sh` — **file does not exist**
|
|
- `JOURNAL.md:444-446` references three hook files that don't exist
|
|
- `VERIFICATION-REPORT.md:26` references `config/preseed.cfg` — wrong path
|
|
|
|
---
|
|
|
|
## PRD Compliance Matrix
|
|
|
|
| Requirement | Status | Gap |
|
|
|-------------|--------|-----|
|
|
| FR-001: LUKS2 FDE (Argon2id) | **NOT MET** | Ships with PBKDF2 |
|
|
| FR-002: Debian 13 Base | **MET** | — |
|
|
| FR-003: Desktop Environment | **MET** | — |
|
|
| FR-004: Network Isolation | **PARTIAL** | Live firewall allows any WG endpoint |
|
|
| FR-005: Hardware Disabled | **MET** | WiFi/BT blacklists present |
|
|
| FR-006: SSH Client Only | **PARTIAL** | `StrictHostKeyChecking ask` not `yes`; sshd_config written |
|
|
| FR-007: System Hardening | **PARTIAL** | PAM not enforced; sudo group conflict |
|
|
| FR-008: USB Handling | **NOT MET** | Missing `noexec,nosuid,nodev`; no audit logging |
|
|
| FR-009: Immutability | **MET** | — |
|
|
| FR-010: ISO Build (Reproducible) | **NOT MET** | No reproducibility controls |
|
|
| FR-011: Host FDE Mandatory | **NOT MET** | Check exists but never called |
|
|
| FR-012: Secure Boot/UKI | **PARTIAL** | Keys unencrypted; one build path missing `module.sig_enforce` |
|
|
|
|
**PRD Compliance: 3/12 fully met, 5/12 partially met, 4/12 not met**
|
|
|
|
---
|
|
|
|
## Git History Assessment
|
|
|
|
| Category | Status | Finding |
|
|
|----------|--------|---------|
|
|
| Commit format | ✅ Good | Conventional commits with verbose bodies |
|
|
| Atomic commits | ❌ Violated | 13 fixes in single commit `62d2060` |
|
|
| Branch protection | ❌ Missing | Direct push to main; no CODEOWNERS; no CI |
|
|
| Secret exposure | ❌ Critical | Plaintext passwords permanently in history |
|
|
| Build artifacts | ✅ Clean | No ISOs/binaries committed |
|
|
| Pre-commit enforcement | ⚠️ Partial | Opt-in only; not server-side |
|
|
|
|
---
|
|
|
|
## Recommended Remediation Priority
|
|
|
|
### Phase 1 — Blockers (Must fix before ANY deployment)
|
|
|
|
| # | Finding | Effort | Impact |
|
|
|---|---------|--------|--------|
|
|
| 1 | Enforce Argon2id KDF automatically (C-01) | Medium | Fixes encryption strength |
|
|
| 2 | Call `check_host_fde()` in build path (C-02) | Trivial | Enforces supply chain security |
|
|
| 3 | Add `noexec,nosuid,nodev` to USB mounts (C-05) | Trivial | Prevents BadUSB attacks |
|
|
| 4 | Encrypt Secure Boot private keys (C-04) | Medium | Protects boot chain trust |
|
|
| 5 | Remove `--privileged` from Docker build (C-03) | Medium | Prevents container escape |
|
|
| 6 | Scrub credentials from git history (C-06) | Medium | Prevents credential exposure |
|
|
|
|
### Phase 2 — Critical Hardening (Before production use)
|
|
|
|
| # | Finding | Effort |
|
|
|---|---------|--------|
|
|
| 7 | Fix `StrictHostKeyChecking yes` (H-01) | Trivial |
|
|
| 8 | Remove sshd_config generation (H-02) | Trivial |
|
|
| 9 | Fix `sbverify` to fail on error (H-07) | Trivial |
|
|
| 10 | Add `module.sig_enforce=1` to all UKI paths (H-08) | Trivial |
|
|
| 11 | Fix sudo group conflict (M-02) | Trivial |
|
|
| 12 | Configure PAM for password enforcement (M-03) | Small |
|
|
| 13 | Initialize AIDE database (M-06) | Small |
|
|
| 14 | Add GPG signing to ISO artifacts (M-10) | Small |
|
|
| 15 | Enable GitHub branch protection | Trivial |
|
|
|
|
### Phase 3 — Test Suite Overhaul (Before trusting the test results)
|
|
|
|
| # | Finding | Effort |
|
|
|---|---------|--------|
|
|
| 16 | Rewrite tests as behavioral, not grep-based | Large |
|
|
| 17 | Add negative/adversarial testing | Large |
|
|
| 18 | Remove tautological tests (`|| true`) | Medium |
|
|
| 19 | Add CI pipeline with VM boot testing | Large |
|
|
| 20 | Deduplicate test suite | Medium |
|
|
|
|
### Phase 4 — Documentation Cleanup
|
|
|
|
| # | Finding | Effort |
|
|
|---|---------|--------|
|
|
| 21 | Remove fabricated compliance claims | Small |
|
|
| 22 | Fix VERIFICATION-REPORT contradictions | Small |
|
|
| 23 | Remove phantom file references | Small |
|
|
| 24 | Add threat model document | Medium |
|
|
|
|
---
|
|
|
|
## Positive Findings (What's Done Well)
|
|
|
|
1. **JOURNAL.md is genuinely excellent** — 13 proper ADRs, honest self-criticism, append-only discipline
|
|
2. **Package pinning in Dockerfile** — All build dependencies pinned to specific versions
|
|
3. **`.gitignore` is comprehensive** — No build artifacts or secrets committed
|
|
4. **Security hardening coverage is broad** — Kernel, sysctl, services, mount, sudo, audit all addressed
|
|
5. **SDLC process is well-documented** — Even if enforcement is incomplete, the process is sound
|
|
6. **Pre-commit hook exists** — Opt-in but provides a foundation for enforcement
|
|
7. **Defense-in-depth thinking** — Multiple layers of security controls throughout
|
|
8. **No binary artifacts in git** — Clean separation of source and output
|
|
9. **Wifi/BT blacklisting** — Comprehensive module blacklists for wireless hardware
|
|
10. **Immutable package management** — `disable-package-management.sh` properly locks down apt/dpkg
|
|
|
|
---
|
|
|
|
## Final Assessment
|
|
|
|
### Is This Production Ready for Tier0 Infrastructure?
|
|
|
|
**No.**
|
|
|
|
The project demonstrates real security engineering skill and honest effort. The architecture is sound in principle. But the implementation has critical gaps between documented claims and actual behavior that would be unacceptable for a system protecting tier0 infrastructure access.
|
|
|
|
The most dangerous aspect is **false confidence**: the test suite says 786 tests pass, the verification report says everything is ✅, and the compliance matrix claims CMMC L3 / FedRAMP compliance. None of these are accurate. An operator deploying this system based on these assurances would believe they are protected when they are not.
|
|
|
|
**Specifically, as a tier0 access terminal:**
|
|
- The disk encryption uses a weaker KDF than documented
|
|
- USB devices can execute arbitrary code
|
|
- The build chain can be compromised via the unencrypted build host
|
|
- Secure Boot keys are unprotected
|
|
- There are no behavioral tests proving any security property actually works
|
|
- The compliance framework is aspirational documentation, not verified implementation
|
|
|
|
### Estimated Effort to Production-Ready
|
|
|
|
| Phase | Effort | Timeline |
|
|
|-------|--------|----------|
|
|
| Phase 1 (Blockers) | ~40 hours | 1-2 weeks |
|
|
| Phase 2 (Hardening) | ~30 hours | 1-2 weeks |
|
|
| Phase 3 (Test overhaul) | ~60 hours | 2-3 weeks |
|
|
| Phase 4 (Docs cleanup) | ~20 hours | 1 week |
|
|
| **Total** | **~150 hours** | **5-8 weeks** |
|
|
|
|
### Recommendation
|
|
|
|
**Do not deploy.** Fix Phase 1 blockers first. Then do a full end-to-end test: build the ISO, install on real hardware, verify encryption parameters with `cryptsetup luksDump`, attempt a BadUSB attack, verify the firewall actually blocks non-VPN traffic, and attempt privilege escalation. Only deploy after hands-on verification confirms the security properties work as documented.
|
|
|
|
---
|
|
|
|
*Report generated: 2026-05-08*
|
|
*Auditor: Senior Security Engineer / Technical Operations Manager*
|
|
*Review classification: CONFIDENTIAL*
|