feat(diagnose): offer a report the user sends themselves - #462
Draft
volen-silo wants to merge 1 commit into
Draft
volen-silo wants to merge 1 commit into
volen-silo wants to merge 1 commit into
Conversation
volen-silo
force-pushed
the
feat/doctor-report-approved-architectures
branch
from
September 30, 2026 10:17
d9ac489 to
db0d18e
Compare
volen-silo
force-pushed
the
feat/doctor-report-sent-by-the-user
branch
3 times, most recently
from
September 30, 2026 11:32
e49f924 to
1573c97
Compare
A report reaches AMD because a person read it and sent it. This builds the prefilled mail, decides whether a mail client may be started, and offers it behind `--send`. It holds nothing that could send anything: no SMTP client, no credential, nothing to authenticate with. That is the design, not an omission, so the absence is worth keeping visible. The destination is a mailbox fixed in code. An address a caller can choose is an address an attacker can choose, and the user would be reading a report they believe goes to AMD while it goes somewhere else. The address is pinned by a test as a literal, because a typo there sends every report somewhere nobody is watching and nothing else would notice. A mailbox has no labels, so the classification an issue would carry in metadata moves to the subject line, which is the only place a mail rule and a person scanning an inbox can both read. It is ordered most stable first, so a sorted inbox groups by cause and then by machine. A subject is as public as the body and travels further, since it shows in an inbox list, so a field not approved for the body is not approved for the subject either, and a test plants markers to prove none reaches it. `--send` requires `--report`, which makes "the content is shown first" structural rather than a promise: the flag that sends a report cannot be given without the flag that prints it. It refuses `--json`, because that combination is for scripts and a script is not a person who can read a mail before sending it. Two conditions gate a mail client, and both are checked. The user has to have asked, and the machine has to look like a desktop they are at. Every unknown answers no, a session reached over SSH answers no whatever DISPLAY says, and an empty variable is not evidence. The printed form names the address on its own rather than only inside the link, because a server or a container usually has no mail client and the person has to send it by hand. The link body is compared against the report as JSON rather than as a `Report`. Deserializing discards fields the struct does not know, so a body carrying a hostname beside the approved fields round-trips to an identical `Report` and passes. A planted leak survived the first version of that test. The opener moves behind a trait and out of the ComfyUI path, which held the only implementation. Callers take the trait, so a test can observe that a client was deliberately not started, which is otherwise indistinguishable from one that failed. There is now exactly one opener in the tree. One cost is worth stating where it is incurred rather than in a footnote: a mail carries the sender's address, which the report itself deliberately does not. The transport identifies a person the payload was designed not to. Signed-off-by: Eugene Volen <Eugene.Volen@amd.com>
volen-silo
force-pushed
the
feat/doctor-report-sent-by-the-user
branch
from
October 1, 2026 12:16
1573c97 to
eb32981
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #452. Review that one first; this diff only makes sense on top of it, and the base changes to
mainonce it lands.Summary
--send, which requires--reportand offers that mail.rocm-core, out of the ComfyUI path that held the only implementation. There is now exactly one opener in the tree.rocm diagnose --reportnow ends with the real delivery decision instead of the hardcoded "Sending is not implemented yet".Why. A report reaches AMD because a person read it and sent it. That rules out anything automatic, and it rules out the CLI holding a credential of any kind.
Risk: low. The ComfyUI move is logic transplanted verbatim and its tests pass unchanged. The rest is new surface behind a new flag.
Destination
Reports go to a mailbox, fixed in code. An address a caller can choose is an address an attacker can choose, and the user would be reading a report they believe goes to AMD while it goes somewhere else. The address is pinned by a test as a literal, because a typo there sends every report somewhere nobody is watching and nothing else would notice.
An earlier revision of this branch targeted a private issue tracker. That was changed deliberately. The report content is unaffected either way; only the transport differs.
What a mailbox costs, and what this does about it
No labels. The classification an issue would carry in metadata moves to the subject line, which is the only place a mail rule and a person scanning an inbox can both read:
Ordered most stable first, so a sorted inbox groups by cause and then by machine.
A subject is as public as a body, and travels further, since it shows in an inbox list. So a field that is not approved for the body is not approved for the subject. A test plants markers for the user name, the ROCm path, the CPU model, the GPU marketing name and the PCI address, and asserts none of them reaches the subject.
Mail clients are often absent on servers, lab machines and containers, which is a large part of the target population. There, a
mailto:link does nothing. The printed form therefore names the address on its own, not only inside the link, so the person can send the mail by hand.A mail identifies its sender. The report carries no user name, no host name and no machine identifier, deliberately. A mail envelope carries the sender's address whatever the body says. The transport identifies a person the payload was designed not to. This is stated in the README where a user decides whether to send, rather than left to be discovered.
Non-obvious decisions
--sendrequires--report. That makes "the content is shown first" structural rather than a promise: the flag that sends a report cannot be given without the flag that prints it. It refuses--json, because that combination is for scripts, and a script is not a person who can read a mail before sending it.Two conditions gate a mail client, checked separately. The user has to have asked, and the machine has to look like a desktop they are at. A display is permission from the environment, never from the person, so adding one to a machine must not change what
--reportalone does. Every unknown answers no, SSH answers no whateverDISPLAYsays, and an empty variable is not evidence.The link body is compared as JSON, not as a
Report. Deserializing into the struct discards fields it does not know, so a body carrying a hostname beside the approved fields round-trips to an identicalReportand passes. A planted leak survived the first version of that test. This seam is where an extra useful-looking detail would get added, so the check has to be exact.The address is not percent-escaped; the query values are. RFC 6068 allows
@and.unescaped in the address part, and an escaped@there is handled poorly by some clients. That is safe because the address is a compile-time constant this crate owns, never text read from a machine.Deciding and acting are separate functions. The decision is tested in
rocm-coreacross many environments; acting on it is tested against an opener that does not exist, on a machine with no mail client. A function that did both could be verified on neither.Not in this PR
Test plan
cargo test --workspace --all-targets: 3187 pass, 0 fail.cargo clippy --workspace --all-targets -- -D warningsandcargo fmt --all --checkclean, gated on exit status.Every new guard was checked by mutation, so the tests are known to fail when the thing they describe breaks:
hostnamefield into itunrecognisedShowTwo of those rows exist because the first version of the test did not catch them.
The Linux-only assertions carry
#[cfg(target_os = "linux")], becausemay_open_browsertreats Windows and macOS as a desktop outright and there is no environment there that means "not a desktop". An earlier revision asserted the Linux rules unconditionally and failed the Windows lane after passing locally. Verified by simulating that lane: forcing the platform gate and compiling out the Linux guards, the remaining tests pass.Not verified, and cannot be here: that a real mail client opens, and that mail reaching the mailbox is readable after a client has wrapped and quoted it.