CVE-2026-65636 Overview
CVE-2026-65636 is a CRLF (Carriage Return Line Feed) injection vulnerability [CWE-93] in the ymlr Elixir library maintained by ufirstgroup. The flaw resides in the Elixir.Ymlr module, which generates YAML documents but fails to sanitize line-break characters in caller-supplied comment strings. Attackers who control comment text can terminate the comment context early and inject arbitrary YAML content into the document body. Injected content is parsed as legitimate data by downstream configuration loaders, deployment manifests, CI pipelines, and data importers. The issue affects ymlr from version 0.0.1 before 5.1.6.
Critical Impact
Attackers can forge top-level mapping keys, override application-set values, and emit --- or ... markers that split output into additional YAML documents consumed downstream.
Affected Products
- ufirstgroup ymlr (Elixir Hex package) versions 0.0.1 through 5.1.5
- Applications invoking Ymlr.document!/2, Ymlr.document/2, Ymlr.documents!/2, or Ymlr.documents/2 with attacker-influenced comment strings
- Downstream YAML consumers (configuration loaders, deployment manifests, CI pipelines, data importers) that ingest ymlr output
Discovery Timeline
- 2026-07-31 - CVE CVE-2026-65636 published to NVD
- 2026-08-04 - Last updated in NVD database
Technical Details for CVE-2026-65636
Vulnerability Analysis
The ymlr library encodes Elixir data structures into YAML documents. The document encoding entry points accept a tuple of {comments, data}, where comments is intended to be rendered as one or more YAML comment lines prefixed with #. The vulnerable implementation interpolates each caller-supplied comment string directly behind a single # prefix without validating or escaping line-break characters.
A YAML comment is terminated by a line break. When the comment string contains a carriage return or line feed, the first such character ends the comment context. Any content following the line break is emitted at column 0 of the document body and is parsed as YAML data rather than as a comment.
Root Cause
The root cause resides in lib/ymlr.ex. The original document!/2 clause built comments with Enum.map_join(lines, "", &"# #{&1}\n"), providing no filtering for embedded \n, \r, or \r\n sequences. The same construction backed documents!/2, so every document encoding entry point inherited the flaw. Because YAML treats bare newlines as structural delimiters, any embedded newline in a comment string escapes the comment context.
Attack Vector
An attacker supplies a comment string containing a newline followed by YAML content. When the host application calls Ymlr.document!/2 with that comment, the generated YAML contains attacker-controlled top-level keys, overridden values, or additional document boundaries (---, ...). Downstream parsers accept the injected content as legitimate configuration data.
# Vulnerable pre-patch behavior in lib/ymlr.ex
def document!({lines, data}, opts) when is_list(lines) do
comments = Enum.map_join(lines, "", &"# #{&1}\n")
"---\n" <> comments <> Encode.to_s!(data, opts) <> "\n"
end
Source: GitHub Commit 7e53061
Detection Methods for CVE-2026-65636
Indicators of Compromise
- Generated YAML documents containing top-level keys that the host application never set
- Unexpected --- or ... document separators appearing inside comment blocks in ymlr output
- Configuration or manifest files with keys following a #-prefixed line at column 0 after decoding
Detection Strategies
- Audit application source for calls to Ymlr.document!/2, Ymlr.document/2, Ymlr.documents!/2, and Ymlr.documents/2 where the comment argument originates from user input, HTTP parameters, database fields, or external APIs
- Scan Hex dependency lockfiles (mix.lock) for ymlr versions earlier than 5.1.6
- Add regression tests that pass \n, \r, and \r\n characters into comment strings and assert that no injected keys appear in the encoded output
Monitoring Recommendations
- Log and review comment inputs passed to ymlr encoding functions in production paths
- Validate YAML documents against a strict schema before downstream consumption by CI pipelines or deployment tooling
- Monitor commits to CI/CD manifest repositories for unexpected key insertions or duplicate document markers
How to Mitigate CVE-2026-65636
Immediate Actions Required
- Upgrade ymlr to version 5.1.6 or later in mix.exs and refresh mix.lock
- Inventory all Elixir services that depend on ymlr directly or transitively and prioritize those that accept externally influenced comment strings
- Treat any YAML previously produced from untrusted comment inputs as untrusted and re-validate consumers
Patch Information
The fix is delivered across two commits in lib/ymlr.ex. The first patch centralizes comment handling through a sanitize_comments/1 helper that both prefixes every line with # and strips embedded newlines. The second patch expands the split delimiters to cover \r\n, \n, and \r.
# Patched sanitize_comments/1 in lib/ymlr.ex
defp sanitize_comments(comments) do
comments
|> Enum.flat_map(&String.split(&1, ["\r\n", "\n", "\r"], trim: true))
|> Enum.map_join("", &"# #{&1}\n")
end
Source: GitHub Commit 42a0bf8. See also the GitHub Security Advisory GHSA-p8qx-7cp9-v6c9 and the CNA advisory from the Erlang Ecosystem Foundation.
Workarounds
- Strip or reject \r and \n characters from any string passed as a ymlr comment before calling the encoder
- Do not pass user-controlled data as comment arguments to Ymlr.document!/2 or Ymlr.documents!/2; place untrusted values only in the data argument, which is properly encoded
- Post-process generated YAML through a strict schema validator before handing it to configuration loaders or CI systems
# Update ymlr in mix.exs and refresh the lockfile
# mix.exs
# {:ymlr, "~> 5.1.6"}
mix deps.update ymlr
mix deps.get
mix deps.compile ymlr
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

