DEV Community

Cover image for A conformant DICOM de-identifier silently strips your image's signature

A conformant DICOM de-identifier silently strips your image's signature

If you sign DICOM objects and then de-identify them, the signature is gone on the other side. Nobody re-signs it, nobody logs it, and the receiver has no way to tell the image was ever signed. I measured this, and it's quieter than I expected.

Here's the setup. DICOM has a digital signature mechanism in PS3.15: a Digital Signatures Sequence that attests where an object came from and that it hasn't been altered. De-identification is the step you run before images leave your four walls, for research, for AI training, for a data-sharing deal. It rewrites the object to strip patient identifiers.

I built a small Secondary Capture image, signed content the de-identifier doesn't touch (the pixel data, the dimensions, the modality), and ran it through a real de-identifier. Then I checked whether the signature survived.

tool Digital Signatures Sequence after de-id
dcm4che deidentify (PS3.15 Basic Profile) removed
dicognito kept

dcm4che's deidentify, which implements the PS3.15 Basic Confidentiality Profile, removed the Digital Signatures Sequence outright. It blanked the patient name and ID, as it should. But it left the signed image content untouched, which means the signature it deleted would still have verified. It didn't re-sign. It even left an orphaned MAC Parameters Sequence pointing at a signature that no longer exists.

dicognito, a lighter anonymizer that only targets specific identifiers, left the signature in place.

So two conformant tools disagree on whether your image keeps its provenance, and you find out which one you have by running it, not by reading the spec.

This isn't a bug

The part that caught me is that dcm4che is right. PS3.15 says to remove the Digital Signatures Sequence during de-identification, because the Certificate of Signer can itself carry identifying information. And it says, in as many words, that re-signing by the de-identifier is not required. So the standard's own recipe deletes the origin proof and leaves restoring it optional. The tool is doing exactly what it's told.

There's no attacker anywhere in this. A legitimate sender signs, a legitimate pipeline de-identifies, and the proof is gone. That's why it's easy to miss. Nothing in the flow looks wrong.

Where it bites, and where it doesn't

If you don't sign your DICOM objects, none of this touches you today, and most shops don't sign. I'll say that plainly, because the opposite would be scaremongering. But the moment you do sign, for provenance, for integrity, for a data-authenticity claim in a regulatory file, a downstream de-identification step quietly undoes it. And de-identification is exactly where your AI training and validation data comes from. An image that entered your training set can't be traced back to the device that produced it.

Under FDA Section 524B this reads as a data-integrity control gap for your Security Risk Management, not a product vulnerability. It's the kind of thing a threat model should name, then either accept with eyes open or fix.

The fix is boring. Re-sign after de-identification. The standard lets you, it just doesn't make you. Where you can't, carry provenance in a record the de-identifier preserves, and have downstream consumers treat a missing signature as unverified rather than as absent.

Run it yourself

Sign a DICOM object, then:

# de-identify with a PS3.15-conformant tool
docker run --rm -v "$PWD":/w -w /w dcm4che/dcm4che-tools \
    deidentify /w/signed.dcm /w/out.dcm

# did the signature survive?
python -c "import pydicom; d=pydicom.dcmread('out.dcm'); \
    print('signature present:', 0xFFFAFFFA in [e.tag for e in d])"
Enter fullscreen mode Exit fullscreen mode

If the Digital Signatures Sequence is gone and nothing re-signed the object, this applies to you.

The bigger pattern

This is one instance of something I've been measuring across protocols: authentication or integrity material that a conformant intermediary drops when it parses a message and rebuilds it, with no attacker at the moment of removal. MAVLink relays, SOME/IP gateways, gRPC-JSON transcoders, and now DICOM de-identification. Same shape, different boundary.

The full threat-catalogue entry, written to paste into a 524B risk file, with the exact test: https://github.com/cleitonaugusto/CleitonQ/blob/main/docs/dicom-provenance-threat-entry.md

The class write-up across the other protocols, including the results that argue against the thesis: https://doi.org/10.5281/zenodo.21840073

Top comments (0)