Skip to content

fix(diag): keep dezhban's own file paths out of the hostname pass - #70

Merged
Behnam-RK merged 2 commits into
mainfrom
fix/sock-is-not-a-hostname
Sep 13, 2026
Merged

Behnam-RK merged 2 commits into
mainfrom
fix/sock-is-not-a-hostname

Conversation

@Behnam-RK

@Behnam-RK Behnam-RK commented Sep 13, 2026

Copy link
Copy Markdown
Owner

Closes #68.

doctor's control check names the socket it probed, and a default (redacted) bundle reported it as:

"summary": "unreachable (/var/db/dezhban/host-1) — dezhban is not running; routine ops need sudo."

The path is the answer to "which socket did it probe". Replacing it throws the diagnosis away and hides no identity — the direction docs/contribute/testing.md calls out by itself — and it counts a hostname in the legend that stands for a filename.

Why

control.sock satisfies hostRe (dotted, alphabetic last label), and keepHost kept neither it nor dezhban.lock, whose path a startup failure carries into the log.

By name, not by file ending

The obvious fix is .sock and .lock in keptSuffixes. That is wrong, and this PR's first commit made the mistake before its second reverted it.

control.socket is a config key. A suffix rule keeps whatever it points at, so a socket sitting beside the VPN it serves — /var/run/nordvpn.sock — would have shipped verbatim in a default bundle, naming the provider as plainly as a server address does. That is rule 2 on keptSuffixes' own doc comment, and exactly why .conf and .ovpn are kept off that list.

So: a new exact-match keptNames, consulted by keepHost beside allowedHosts. control.sock is controlSocketPath's default basename and dezhban.lock is a constant — both are dezhban's, neither is configurable, and a socket the user renamed goes back to being redacted.

.zip is deliberately NOT added

The report bundle's own filename ends in .zip, which makes it the obvious next thing someone adds — and it is what rule 1 refuses, because .zip is a delegated gTLD. TestADelegatedTLDIsNeverTreatedAsAFileExtension fails on mullvad.zip if anyone tries: a real provider name waved straight through by a suffix that looks like a file extension. .pkg is left out for want of a root-zone check rather than a decision; it reaches no bundle entry.

Not a regression

Reproduced against v0.14.0's internal/redact, so it predates #67 and the v0.15.0 release:

v0.14.0 doctor summary -> "reachable (/var/db/dezhban/host-1, group \"vpnadmins\")"

Found while probing the redactor after that release.

Review loop

Round Reviewer Findings Pre-existing Loop-introduced Defects fixed
0 me, before asking 1 0 1 1
1 read-only subagent 0 0 0 0

The loop's own finding is the .sock/.lock suffix mistake above — named rather than absorbed, because it is the interesting part of this change and the first commit on the branch still contains it.

Verification

task check green; CI green. Every test was run against the code it guards:

  • without keptNames: control.sock was treated as a hostname: "wrote host-1", the socket path returns /var/db/dezhban/host-1, and the legend reads 2 distinct hostnames → host-1 … host-2
  • with the reverted suffix version: nordvpn.sock survived, mullvad.sock survived, proton.lock survived
  • with .zip wrongly added: mullvad.zip survived — a delegated TLD was treated as one of dezhban's file endings

Plus a real dezhban report, whose doctor.json now reads unreachable (/var/db/dezhban/control.sock) with nothing else leaked.

Still open from the same probe

#69control.group ships unredacted in both config.json and doctor's prose. Filed as a decision rather than a bug, and deliberately untouched here: a one-sided fix would leave the two entries disagreeing about the same value.

🤖 Generated with Claude Code

`doctor`'s control check names the socket it probed, and a default bundle
reported it as `/var/db/dezhban/host-1`. The path is the answer to "which
socket" — replacing it throws the diagnosis away and hides nothing, the
direction docs/contribute/testing.md names by itself. It also counted a hostname
in the legend that stands for a filename.

`control.sock` satisfies hostRe (dotted, alphabetic last label) and keptSuffixes
did not list `.sock`. Nor `.lock`, which has the same problem wherever a startup
failure carries the run lock's path into the log. Both pass the two rules that
list states: neither is a delegated TLD, and both names are dezhban's.

Pre-existing — reproduced against v0.14.0's internal/redact, so it is not a
regression from #67; found while probing the redactor after that release.

`.zip` is NOT added and the comment now says why, because the bundle's own
filename ends in it and that makes it the obvious next thing to add: `.zip` is a
delegated gTLD, so rule 1 refuses it. TestADelegatedTLDIsNeverTreatedAsAFileExtension
fails on `mullvad.zip` if anyone tries — a real provider name waved through by a
suffix that looks like a file extension, which is the whole reason that rule
exists. `.pkg` is left out for want of a root-zone check rather than a decision.

Verified: task check, and a real `dezhban report` whose doctor.json now reads
`unreachable (/var/db/dezhban/control.sock)` with nothing else leaked.

Closes #68

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Behnam-RK Behnam-RK added the run-ci Run CI on this PR (gates .github/workflows/ci.yml) label Sep 13, 2026
Self-review of the previous commit, before anyone else read it. It added `.sock`
and `.lock` to keptSuffixes, and that breaks rule 2 on that very list — the part
in front has to be dezhban's, not the user's.

`control.socket` is a config key. A suffix rule keeps whatever it points at, so
a socket sitting beside the VPN it serves — `/var/run/nordvpn.sock` — would have
shipped verbatim in a default bundle. That names the provider as plainly as a
server address does, and it is exactly the trap `.conf` and `.ovpn` are kept off
the list for.

So: an exact-name map instead. `control.sock` is controlSocketPath's default
basename and `dezhban.lock` is a constant; both are ours, neither is
configurable, and a socket the user renamed goes back to being redacted.

TestASocketTheUserNamedIsStillRedacted fails against the suffix version on
nordvpn.sock, mullvad.sock and proton.lock.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Behnam-RK
Behnam-RK merged commit f4ba2cc into main Sep 13, 2026
6 checks passed
@Behnam-RK
Behnam-RK deleted the fix/sock-is-not-a-hostname branch September 13, 2026 08:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

run-ci Run CI on this PR (gates .github/workflows/ci.yml)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

redact: control.sock is redacted as a hostname, so the control check's path reads as host-N

1 participant