All Advisories

dcm4chee-arc-light

Remote Code Execution via Storage-Descriptor File Write

A storage location defines where the archive writes the objects it receives. Both its filesystem root and its path template are configuration-controlled, and neither was validated against a scheme allowlist nor against a containment boundary, so configuration alone determined the destination of a stored object. An attacker able to write archive configuration can point a storage location at a directory the application server watches for deployments and then store an ordinary DICOM object whose payload is a deployable web application, which the server picks up and runs as the archive service account.

Authored byVolker Schönefeld, Simon WeberDisclosed 2026-08-18Fully disclosed 2026-08-31
SeverityCriticalCVSS 9.8CVSS 3.1 VectorAV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:HCWECWE-22 (Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal'))Productdcm4chee-arc-lightAffected VersionsAll 5.x releases up to and including 5.34.3.Fixed In5.35.0CVEPendingGHSAGHSA-rf29-xp3v-4wp3

Description

A storage descriptor tells the archive where to put the objects it receives. Two of its fields decide the destination: the storage URI, which is the filesystem root, and the storage path format, a template evaluated against the attributes of the object being stored. Both are ordinary configuration. The setter for the root accepts whatever it is given, with no scheme allowlist and no containment boundary:

StorageDescriptor.java:128-131

public void setStorageURIStr(String str) {
    this.storageURI = URI.create(StringUtils.replaceSystemProperties(str));
    this.storageURIStr = str;
}

View source →

At write time the root and the evaluated path template are joined and opened directly:

FileSystemStorage.java:174-181

protected OutputStream openOutputStreamA(WriteContext ctx) throws IOException {
    Path path = Paths.get(rootURI.resolve(ctx.getStoragePath()));
    Path dir = path.getParent();
    createDirectories(dir);
    while (true)
        try {
            ctx.setStoragePath(rootURI.relativize(path.toUri()).toString());
            return Files.newOutputStream(path, descriptor.getFileOpenOptions());

View source →

There is nothing to traverse out of, which is why no traversal sequence appears anywhere in this finding. An attacker who can write configuration sets the root to the directory they want and the path template to the filename they want, and the archive writes there because that is what it was told to do. The path template draws on attributes of the stored object, which the same caller supplies, so the filename and its extension are controllable too.

The step from a controlled write to code execution uses the same property of the application server as the vendor-data finding covered in the related advisory: an archive appearing in the deployments directory is picked up and deployed. Getting a deployable file there takes two properties of the store path. An Encapsulated PDF object carries its document in a bulk-data attribute, and the store re-encodes the object but copies that attribute through verbatim rather than running it past an image codec, so an embedded archive survives intact; placed as the highest-numbered element, nothing follows it in the written dataset. What lands on disk is therefore the whole DICOM object, not the archive alone. That still deploys, because an archive reader locates a ZIP's central directory from the end of the file, so the DICOM preamble and the element headers ahead of the payload are tolerated as a leading prefix.

The prefix does have a cost for the attacker, and it is worth being precise about it: the application server's deployment scanner runs a completeness check that reads a prefixed file as still being copied, so the first write does not deploy on its own. Deployment follows only once a corresponding marker file tells the scanner to proceed, which the same configuration-and-store primitive can produce. The chain is two writes rather than one, which is why the attack complexity stays low without the finding being a single request.

Code execution is the ceiling rather than the whole finding. The same primitive, used without the deployment step, writes well-formed and fully readable DICOM studies to chosen locations, which is enough to place imaging in an archive that no imaging device produced. The file open options are themselves a configuration field, so switching them from the default create-if-absent to a truncating mode through the same interface turns the primitive from placing new files into overwriting existing ones.

The fix resolves each storage path against its root and rejects any result that leaves it, and it additionally refuses a storage root that lies inside the application server's own home directory outside the subtree now designated for storage. The default storage location was moved into that subtree in the same release.

dcm4chee-arc-light is the DICOM archive and image manager of the dcm4che project, used by hospitals, research groups, and imaging vendors as open infrastructure for storing and exchanging medical images. We appreciate the project's long-running work on that infrastructure and the care its maintainers took over this report. We reported this finding privately to J4Care in June 2026; they responded constructively and released a fix.

Impact

  • Code execution in the archive process carries the archive's own access to the imaging record it holds, so stored studies and the patient identifiers attached to them can be read, altered, or deleted. Independently of code execution, the same write primitive places well-formed studies at chosen locations, so an archive can be made to hold and later serve imaging that no imaging device produced. What that means clinically depends on how the receiving organisation uses the archive, and is for that organisation to assess.
  • Severity is rated against the deployment the project's own documentation presents first, in which the configuration interface answers without authentication. Where the secured build is deployed instead, the configuration interface requires only the base role that the shipped low-privilege account already holds, so the chain remains reachable by any authenticated user rather than being closed.

Mitigation

Upgrade to dcm4chee-arc-light 5.35.0 or later, which contains each storage path within its root and refuses a storage root inside the application server home outside the subtree now designated for storage. Until upgraded, operators can reduce exposure by restricting the configuration and control interfaces and the LDAP configuration backend to trusted networks, and by reviewing the configured storage locations against the paths the deployment actually intends to use.

Defender's Checklist

  • Review every configured storage descriptor.

    List the storage locations on your archive device and compare each storage URI against the paths your deployment actually intends to use. Be precise about what counts as wrong: the subtree the release designates for storage is legitimate, and the stock default before 5.35.0 also sat inside the application server home under the server data directory, so finding that one means an installation that has not been migrated rather than an intrusion. A storage root pointing at the deployments directory is the signal that matters. Check the path format and the file open options on the same descriptors while you are there.

  • Turn off the deployment scanner where it is not needed.

    The step that converts a file write into code execution is the application server picking up an archive from its deployments directory. Installations that deploy once and do not hot-deploy can disable the scanner, which removes that step for this finding and for the vendor-data extraction covered in the related advisory.

  • Restrict the configuration and control interfaces.

    The chain starts from a configuration write. The archive provides no way to restrict its device resource to administrators separately from ordinary users, so the boundary has to be enforced outside the application, at a reverse proxy or on the network. The LDAP configuration backend needs the same treatment.

  • Check for studies the archive holds that no device sent.

    The integrity half of this finding leaves valid, readable DICOM behind rather than a crash. If the configuration interface was exposed, reconcile stored studies against the modalities and senders your deployment expects, rather than assuming that anything the archive serves came from an imaging device.

  • Treat an exposed archive as having disclosed its configuration secrets.

    If the configuration interface was reachable from an untrusted network, assume the credentials held in archive configuration for the database, the storage backends, and the LDAP backend are known, and rotate them.

Severity Reasoning

AV:NThe configuration interface that sets the storage descriptor is an HTTP resource of the archive, and the write is then driven by a network store.AC:LNo timing or environmental preconditions. The deployment scanner and the verbatim copy of non-pixel bulk data are both stock behaviour.PR:NRated against the deployment the project documents first, in which the configuration interface answers without authentication. On the secured build this becomes PR:L, giving 8.8.UI:NThe store that performs the write is issued by the attacker; no operator action is needed.S:UImpact is bounded to the archive service account and what it can reach.C:HCode execution exposes stored imaging, the index database, and the credentials the archive holds for its backing services.I:HIndependently of code execution, the write primitive plants readable studies and, with the file open options changed, overwrites existing ones.A:HThe same primitive overwrites files the archive needs to run, and code execution can stop the service.

References

How We Can Help

Who We Are

The security researchers behind this advisory.

Dr. Simon Weber Profile

Dr. rer. nat. Simon Weber

Senior Pentester & MedSec Researcher

I evaluate your SaMD with the same industry-defining security insight I contributed to the BAK MV for the revision of the B3S standard.

  • PhD on Hospital Cybersecurity
  • Critical vulnerabilities found in hospital systems
  • Alumni of THB MedSec Research Group
  • gematik Security Hero
Volker Schönefeld Profile

Dipl.-Inf. Volker Schönefeld

Senior Application Security Expert

As a former CTO and developer turned pentester, I work alongside your team to uncover vulnerabilities and find solutions that fit your architecture.

  • 20+ years as CTO, 50M+ app downloads
  • Architected and secured large-scale IoT fleets
  • Certified Web Exploitation Specialist
  • gematik Security Hero

Looking for a Penetration Test?

Machine Spirits specializes in security assessments for medical devices and healthcare IT. From MDR penetration testing to C5 cloud compliance, we help MedTech companies meet regulatory requirements.