{
  "ticket_id": "CVE-2026-45539",
  "code_root": "external/apm",
  "source": {
    "type": "cve",
    "cve_id": "CVE-2026-45539",
    "advisory_id": "GHSA-q5pp-gvjg-h7v4",
    "advisory_url": "https://github.com/microsoft/apm/security/advisories/GHSA-q5pp-gvjg-h7v4",
    "vendor": "microsoft",
    "product": "apm",
    "repo": "https://github.com/microsoft/apm"
  },
  "facts": {
    "cve_id": "CVE-2026-45539",
    "advisory_id": "GHSA-q5pp-gvjg-h7v4",
    "issue_summary": "The apm-cli tool (the `apm` PyPI package) enumerates the files of an APM package with bare Path.glob() / Path.rglob() and then reads them with read_text(), all of which transparently follow symbolic links. When apm install processes a remote APM dependency, any symlink committed inside that dependency under .apm/prompts/ or .apm/agents/ is silently dereferenced: the symlink target's contents (an arbitrary host file such as /etc/passwd) are read and copied into the consuming project tree. A malicious APM dependency can therefore exfiltrate arbitrary files from the machine running apm install into files inside the victim project.",
    "vulnerability_type": "Symlink-following / path traversal leading to arbitrary file disclosure",
    "suspected_cwe": ["CWE-59", "CWE-22"],
    "affected_versions": "0.5.4 - 0.12.4 (inclusive)",
    "fixed_versions": ["0.13.0"],
    "reproduce_version": "0.12.4",
    "verify_fixed_version": "0.13.0",
    "repo_url": "https://github.com/microsoft/apm.git",
    "code_root": "external/apm",
    "ecosystem": "pip",
    "package": "apm",
    "affected_paths": [".apm/prompts/", ".apm/agents/"],
    "install_recipe": "In a scratch virtualenv run `pip install apm==0.12.4` (vulnerable) or `pip install apm==0.13.0` (fixed). The published PyPI wheel is the canonical artifact. Construct a local 'dependency' APM package directory containing a benign markdown file plus a malicious symlink (for example `.apm/prompts/evil.prompt.md -> /etc/passwd`), then run `apm install` so the CLI installs that dependency into a consuming project.",
    "attacker_access": "An attacker who can get a victim to add / install a malicious APM dependency (a remote package, e.g. published or pulled from a git source) that contains a committed symlink under .apm/prompts/ or .apm/agents/. No privileges on the victim host beyond running apm install are required.",
    "exploit_outline": "1) Create a local APM dependency package whose .apm/prompts/ directory contains a symlink named e.g. evil.prompt.md pointing at an absolute host path such as /etc/passwd (and a normal .md file so the package is non-empty). 2) From a separate consuming project, run `apm install` referencing that dependency. 3) apm-cli walks the dependency's files with Path.glob()/rglob(), follows the symlink, calls read_text() on it, and writes the dereferenced contents into the consuming project's installed-package directory.",
    "vulnerable_indicator": "After `apm install` with apm==0.12.4, the installed copy of the dependency in the consuming project tree contains a file whose contents are the host file's contents (e.g. the line `root:x:0:0:` / the body of /etc/passwd) rather than the symlink itself. Host file contents have been disclosed into the project tree.",
    "fixed_indicator": "With apm==0.13.0 the symlink is detected and not followed: the dereferenced host file contents do NOT appear anywhere in the consuming project tree (the malicious entry is skipped / rejected, or copied as an unresolved symlink, but never as the disclosed target contents).",
    "reproduction_requirements": "Python 3 with pip and the apm package at the specified version. No network service, database, or browser required. The reproduction needs a filesystem that supports symlinks (standard on Linux) and a readable host file to use as the disclosure target (use /etc/passwd, or create a sentinel file with known marker contents).",
    "notes": "The fixed version to verify against is 0.13.0; do not assume any specific intermediate patch commit. The repro agent should clone https://github.com/microsoft/apm.git and inspect the diff between the 0.12.4 and 0.13.0 release tags to confirm the root cause and the symlink guard. The observable difference is purely on the local filesystem: vulnerable = host file contents land inside the project tree; fixed = they do not."
  }
}
