Security and audit
A patient index handles the most identifying data in a health system, so both crates are built to keep it out of anywhere it was not sent. This page says what they guarantee today. The server’s own access control and audit are planned in the v0.0.3 milestone.
No identifying data where it was not sent
- Every identifier, every demographic criterion, a pseudonymised BSN, a SAML
assertion and a token travels as a
secrecy::SecretStringor in a type that redacts its content inDebugand has noDisplay. - No error carries a value, a request URL or body, or the free text the other server wrote, so an error you log cannot leak one.
- A client’s
Debugshows its URLs with the userinfo replaced by***and leaves out thereqwest::Client, whose default headers may hold a credential. - Build each
reqwest::Clientyou pass in withredirect::Policy::none(): the request carries the identifier, and a redirect would send it on. - Lookups by a patient identifier use
POST. A PDQm query sends its criteria in the request body. FerroHEALTH clients call a PIXm Manager byPOSTwith aParametersbody (ihe_iti::pixm::Invocation::Post, FHIR R4 Operations §3.2.0.1), so a BSN never appears in a URL. FerroPIX’s planned PIX Manager is to accept$ihe-pixbyGET(ITI-83) and byPOST, and to keep no URL query in a request log (FerroHEALTH/FerroPIX#52). A proxy in front of any Manager must not log query strings, because a client that uses theGETputs the identifier there. - The PMIR feed drops every demographic as it reads an ITI-93 message.
Access tokens
The PIXm, PDQm, mCSD and PMIR clients send the credential their
reqwest::Client carries in its default headers or, built
.with_authorizer(…), ask an ihe_iti::authorizer::Authorizer for the
headers of every request: an OAuth 2.0 access token incorporated as IUA
ITI-72 §3.72.4.2 asks. After a 401 the request is sent once more with new
headers (§3.72.4.3), never more than twice in all. The authorizer is handed
the request URL without its query, so no identifier or search criterion
reaches it, and a request it cannot authenticate is not sent.
nl-generic-functions has the same seam for the Generic Functions, behind
its authorizer feature.
Audit
The audit trail is ihe-atna, the
family’s audit crate from FerroAUDIT: ATNA ITI-20 with its syslog sender,
spool and forwarder, and the BALP FHIR feed. ihe-iti writes the record
each profile defines for its own transactions on it:
balp: every PIXm, PDQm, mCSD and PMIR client takes anihe_atna::balp::AuditRecorderthrough.audited(…)and records the BALPAuditEventof each transaction.atna:XcpdClient::auditedhands the ITI-55 Initiating Gateway audit message of every exchange to a recorder, written as the DICOM audit message inihe-atna’s ATNA model.
The client waits for the recorder before it returns the answer, the exchange’s timeout bounds the record too, and a record the recorder refuses fails the exchange as an audit failure, so no answer is used without its audit. An audited exchange’s record names the user it was made for.
Reporting a vulnerability
Report a vulnerability privately through GitHub’s
private vulnerability reporting,
never in a public issue. The supported versions and the response times are
in
SECURITY.md,
and the manufacturer’s vulnerability handling, disclosure and advisories are
in the family book’s security page.