CVE-2026-115938
Low privilege condition filter escapes Twig sandbox, recovers "securityKey" and reaches RCE
High 8.7
Craft CMS allows any authenticated control panel user to submit an element-search condition whose element selector is evaluated as a sandboxed Twig object template. Craft’s allowed column filter delegates property lookup to Yii ArrayHelper, outside Twig’s SecurityPolicy. Repeated single-segment lookups therefore bypass the sandbox’s empty property/method allowlists. The vulnerable condition value is ultimately cast to an integer. That does not protect the secret: the template can return author ID 1 when a guessed key character is correct and an impossible ID otherwise. The JSON endpoint returns entries for the first case and an empty array for the second, forming a stable remote character oracle. After recovering GeneralConfig::securityKey, the same user can compute Craft’s generic HMAC wire format offline. Signed parameters such as redirect are then accepted and passed to unsandboxed View::renderObjectTemplate(), where Twig’s string-callable form can invoke native PHP callables. The regression proof uses the harmless substr() callback and observes abcdef becoming cdef; it does not execute an OS command.
Hackrate
2026-10-23
2026-10-23
2026-10-23
Scores
| Source | CVSS | Score | Severity | Vector |
|---|---|---|---|---|
| Hackrate | 4.0 | 8.7 | High | CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N |
| Hackrate | 3.1 | 8.8 | High | CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H |
Weaknesses
Affected
| Vendor | Product | Versions |
|---|---|---|
| craftcms | cms | 5.0.0 to < 5.11.2 (affected) 4.0.0 to < 4.18.9 (affected) others: unaffected |
References
- https://www.hckrt.com/hacktivity/HCKRT-DRNL9W third-party-advisorytechnical-descriptionmitigation
- https://github.com/craftcms/cms/releases/tag/5.11.2 release-notes
- https://github.com/craftcms/cms product
- https://github.com/craftcms/cms/security/advisories/GHSA-v4q3-2g5g-wjj6 third-party-advisory
Full CVE JSON record (5.2)
{
"containers": {
"cna": {
"affected": [
{
"collectionURL": "https://packagist.org",
"defaultStatus": "unaffected",
"packageName": "craftcms/cms",
"product": "cms",
"vendor": "craftcms",
"versions": [
{
"lessThan": "5.11.2",
"status": "affected",
"version": "5.0.0",
"versionType": "semver"
},
{
"lessThan": "4.18.9",
"status": "affected",
"version": "4.0.0",
"versionType": "semver"
}
]
}
],
"cpeApplicability": [
{
"nodes": [
{
"cpeMatch": [
{
"criteria": "cpe:2.3:a:craftcms:cms:*:*:*:*:*:*:*:*",
"versionEndExcluding": "5.11.2",
"versionStartIncluding": "5.0.0",
"vulnerable": true
},
{
"criteria": "cpe:2.3:a:craftcms:cms:*:*:*:*:*:*:*:*",
"versionEndExcluding": "4.18.9",
"versionStartIncluding": "4.0.0",
"vulnerable": true
}
],
"negate": false,
"operator": "OR"
}
],
"operator": "OR"
}
],
"credits": [
{
"lang": "en",
"type": "reporter",
"value": "Mohamed Wagdy (@Kalawy)"
},
{
"lang": "en",
"type": "coordinator",
"value": "Hackrate"
}
],
"descriptions": [
{
"lang": "en",
"supportingMedia": [
{
"base64": false,
"type": "text/html",
"value": "\u003cp\u003eCraft CMS allows any authenticated control panel user to submit an element-search condition whose element selector is evaluated as a sandboxed Twig object template. Craft\u2019s allowed\u0026nbsp;\u003ccode\u003ecolumn\u003c/code\u003e\u0026nbsp;filter delegates property lookup to Yii\u0026nbsp;\u003ccode\u003eArrayHelper\u003c/code\u003e, outside Twig\u2019s\u0026nbsp;\u003ccode\u003eSecurityPolicy\u003c/code\u003e. Repeated single-segment lookups therefore bypass the sandbox\u2019s empty property/method allowlists.\u003c/p\u003e\u003cp\u003eThe vulnerable condition value is ultimately cast to an integer. That does not protect the secret: the template can return author ID\u0026nbsp;\u003ccode\u003e1\u003c/code\u003e\u0026nbsp;when a guessed key character is correct and an impossible ID otherwise. The JSON endpoint returns entries for the first case and an empty array for the second, forming a stable remote character oracle.\u003c/p\u003e\u003cp\u003eAfter recovering\u0026nbsp;\u003ccode\u003eGeneralConfig::securityKey\u003c/code\u003e, the same user can compute Craft\u2019s generic HMAC wire format offline. Signed parameters such as\u0026nbsp;\u003ccode\u003eredirect\u003c/code\u003e\u0026nbsp;are then accepted and passed to unsandboxed\u0026nbsp;\u003ccode\u003eView::renderObjectTemplate()\u003c/code\u003e, where Twig\u2019s string-callable form can invoke native PHP callables. The regression proof uses the harmless\u0026nbsp;\u003ccode\u003esubstr()\u003c/code\u003e\u0026nbsp;callback and observes\u0026nbsp;\u003ccode\u003eabcdef\u003c/code\u003e\u0026nbsp;becoming\u0026nbsp;\u003ccode\u003ecdef\u003c/code\u003e; it does not execute an OS command.\u003c/p\u003e"
}
],
"value": "Craft CMS allows any authenticated control panel user to submit an element-search condition whose element selector is evaluated as a sandboxed Twig object template. Craft\u2019s allowed\u00a0column\u00a0filter delegates property lookup to Yii\u00a0ArrayHelper, outside Twig\u2019s\u00a0SecurityPolicy. Repeated single-segment lookups therefore bypass the sandbox\u2019s empty property/method allowlists.\n\n\n\nThe vulnerable condition value is ultimately cast to an integer. That does not protect the secret: the template can return author ID\u00a01\u00a0when a guessed key character is correct and an impossible ID otherwise. The JSON endpoint returns entries for the first case and an empty array for the second, forming a stable remote character oracle.\n\n\n\nAfter recovering\u00a0GeneralConfig::securityKey, the same user can compute Craft\u2019s generic HMAC wire format offline. Signed parameters such as\u00a0redirect\u00a0are then accepted and passed to unsandboxed\u00a0View::renderObjectTemplate(), where Twig\u2019s string-callable form can invoke native PHP callables. The regression proof uses the harmless\u00a0substr()\u00a0callback and observes\u00a0abcdef\u00a0becoming\u00a0cdef; it does not execute an OS command."
}
],
"metrics": [
{
"cvssV4_0": {
"Automatable": "NOT_DEFINED",
"Recovery": "NOT_DEFINED",
"Safety": "NOT_DEFINED",
"attackComplexity": "LOW",
"attackRequirements": "NONE",
"attackVector": "NETWORK",
"baseScore": 8.7,
"baseSeverity": "HIGH",
"exploitMaturity": "NOT_DEFINED",
"privilegesRequired": "LOW",
"providerUrgency": "NOT_DEFINED",
"subAvailabilityImpact": "NONE",
"subConfidentialityImpact": "NONE",
"subIntegrityImpact": "NONE",
"userInteraction": "NONE",
"valueDensity": "NOT_DEFINED",
"vectorString": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N",
"version": "4.0",
"vulnAvailabilityImpact": "HIGH",
"vulnConfidentialityImpact": "HIGH",
"vulnIntegrityImpact": "HIGH",
"vulnerabilityResponseEffort": "NOT_DEFINED"
},
"format": "CVSS",
"scenarios": [
{
"lang": "en",
"value": "GENERAL"
}
]
},
{
"cvssV3_1": {
"attackComplexity": "LOW",
"attackVector": "NETWORK",
"availabilityImpact": "HIGH",
"baseScore": 8.8,
"baseSeverity": "HIGH",
"confidentialityImpact": "HIGH",
"integrityImpact": "HIGH",
"privilegesRequired": "LOW",
"scope": "UNCHANGED",
"userInteraction": "NONE",
"vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
"version": "3.1"
},
"format": "CVSS",
"scenarios": [
{
"lang": "en",
"value": "GENERAL"
}
]
}
],
"problemTypes": [
{
"descriptions": [
{
"cweId": "CWE-1336",
"description": "CWE-1336 Improper neutralization of special elements used in a template engine",
"lang": "en",
"type": "CWE"
}
]
}
],
"providerMetadata": {
"dateUpdated": "2026-10-23T21:58:51.816Z",
"orgId": "7004884b-51e2-48e8-b4a2-5ca29e80453e",
"shortName": "Hackrate"
},
"references": [
{
"tags": [
"third-party-advisory",
"technical-description",
"mitigation"
],
"url": "https://www.hckrt.com/hacktivity/HCKRT-DRNL9W"
},
{
"tags": [
"release-notes"
],
"url": "https://github.com/craftcms/cms/releases/tag/5.11.2"
},
{
"tags": [
"product"
],
"url": "https://github.com/craftcms/cms"
},
{
"tags": [
"third-party-advisory"
],
"url": "https://github.com/craftcms/cms/security/advisories/GHSA-v4q3-2g5g-wjj6"
}
],
"source": {
"advisory": "GHSA-v4q3-2g5g-wjj6",
"discovery": "UNKNOWN"
},
"title": "Low privilege condition filter escapes Twig sandbox, recovers \"securityKey\" and reaches RCE",
"x_generator": {
"engine": "Vulnogram 1.0.4"
}
}
},
"cveMetadata": {
"assignerOrgId": "7004884b-51e2-48e8-b4a2-5ca29e80453e",
"assignerShortName": "Hackrate",
"cveId": "CVE-2026-115938",
"datePublished": "2026-10-23T21:58:51.816Z",
"dateReserved": "2026-10-23T21:25:32.945Z",
"dateUpdated": "2026-10-23T21:58:51.816Z",
"state": "PUBLISHED"
},
"dataType": "CVE_RECORD",
"dataVersion": "5.2"
}