Skip to content

Apply what it diagnoses: sshd enforce, firewall enable parity - #12

Merged
edimarlnx merged 2 commits into
mainfrom
apply-coverage
Sep 1, 2026
Merged

edimarlnx merged 2 commits into
mainfrom
apply-coverage

Conversation

@edimarlnx

Copy link
Copy Markdown
Contributor

Five of the eight probes could name a problem and then hand the reader
somewhere else for a one-line change. ufw-enable, timer:<unit> and
sysctl:<key> were the only things this tool would run; everything else —
a weak sshd keyword, a stopped firewalld, an empty nftables ruleset, a
service listening on the network — ended at a status-line hint saying it
belonged to another tool.

The rule for what may be offered has not moved. A change is a command this
tool runs only when it can be previewed in full, read at a glance and
undone the same way.

What is new

Action What runs
sshd:<keyword> sshd -t -f <staged>, install -m 600 <it> /etc/ssh/sshd_config.d/50-tui-secure.conf, systemctl reload sshd
firewalld-enable systemctl enable --now firewalld
nftables-enable systemctl enable --now nftables
port:<n> systemctl disable --now <the unit behind the socket>

Six sshd keywords are owned: PermitRootLogin, PasswordAuthentication,
PermitEmptyPasswords, PubkeyAuthentication, MaxAuthTries,
X11Forwarding. The drop-in is regenerated whole from what it held before,
so a keyword agreed to earlier survives and one this tool does not own is
not carried forward — which is what makes the file shown on the dialog the
whole file that will exist. The check runs first, so a file sshd refuses
never reaches /etc. The unit name is the one the probe detected (sshd,
or ssh on Debian), mirroring tui-ssh.

The probe also grades PermitEmptyPasswords now, which it read and ignored
before.

What it refuses

  • Passwords off with no key anywhere. /etc/passwd is walked for an
    authorized_keys with something in it. None, or only root's while
    PermitRootLogin goes to no in the same change, is refused with the
    reason. A home that could not be read is not an account without a key:
    those are named on the dialog instead.
  • Both authentication methods off. Nothing could log in at all.
  • nftables.service with no ruleset, or one nft -c -f will not
    parse. A loader service enabled with nothing to load is a green row on an
    open machine.
  • The ssh server, as something to stop, whatever port it is found on.

--demo has parity: the sample machine offers the sshd and port actions,
and applying them turns the rows green the way the real ones would.

Checked

  • make check (gofmt, go vet, check-exec.sh, golangci-lint with gosec
    and errcheck, tests) green.
  • New builder tests cover the exact argv of all five new commands, the
    injection guards on every argument, the lockout matrix, the include-order
    warning, and both fake-parity paths.
  • Three new fuzz targets, run past the seed corpus locally:
    FuzzRenderSSHDDropIn (the file this tool wrote last time is input to the
    next preview), FuzzParseCgroupUnit (its output goes into a
    systemctl disable argv) and FuzzParsePasswdLoginAccounts.
  • test/smoke.sh on Fedora 42: 22 passed, 4 failed — the same four
    --report failures main has today, untouched by this branch.
  • Screenshots re-rendered; the sshd frame was stale.

Co-Authored-By: Claude Fable 5.1 noreply@anthropic.com

🤖 Generated with Claude Code

edimarlnx and others added 2 commits September 1, 2026 19:11
Five of the eight probes could name a problem and then hand the reader
somewhere else for a one-line change. That gap is what this closes: a
posture tool that measures a weak sshd keyword, a stopped firewalld and a
service listening on the network, and then offers nothing for any of them,
is asking its reader to go and do by hand exactly what it has just proved
needs doing.

The rule for what may be offered has not moved. A change is a command this
tool will run only when it can be previewed in full, read at a glance and
undone the same way. What is new:

  - sshd:<keyword> sets one of six keywords through
    /etc/ssh/sshd_config.d/50-tui-secure.conf, a file this tool owns and
    regenerates whole from what it held before. The plan is three commands
    and the check comes first, so a file sshd refuses never reaches /etc.
  - firewalld and nftables get the enable action ufw already had, with the
    same warning about the session it can end. nftables refuses without a
    ruleset file, or with one nft will not parse: a loader service enabled
    with nothing to load is a green row on an open machine.
  - port:<n> stops the unit behind a listening socket, found in
    /proc/<pid>/cgroup rather than by asking systemd a second time. The ssh
    server is never offered.

The refusals are the part worth reading. Turning passwords off is refused
when no account on the machine holds an authorized key — and when the only
one that does is root while PermitRootLogin is going to no in the same
change. A home directory that could not be read is not an account without a
key: those are named on the dialog instead, because guessing in either
direction is worse than saying which homes could not be looked into.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MCypLQF5AD8JD831Ea9S9q
The README and the manifest still said "three fixes", which was true until
the commit before this one. They now name the whole set, and give the
refusals a section of their own: a reader deciding whether to trust this
tool with sshd deserves to know, before running it, that turning passwords
off on a machine with no key anywhere is a thing it will not do.

The smoke test now checks both drop-ins are absent after a read-only run,
not just the sysctl one. The main and sshd screenshots are re-rendered:
the sshd probe grades PermitEmptyPasswords now, so the frame was stale.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MCypLQF5AD8JD831Ea9S9q
@edimarlnx
edimarlnx merged commit 2dac584 into main Sep 1, 2026
8 checks passed
@edimarlnx
edimarlnx deleted the apply-coverage branch September 1, 2026 22:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant