Fix audit findings: lockout guards, apt hardening, injection & integrity #29

Merged
kleb merged 4 commits from fix/audit-round-3 into main 2026-07-12 17:15:22 +02:00
Owner

Summary

Fixes the findings from the round-3 audit (Security / Reliability / Performance) on the kInit installer. 18 findings across 10 scripts, plus a regenerated integrity manifest.

Highlights

Lockout / access safety

  • uninstall.sh reverts root's login shell from fish to /bin/bash before advising fish removal (previously following the uninstaller's own guidance could break root login).
  • HOME normalized to root's real home (getRootHome via getent passwd root) so authorized_keys, cron scripts and shell config never land in an invoking user's home under sudo/su.
  • system.sh unions (never clobbers) a custom AuthorizedKeysFile so the installed root key is honored without locking out root or centralized-key accounts; the sshd -T probe is pipefail-safe.

Security

  • KINIT_SKIP_BOOTSTRAP_VALIDATION now requires an interactive TTY + I UNDERSTAND THE RISKS, matching the sibling integrity bypasses.
  • software.sh requires a strict-charset hostname before baking it into the root cron script apt.sh (closes a command-injection sink on the non-interactive path).
  • Run-log command lines are redacted; zabbix.sh rejects empty/bad-magic vendor downloads; checksum.sh verifies its pin edits landed.

Reliability

  • Installer apt calls get DPkg::Lock::Timeout + DEBIAN_FRONTEND=noninteractive so first-boot apt-daily lock contention doesn't abort provisioning.
  • update.sh: a failed apt-get update no longer suppresses the upgrade; setsid/timeout reordered so the timeout actually bounds apt (also clean.sh).
  • Validate SWAP_SIZE / PermitRootLogin / LoginGraceTime; anchor uninstall cron cleanup to full installed paths.

Perf / correctness

  • printf instead of echo -e in log helpers; case-insensitive security-update counting (apt.sh, motd.sh); corrected a misleading batching comment.

Verification

  • bash -n clean on all edited scripts; shellcheck introduced no new diagnostics.
  • Integrity chain rebuilt: sha256sum -c checksums.sha256 -> all 62 files OK; both embedded bootstrap hashes in kInit.sh match.
  • Isolated-logic tests pass for redaction, the hostname guard, the AuthorizedKeysFile decision table (incl. pipefail-safety), and the download guards.

Notes / deliberate non-changes

  • Per-log-line date fork left as-is (negligible for a one-shot installer; ms timestamps need date).
  • --base-url http:// still accepted (local testing relies on it; integrity is enforced by the pinned hash).
  • Not addressed here (posture, opt-in): minisign signing is off by default, so the trust root is integrity-only. Recommend enabling KINIT_MINISIGN_PUBKEY for production.
## Summary Fixes the findings from the round-3 audit (Security / Reliability / Performance) on the kInit installer. 18 findings across 10 scripts, plus a regenerated integrity manifest. ## Highlights **Lockout / access safety** - `uninstall.sh` reverts root's login shell from fish to `/bin/bash` before advising fish removal (previously following the uninstaller's own guidance could break root login). - `HOME` normalized to root's real home (`getRootHome` via `getent passwd root`) so `authorized_keys`, cron scripts and shell config never land in an invoking user's home under `sudo`/`su`. - `system.sh` **unions** (never clobbers) a custom `AuthorizedKeysFile` so the installed root key is honored without locking out root or centralized-key accounts; the `sshd -T` probe is pipefail-safe. **Security** - `KINIT_SKIP_BOOTSTRAP_VALIDATION` now requires an interactive TTY + `I UNDERSTAND THE RISKS`, matching the sibling integrity bypasses. - `software.sh` requires a strict-charset hostname before baking it into the root cron script `apt.sh` (closes a command-injection sink on the non-interactive path). - Run-log command lines are redacted; `zabbix.sh` rejects empty/bad-magic vendor downloads; `checksum.sh` verifies its pin edits landed. **Reliability** - Installer `apt` calls get `DPkg::Lock::Timeout` + `DEBIAN_FRONTEND=noninteractive` so first-boot `apt-daily` lock contention doesn't abort provisioning. - `update.sh`: a failed `apt-get update` no longer suppresses the upgrade; `setsid`/`timeout` reordered so the timeout actually bounds apt (also `clean.sh`). - Validate `SWAP_SIZE` / `PermitRootLogin` / `LoginGraceTime`; anchor uninstall cron cleanup to full installed paths. **Perf / correctness** - `printf` instead of `echo -e` in log helpers; case-insensitive security-update counting (`apt.sh`, `motd.sh`); corrected a misleading batching comment. ## Verification - `bash -n` clean on all edited scripts; `shellcheck` introduced no new diagnostics. - Integrity chain rebuilt: `sha256sum -c checksums.sha256` -> all 62 files OK; both embedded bootstrap hashes in `kInit.sh` match. - Isolated-logic tests pass for redaction, the hostname guard, the `AuthorizedKeysFile` decision table (incl. pipefail-safety), and the download guards. ## Notes / deliberate non-changes - Per-log-line `date` fork left as-is (negligible for a one-shot installer; ms timestamps need `date`). - `--base-url http://` still accepted (local testing relies on it; integrity is enforced by the pinned hash). - Not addressed here (posture, opt-in): minisign signing is off by default, so the trust root is integrity-only. Recommend enabling `KINIT_MINISIGN_PUBKEY` for production.
Addresses the round-3 audit (security/reliability/performance):

- Normalize HOME to root's real home (getRootHome via getent) so
  authorized_keys, cron scripts and shell config never land in an
  invoking user's home under sudo/su (kInit.sh, utils.sh, uninstall.sh).
- uninstall.sh: revert root's login shell from fish to /bin/bash before
  advising fish removal; anchor cron cleanup to full installed paths.
- Gate KINIT_SKIP_BOOTSTRAP_VALIDATION behind an interactive TTY + explicit
  confirmation, matching the other integrity bypasses.
- Installer apt calls get DPkg::Lock::Timeout and DEBIAN_FRONTEND=noninteractive
  so first-boot apt-daily lock contention no longer aborts provisioning.
- update.sh: a failed 'apt-get update' no longer suppresses the upgrade;
  reorder setsid/timeout so the timeout actually bounds apt (update.sh, clean.sh).
- software.sh: require a strict-charset hostname before baking it into the
  root cron script apt.sh (closes a command-injection sink).
- system.sh: validate SWAP_SIZE / PermitRootLogin / LoginGraceTime; union
  (never clobber) a custom AuthorizedKeysFile so the installed root key is
  honored without locking out root or central-key accounts.
- Redact run-log command lines; printf instead of echo -e in log helpers;
  case-insensitive security-update counting (apt.sh, motd.sh).
- zabbix.sh: reject empty/bad-magic vendor downloads; checksum.sh verifies
  its pin edits landed.
- Regenerated checksums.sha256 and the embedded bootstrap hashes.
Collaborator

kReview review

Verdict: no findings

No findings to address in the reviewed diff.

Overall risk is low; no concrete regressions are provable from the supplied diff.

Reviewed by kReview at 2ec1e57c15. This comment is conservative and based only on the PR diff and metadata.

Est. cost ~$0.59 total (95.3k in / 3.7k out) · this run ~$0.13 (23.8k in / 359 out) / gpt-5.6-sol.

<!-- codex-forgejo-review --> <!-- codex-forgejo-review-head:2ec1e57c156f966fff6cddb819d9750e27ca47d5 --> ## kReview review **Verdict:** no findings No findings to address in the reviewed diff. Overall risk is low; no concrete regressions are provable from the supplied diff. _Reviewed by kReview at `2ec1e57c15`. This comment is conservative and based only on the PR diff and metadata._ _Est. cost ~$0.59 total (95.3k in / 3.7k out) · this run ~$0.13 (23.8k in / 359 out) / gpt-5.6-sol._ <!-- codex-forgejo-review-state:eyJoZWFkU2hhIjoiMmVjMWU1N2MxNTZmOTY2ZmZmNmNkZGI4MTlkOTc1MGUyN2NhNDdkNSIsInN1bW1hcnkiOiJPdmVyYWxsIHJpc2sgaXMgbG93OyBubyBjb25jcmV0ZSByZWdyZXNzaW9ucyBhcmUgcHJvdmFibGUgZnJvbSB0aGUgc3VwcGxpZWQgZGlmZi4iLCJmaW5kaW5ncyI6W10sImN1bXVsYXRpdmVDb3N0Ijp7InVzZCI6MC41ODg0MDUwMDAwMDAwMDAxLCJpbnB1dFRva2VucyI6OTUzMjUsIm91dHB1dFRva2VucyI6MzcyNiwibW9kZWwiOiJncHQtNS42LXNvbCJ9fQ== -->
The manifest generator's find swept the untracked .codegraph and .serena
tool-state dirs (mutable db/WAL/log/pid) into checksums.sha256, so
'sha256sum -c' would fail after any daemon activity or on a clean checkout.
Add both to the generator ignoreList (matching .cursor/.vscode) and
regenerate the manifest and embedded hash. Addresses PR review.
The LoginGraceTime validation regex only allowed a single number+unit, so
valid OpenSSH durations like 1h30m were rejected and silently downgraded to
60. Broaden to one-or-more number+unit components. Addresses PR review.
A host with 'AuthorizedKeysFile none' would have received the invalid
'none .ssh/authorized_keys' (none cannot be combined with a path), failing
sshd config validation. Replace 'none' with .ssh/authorized_keys so the
installed root key is honored. Addresses PR review.
kleb merged commit 514a39440e into main 2026-07-12 17:15:22 +02:00
kleb deleted branch fix/audit-round-3 2026-07-12 17:15:22 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kleb/kInit!29
No description provided.