ANT-2026-XBE9HJ4Y · moodle/moodle

path-traversal high

Severity Claude high · Security research firm high · Maintainer -

Discovered by Claude Mythos Preview

REPORT

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

ANT-2026-XBE9HJ4Y: Path Traversal → Arbitrary File Write → RCE in repository_googledocs

repository_googledocs::download_file() passes the Google Drive file name (fetched from the Google API and therefore controlled by the file owner) directly to repository::prepare_file(), which performs a naive string concatenation with no path sanitization. The resulting path is opened with fopen(..., 'w') by curl::download_one().

An authenticated Moodle user (student or teacher) who links their Google account can create a Google Drive file named ../../../../../../../../var/www/html/public/shell.php, pick it as an Access Controlled Link, and submit the form. When Moodle processes the draft → final transition it fetches the file's name from Google, builds a temp path with it, and writes the attacker's file body to that path — escaping the temp directory and landing a PHP web-shell in the Moodle web-root.

Google Drive uses a flat namespace where name is arbitrary metadata; the / character is fully permitted in Drive file names.

Target

Project: moodle/moodle
Commit: 9a5df8d6da29571e
Discovery: static analysis — not yet dynamically reproduced

Technical Details

Root cause is trusting the externally-supplied name field from the Google Drive v3 files API as a safe local path component. prepare_file() performs naive string concatenation with no '..'/'/'/null-byte stripping, and download_one() calls fopen($options['filepath'], 'w') directly, which follows traversal sequences and creates/truncates the target. Although Moodle HMAC-validates the Drive file ID via sourcekey, the name is re-fetched at commit time and never validated, so attacker-chosen traversal sequences survive to the fopen sink.

Reproduction

This finding was identified by static analysis and has not yet been dynamically reproduced. The Technical Details section above describes the code path; a trigger input is not included.

[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-XBE9HJ4Y.


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

SECURITY RESEARCH FIRM ANALYSIS

Triage and disclosure were performed by Ophion Security.

Verdict
true positive
Severity
high
TIMELINE

Recorded dates, in order.

  1. 2026-03-30 Discovered or logged
  2. 2026-04-10 Maintainer acknowledged
  3. 2026-04-23 Sent to maintainer
  4. 2026-05-18 Patch released
  5. 2026-07-21 Publicly revealed
PROVENANCE

SHA-3-512 hash:

abdda0ccd741fe8be1684c7434f523327ddb872f9e7acb72e2f95f687850e08db5ae5f2c1d6df22ff433676f6dafa86f2060d13be74b09eeda5b2a0b1c897283

Committed 2026-04-23 07:04 UTC

Revealed 2026-07-21 05:10 UTC

Verify (download preimage.json)

Show preimage JSON
{
  "ant_id": "ANT-2026-XBE9HJ4Y",
  "bug_class": "Path-traversal",
  "claude_severity": "high",
  "commit_sha": "9a5df8d6da29571e",
  "created_at": "2026-03-30T23:20:07+00:00",
  "description": "`repository_googledocs::download_file()` passes the Google Drive file **name** (fetched from the Google API and therefore controlled by the file owner) directly to `repository::prepare_file()`, which performs a naive string concatenation with no path sanitization. The resulting path is opened with `fopen(..., 'w')` by `curl::download_one()`.\n\nAn authenticated Moodle user (student or teacher) who links their Google account can create a Google Drive file named `../../../../../../../../var/www/html/public/shell.php`, pick it as an **Access Controlled Link**, and submit the form. When Moodle processes the draft → final transition it fetches the file's name from Google, builds a temp path with it, and writes the attacker's file body to that path — escaping the temp directory and landing a PHP web-shell in the Moodle web-root.\n\nGoogle Drive uses a flat namespace where `name` is arbitrary metadata; the `/` character is fully permitted in Drive file names.",
  "discovered_at": null,
  "location": null,
  "poc_sha256": "e85b8dd500756df02a336874b983832d929bce2409b55f4484b99481743e405f",
  "preimage_version": 1,
  "project": "moodle",
  "reproduction": null,
  "technical_details": "Root cause is trusting the externally-supplied `name` field from the Google Drive v3 files API as a safe local path component. prepare_file() performs naive string concatenation with no '..'/'/'/null-byte stripping, and download_one() calls fopen($options['filepath'], 'w') directly, which follows traversal sequences and creates/truncates the target. Although Moodle HMAC-validates the Drive file *ID* via sourcekey, the *name* is re-fetched at commit time and never validated, so attacker-chosen traversal sequences survive to the fopen sink.",
  "title": "Path Traversal → Arbitrary File Write → RCE in repository_googledocs",
  "vendor_severity": "high"
}