⚠️ Final release — serde_yml is deprecated
This is the final maintenance release of serde_yml. The crate is no longer under active development. 0.0.13 is a thin compatibility shim that lets existing call sites keep compiling while you migrate to one of the maintained alternatives listed below.
If you are reading this because cargo audit flagged your build, upgrading to 0.0.13 resolves RUSTSEC-2025-0068 structurally — see Security below.
TL;DR
# Cargo.toml
- serde_yml = "0.0"
+ serde_yml = "0.0.13"Your existing call sites compile unchanged. The compiler now emits a #[deprecated] warning at every use serde_yml::* import pointing at the migration guide. The C-FFI libyml parser is no longer in your dependency graph.
When you're ready to fully migrate, see the migration guide.
Security: RUSTSEC-2025-0068 fixed
RUSTSEC-2025-0068 (also GHSA-hhw4-xg65-fp2x) flagged every serde_yml ≤ 0.0.12 as unsound — the serde_yml::ser::Serializer.emitter field could cause a segmentation fault via the C-FFI libyaml parser.
0.0.13 removes the vulnerable surface entirely:
- The C-FFI
libymldependency is gone from the graph. serde_yml::ser::Serializeris now a re-export of a pure-Rust unit struct (pub struct Serializer;) with noemitterfield — code that referenced.emitterno longer compiles, which is the desired outcome.- The backend (
noyalib) enforces#![forbid(unsafe_code)]workspace-wide.
Verification:
cargo update -p serde_yml --precise 0.0.13
cargo tree -p serde_yml | grep libyml # → no outputThe RustSec advisory database PR adding patched = ["^0.0.13"] is pending review at rustsec/advisory-db#2915. Until it merges, cargo audit may still warn against 0.0.13 — the 0.0.13 release itself ships .cargo/audit.toml + deny.toml ignore entries so the self-referential warning doesn't block your own CI.
Maintained alternatives
Three crates are realistic destinations. Pick the one that fits.
| Crate | Migration shape | Best fit |
|---|---|---|
noyalib
| Drop-in via features = ["compat-serde-yaml"]
| Codebases that want a serde_yml-shaped API on a modern, safe, pure-Rust backend with zero call-site changes
|
serde-saphyr
| Path rename for typed code; no Value DOM
| Typed-deserialise workloads (from_str::<MyStruct>) — the 95 % case
|
yaml-rust2
| Lower-level parser API, not serde-integrated | Users who were on serde_yml::libyml / loader (removed in this shim)
|
Full per-destination mapping tables: MIGRATION.md.
The shim itself is backed by noyalib internally — that's an implementation detail, not a recommendation. Pick whichever alternative suits your codebase.
What's removed
The deep internal modules that previous versions exposed leaked implementation details of the C-FFI parser. They are gone in this release:
| Removed | Replacement |
|---|---|
serde_yml::libyml::* (FFI bindings)
| yaml-rust2 for low-level parsing; otherwise n/a
|
serde_yml::loader::Loader
| yaml-rust2::YamlLoader or noyalib::load_all_as::<T>
|
serde_yml::de::{Event, Progress, DocumentAnchor}
| Covered by the alternatives' streaming APIs |
serde_yml::ser::{SerializerConfig, State}
| noyalib::ser::Config
|
serde_yml::modules::path::Path
| Error::location() / Error::path() on any alternative
|
serde_yml::value::Index
| Value types in the alternatives implement Index<&str> / Index<usize> natively
|
Code calling only the public top-level surface (from_str / to_string / Value / Mapping / with::singleton_map*) needs no changes.
Behavioural notes worth knowing
Two intentionally safer defaults flow through the shim:
- Custom-tag scalars surface as
Value::Taggedrather than being coerced to the inner string. Code exhaustively matching the previous six-variantValueenum needs either aValue::Tagged(_)arm or a call toValue::untag()/Value::untag_ref()before the match. - YAML 1.2 strict booleans by default.
country: NOstays"NO"(the YAML 1.2 fix to the "Norway problem") instead of becomingfalse.
MSRV
0.0.13 requires Rust 1.85.0 (the backend's MSRV); the previous releases required 1.56. Users who cannot move past 1.56 should pin serde_yml = "=0.0.12" and plan a migration window — but note that pinning 0.0.12 keeps RUSTSEC-2025-0068 in your audit feed.
Dependencies
The runtime dependency tree dropped from six crates to two:
serde_yml v0.0.13
├── noyalib v0.0.5
│ ├── indexmap, memchr, rustc-hash, serde, smallvec
└── serde v1.0.x
No libyml, no unsafe-libyaml, no serde_yaml 0.9. Downstream cargo audit / cargo deny runs stop flagging the unmaintained chain.
Documentation
README.md— overview, install, behavioural notesMIGRATION.md— full per-destination mapping tables, removed-surface table, test/example coverage triageSECURITY.md— RUSTSEC-2025-0068 status, supported-versions table, reporting policy- docs.rs/serde_yml/0.0.13 — API reference with
#[deprecated]banner on every item
License
Dual-licensed under Apache 2.0 or MIT, at your option.
Thanks to everyone who used and contributed to serde_yml. The crate served its purpose; it's time to move on to maintained, safer alternatives.