{"id":"CVE-2026-28696","aliases":["GHSA-7x43-mpfg-r9wj"],"url":"https://o3.security/vulnerability/CVE-2026-28696","summary":"Craft affected by IDOR via GraphQL @parseRefs","details":"The GraphQL directive `@parseRefs`, intended to parse internal reference tags (e.g., `{user:1:email}`), can be abused by both authenticated users and unauthenticated guests (if a Public Schema is enabled) to access sensitive attributes of any element in the CMS. The implementation in `Elements::parseRefs` fails to perform authorization checks, allowing attackers to read data they are not authorized to view.\n\n## Vulnerability Details\n\n`craft\\services\\Elements::parseRefs` identifies reference tags and resolves them using `_getRefTokenReplacement`. This method fetches the referenced element and accesses the specified attribute via $element->$attribute.\n\n- Missing Auth Check: It bypasses `canView()` checks.\n- Polymorphic Access: `getElementTypeByRefHandle` allows referencing any element type (entry, asset, user, category).\n- Custom Field Access: Since Craft elements use `__get()` to resolve custom field handles, an attacker is not limited to core attributes. They can exfiltrate any custom field data by enumerating the field handle (e.g. `{entry:123:privateNotes}`).\n\n## Attack Vectors\n\n1. Privilege Escalation / User Data Leak\n\nAn attacker can enumerate sensitive attributes of administrators or other users.\n\n- Payload: `{user:1:email}` or `{user:1:photoId}`\n\n2. Arbitrary Property Reflection & Server-Side Logic Execution\n\nThe vulnerability allows reflecting any accessible property of the underlying Element model.\n\n- Username/Admin Enumeration: `{user:1:username}` (Confirmed: returns admin), {user:1:admin}.\n- Internal Path Disclosure: Accessing methods that trigger errors (e.g., `{user:1:authKey}`) exposes full server stack traces in the GraphQL error response (e.g., Exception: No user session token exists with paths like `/var/www/html/...`).\n\n3. IDOR on Private Entries & Assets (Polymorphism)\n\nThe vulnerability is not limited to Users. Reference tags can target any element type.\n\n- Payload: `{entry:456:myConfidentialField}` (Bypasses canView checks).\n- Asset Path Leakage: `{volume:1:path}` can expose internal file system paths.\n\n4. Unauthenticated Exploitation (Public Schema)\n\nConfirmed locally. The `@parseRefs` directive is active in the Public Schema. By injecting a payload into a public-facing field (e.g., a \"News\" entry title), an unauthenticated guest can trigger the resolution and retrieve the sensitive output.\n\n## Steps to Reproduce\n\n1. Setup (Admin Panel):\n- Create a Section (e.g., \"News\") and an Entry Type.\n- Create a new Entry in that section. Set the Title to the payload: {user:1:username} or {user:1:email}.\n- Go to GraphQL > Schemas > Public Schema. Enable it, and ensure \"Query for elements in the Site\" and \"News\" section queries are checked.\n\n2. Execute Exploit (Unauthenticated):\n- Send a POST request to http://localhost:8000/index.php?action=graphql/api:\n```\ncurl -X POST \\\n-H \"Content-Type: application/json\" \\\n-d '{\"query\": \"{ entries { title @parseRefs } }\"}'\n```\n\n3. Observation:\n- The API returns `{\"data\":{\"entries\":[{\"title\":\"admin\"}]}}` (or the email).\n- Using `{user:1:authKey}` triggers an internal server error that leaks the full server path in string format.\n\n## Impact\n\n- Critical Information Disclosure: Full PII enumeration (emails, usernames).\n- System Information Leakage: Absolute server paths via stack traces.\n- Authentication Bypass: Guest accounts can effectively query the database as the system user.\n\n## Recommended Fix\n\nModify `Elements::parseRefs` to enforce `canView` permissions on the resolved element before extracting attributes.\n\n## References\n\nhttps://github.com/craftcms/cms/commit/4d98a07e47580f1712095825d3e3c4d67bc9f8b9","published":"2026-03-04T16:21:43.199Z","modified":"2026-08-12T03:51:24.581370465Z","cvss":null,"epss":{"score":0.00447,"percentile":0.36983,"asOf":"2026-08-24"},"cisaKev":null,"exploitsKnown":0,"affectedPackages":[{"ecosystem":"Packagist","name":"craftcms/cms","fixedVersion":"4.17.0-beta.1"},{"ecosystem":"Packagist","name":"craftcms/cms","fixedVersion":"5.9.0-beta.1"}],"fix":{"url":"https://github.com/craftcms/cms/commit/4d98a07e47580f1712095825d3e3c4d67bc9f8b9","label":"craftcms/cms@4d98a07"},"references":[{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/28xxx/CVE-2026-28696.json"},{"type":"ADVISORY","url":"https://github.com/craftcms/cms/security/advisories/GHSA-7x43-mpfg-r9wj"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-28696"},{"type":"FIX","url":"https://github.com/craftcms/cms/commit/4d98a07e47580f1712095825d3e3c4d67bc9f8b9"},{"type":"PACKAGE","url":"https://github.com/craftcms/cms"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-08-12T03:51:24.581370465Z"}}