ANT-2026-YQ12XT7Y · openbabel

heap-buffer-overflow high

Severity Claude critical · Security research firm high · Maintainer -

Discovered by Claude Mythos Preview

REPORT

Anthropic's analysis, sealed at approval. Disclosure to the maintainer was performed by Ada Logics.

ANT-2026-YQ12XT7Y: Heap-buffer-overflow in openbabel

OpenBabel's MCDL (Molecular Chemical Description Language) parser in MCDLformat.cpp allocates the charges and radicals vectors with a fixed size of MAXFRAGS=200. When parsing the {CZ:...} charge block, it extracts an atom index via n2 = atoi(sa1.c_str()) and writes directly to charges[n2-1] without validating that n2 <= MAXFRAGS. A crafted MCDL file containing {CZ:201,1+} forces a write to charges[200], one element past the end of the 800-byte heap allocation. An attacker who can supply an MCDL file to an application using OpenBabel gains a heap out-of-bounds write of an attacker-chosen integer at an attacker-influenced offset.

Target

Project: openbabel

Technical Details

ASAN: heap-buffer-overflow WRITE past an 800-byte region. The 800-byte region corresponds to std::vector<int> charges(MAXFRAGS) with MAXFRAGS=200 (200 × 4 bytes). The index n2 is taken directly from user input (atoi on the substring before the comma in {CZ:n2,charge}) and used unchecked as charges[n2-1] = n1, so any n2 > 200 (or n2 <= 0) produces an out-of-bounds store.

Crash trace:

INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 3816546015
INFO: Loaded 1 modules   (135920 inline 8-bit counters): 135920 [0x634b39f5d608, 0x634b39f7e8f8), 
INFO: Loaded 1 PC tables (135920 PCs): 135920 [0x634b39f7e8f8,0x634b3a1917f8), 
/out/fuzz_convert: Running 1 inputs 1 time(s) each.
Running: /tmp/poc
EXIT_CODE:1

Reproduction

Reproduce against the target as described under Technical Details.

[No reproducer or sanitizer output attached — request from security-cvd@anthropic.com if needed.]

Acknowledgement

This vulnerability was discovered by Claude, Anthropic's AI assistant, and triaged by the Anthropic security team in collaboration with Anthropic Research. Please direct questions to security-cvd@anthropic.com and reference ANT-2026-YQ12XT7Y.


Reference: ANT-2026-YQ12XT7Y
Anthropic CVD Policy: https://www.anthropic.com/coordinated-vulnerability-disclosure

SECURITY RESEARCH FIRM ANALYSIS

Triage and disclosure were performed by Ada Logics.

Verdict
true positive
Severity
high
TIMELINE

Dates from discovery through public reveal.

  1. 2026-03-24 Reported to tracker
  2. 2026-05-07 Sent to maintainer
  3. 2026-05-08 Patch released
  4. 2026-05-12 Maintainer acknowledged
  5. 2026-08-17 Publicly revealed
PROVENANCE

SHA-3-512 hash:

60c7e49a9cc3c4e19f32ea2add6e062aba6f7f88fd013cebfd4388de8de5fee576869dbcc5fb22a829d365e21dc0206d99ee1798af5d63dbdfcaeac13c361a16

Committed 2026-05-07 14:16 PT

Revealed 2026-08-17 10:47 PT

Verify (download preimage.json)

Show preimage JSON
{
  "ant_id": "ANT-2026-YQ12XT7Y",
  "bug_class": "Heap-buffer-overflow",
  "claude_severity": "critical",
  "commit_sha": null,
  "created_at": "2026-03-24T18:29:10+00:00",
  "description": "OpenBabel's MCDL (Molecular Chemical Description Language) parser in MCDLformat.cpp allocates the `charges` and `radicals` vectors with a fixed size of MAXFRAGS=200. When parsing the `{CZ:...}` charge block, it extracts an atom index via `n2 = atoi(sa1.c_str())` and writes directly to `charges[n2-1]` without validating that `n2 <= MAXFRAGS`. A crafted MCDL file containing `{CZ:201,1+}` forces a write to `charges[200]`, one element past the end of the 800-byte heap allocation. An attacker who can supply an MCDL file to an application using OpenBabel gains a heap out-of-bounds write of an attacker-chosen integer at an attacker-influenced offset.",
  "discovered_at": null,
  "location": null,
  "poc_sha256": null,
  "preimage_version": 1,
  "project": "openbabel",
  "reproduction": null,
  "technical_details": "ASAN: heap-buffer-overflow WRITE past an 800-byte region. The 800-byte region corresponds to `std::vector<int> charges(MAXFRAGS)` with MAXFRAGS=200 (200 × 4 bytes). The index `n2` is taken directly from user input (`atoi` on the substring before the comma in `{CZ:n2,charge}`) and used unchecked as `charges[n2-1] = n1`, so any `n2 > 200` (or `n2 <= 0`) produces an out-of-bounds store.",
  "title": "Heap-buffer-overflow in openbabel",
  "vendor_severity": "high"
}