Security

graphify: host-file read via Fortran cpp includes

Fortran extractor: incomplete cpp #include hardening allows arbitrary host-file read when indexing an untrusted repo (GHSA-pcc4-rvhr-2pr8)

PUBLISHED SEVERITY HIGHSTATUS PatchedGHSA-pcc4-rvhr-2pr8
Patched

Fixed in graphifyy 0.9.70 (2026-09-27) by commit e1d9dee, which strips every #include directive before preprocessing and feeds the source to cpp on stdin. Track the fix at Graphify-Labs/graphify@e1d9dee.

Product
graphify (PyPI graphifyy) in Graphify-Labs/graphify
Affected versions
graphifyy before 0.9.70. Fixed in 0.9.70 (2026-09-27).
Severity
HIGH
Status
Patched
Weaknesses
  • CWE-22Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
  • CWE-73External Control of File Name or Path
As filed on the advisory.
GitHub advisory
GHSA-pcc4-rvhr-2pr8
Published by the maintainer on 2026-09-27
CVE
Pending (requested from MITRE)
Published
Credit
Finder: Aaron Elijah Mars of Aeon. Tool: Aeon (https://www.aeon.fun).

What users should do now

  1. Upgrade graphify to 0.9.70 or later (pip install -U graphifyy).
  2. If you indexed an untrusted repository with an older version, check its graph.json, GRAPH_REPORT.md, wiki and HTML/SVG exports for content from outside the repo before you share them, and rotate any secret that may have been read.
  3. Until you upgrade, do not index untrusted repositories that contain .F, .F90, .F95, .F03 or .F08 files on a machine that holds secrets, or run graphify where cpp is not on PATH.

Summary

graphify turns a folder of code into a knowledge graph. Fortran files with a capital-F extension go through the C preprocessor (cpp) first. A security comment in the code ("F-007") said the flags -nostdinc -I /dev/null stop a malicious source file from pulling host files in with #include. They do not. cpp always opens absolute include paths, and always looks in the source file's own directory for quoted includes, so a relative path can walk out of the repo. Indexing an untrusted repo could therefore copy any file the user can read into the graph, the LLM context and the files graphify writes to disk.

Affected versions

graphifyy (PyPI) before 0.9.70, when it indexes a folder that contains a .F, .F90, .F95, .F03 or .F08 file and cpp is on PATH. These extensions are picked up by default, and the step runs on the default offline path: no API key, network access or LLM call is needed. Lower-case .f/.f90 files do not go through cpp and are not affected.

Impact

  • Arbitrary local file read. A hostile Fortran file can include an absolute path (for example a key or token file in the user's home directory) or a relative path that climbs out of the repo. cpp inlines that file into the preprocessed source.
  • Exfiltration into shared outputs. The preprocessed text is parsed into graph nodes and edges, so file contents can end up in graph.json, GRAPH_REPORT.md, the Obsidian wiki and the HTML/SVG exports, and in what the MCP tools return to an agent or LLM.
  • Fidelity. Fortran is case-insensitive, so captured identifiers are lower-cased. Single-line secrets such as API key or token files, paths, hostnames and hex tokens come through in full (lower-cased); mixed-case blobs are partly altered but still show that the file exists and is readable.
  • The attacker only needs the user to index a repo they control. The user does not need to run any code from it.

Affected code

Permalinks at c66eebe, the commit just before the fix.

Fix

  • e1d9dee blanks every #include line before preprocessing (line numbers are kept) and passes the cleaned source to cpp on stdin instead of a file path, so cpp never opens the file's directory or any include path. Macro expansion (#define, #ifdef) still works; includes across files are no longer followed. The no-cpp fallback returns the same cleaned bytes. Released in 0.9.70.
  • Feeding stdin also removes the older edge case where a corpus file named like a cpp option could be read as one.

Detection (for defenders)

Search repos you index for #include lines in .F, .F90, .F95, .F03 or .F08 files that use an absolute path or climb out of the repo with ../. In existing graphify output, look for node labels or imports edges that look like secrets, paths or hostnames from your machine rather than Fortran names. A working exploit is withheld.

Timeline

  1. Reported privately via GitHub PVR (GHSA-pcc4-rvhr-2pr8), with a suggested fix.
  2. Maintainer commits the fix (e1d9dee), releases 0.9.70 and publishes the advisory the same day.
  3. CVE ID requested from MITRE.
  4. Asked the maintainer to request a CVE for the published advisory (#4259).

Credit

Finder: Aaron Elijah Mars of Aeon. Tool: Aeon.

References