oss-sec mailing list archives

Re: OSEC-2026-01 in the OCaml runtime: Buffer Over-Read in OCaml Marshal Deserialization


From: Florian Weimer <fweimer () redhat com>
Date: Fri, 27 Feb 2026 20:39:01 +0100

* Alan Coopersmith:

https://sympa.inria.fr/sympa/arc/ocsf-ocaml-security-announcements/2026-02/msg00000.html
announces:
From: Hannes Mehnert <hannes () mehnert org>
To: ocsf-ocaml-security-announcements () inria fr
Subject: [ocsf-ocaml-security-announcements] OSEC-2026-01 in the OCaml runtime: Buffer Over-Read in OCaml Marshal 
Deserialization
Date: Tue, 17 Feb 2026 15:16:54 +0100
Dear everyone,
it is my pleasure to announce the first security announcement of
this year,
and the first on this mailing list.
It should any moment now also appear at
https://osv.dev/list?q=OSEC-2026-01
Human link:
https://github.com/ocaml/security-advisories/tree/main/advisories/2026/OSEC-2026-01.md

Surprised to read this.  I think this comment from 2018 is still
appropriate:

| Marshal should not used in contexts where an attacker can control the
| data. I don't believe it is, at least in any project I'm aware of, and
| if it were, it's unlikely that those project perform enough check on
| the result of Marshal to make the use safe anyway.

<https://github.com/ocaml/ocaml/issues/7765#issuecomment-473076288>

The demarshaller does not have access to type information from the
program, so it has the ability to construct an arbitrary object graph.

The manual has a formatting glitch which hides the last sentence quoted
below:

| Warning: marshaling is currently not type-safe. The type of marshaled
| data is not transmitted along the value of the data, making it
| impossible to check that the data read back possesses the type
| expected by the context. In particular, the result type of the
| Marshal.from_* functions is given as 'a, but this is misleading: the
| returned OCaml value does not possess type 'a for all 'a; it has one,
| unique type which cannot be determined at compile-time. The programmer
| should explicitly give the expected type of the returned value, using
| the following syntax:
|
|    (Marshal.from_channel chan : type)
|
| Anything can happen at run-time if the object in the file does not
| belong to the given type.

<https://ocaml.org/manual/5.4/api/Marshal.html>

And the party supplying the serialized blob can chose whether the type
matches.  So the inherent insecurity of unmarshalling (“Anything can
happen”) is actually documented, just not very clearly.

Maybe time to send a PR.

Thanks,
Florian


Current thread: