{"id":"TECH-202610-unpatched-godot-4-flaw-lets-a-community-po-translation-file-","kind":"technique","aliases":[],"related":[],"title":"Unpatched Godot 4 flaw lets a community .po translation file run attacker-chosen code inside exported games","description":null,"summary":"In Godot Engine 4.1.0 through 4.7.2, the Plural-Forms header of a gettext .po translation file is not checked and is evaluated by the engine's general Expression evaluator. A crafted header can deserialize a GDScript object (via bytes_to_var_with_objects) whose script source the attacker controls. That script then runs inside the game process, with the game's privileges, the first time the game shows a pluralized string. At risk: any Godot 4 game that ships or loads community or third-party translations, and the players who install them. The researcher (Tomasz Kaye) confirmed it at runtime on the official 4.7-stable export and published a public PoC. Disclosed 2026-10-26. Still unpatched as of 2026-10-26: maintainer PRs #123130 and #123857 are not merged. A CVE has been requested. No exploitation in the wild reported.","severity":"medium","cvss":null,"epss":null,"exploited":false,"exploited_at":null,"products":[{"name":"Godot Engine","fixed":[],"versions":">=4.1.0,<=4.7.2","ecosystem":"other"}],"ecosystems":[],"tags":["early-warning","technique"],"not_affected_if":[],"how_to_check":"Find Godot 4.1-4.7.2 projects that load .po files from outside the shipped build (mods, community translation packs, user folders). Inspect each .po Plural-Forms header: anything beyond n, numbers, comparison/logic/arithmetic operators and ?: (for example function calls such as bytes_to_var_with_objects) is malicious.","fix":"Do not load untrusted .po translations in Godot 4 games until a fixed release is out. Ship translations only as vetted, signed-off assets, or validate Plural-Forms against the GNU gettext grammar before loading. Watch for PRs #123130/#123857 to land in a Godot 4.7.x release and upgrade when they do.","status":"open","published_at":null,"first_seen_at":"2026-10-27T09:05:13+00:00","triaged_at":"2026-10-27T09:05:13+00:00","updated_at":"2026-10-27T09:05:13+00:00","category":"runtime","confidence":null,"triage":null,"analyst_status":"done","analyst_note":null,"search":"'-10':154B,161B '-202610':20A '-26':155B,162B '123130':165B '123857':167B '2026':153B,160B '4':3A,24A,115B '4.1.0':42B '4.7':144B '4.7.2':44B 'a':28A 'attack':13A,87B 'attacker-chosen':12A 'byte':78B 'check':58B 'chosen':14A 'code':15A 'communiti':7A,121B 'community':29A 'confirm':137B 'control':88B 'craft':70B 'cve':172B 'deseri':73B 'disclos':152B 'earli':36B 'early-warn':35B 'engin':41B,64B 'engine':34A 'evalu':61B,68B 'exploit':177B 'export':17A,146B 'express':67B 'file':10A,32A,55B 'first':103B 'flaw':4A,26A 'flaw-lets-a-community-po-translation-file':25A 'form':48B 'game':18A,95B,99B,106B,116B 'gdscript':75B 'general':66B 'gettext':52B 'godot':2A,23A,33A,40B,114B 'header':49B,71B 'insid':16A,93B 'instal':131B 'kay':136B 'let':5A 'lets':27A 'load':120B 'maintain':163B 'merg':170B 'object':76B,82B 'offici':143B 'parti':125B 'player':129B 'plural':47B,109B 'plural-form':46B 'po':8A,30A,53B 'poc':151B 'privileg':101B 'process':96B 'prs':164B 'public':150B 'publish':148B 'report':181B 'request':175B 'research':134B 'risk':112B 'run':11A,92B 'runtim':140B 'script':84B,90B 'ship':118B 'show':107B 'sourc':85B 'stabl':145B 'still':156B 'string':110B 'tech':19A 'techniqu':38B 'third':124B 'third-parti':123B 'time':104B 'tomasz':135B 'translat':9A,54B,126B 'translation':31A 'unpatch':1A,157B 'unpatched':22A 'unpatched-godot':21A 'var':80B 'via':77B 'warn':37B 'whose':83B 'wild':180B","nicknames":[],"mitigations":[],"who_affected":null,"tier":"C","verified":{},"analyst_revisit_at":null,"first_public_at":"2026-10-26T20:37:25+00:00","kev":null,"cvss_vector":null,"cvss_by":null,"poc_count":0,"sources":[{"source":"analyst","external_id":"TECH-202610-unpatched-godot-4-flaw-lets-a-community-po-translation-file-","url":null,"severity":null,"published_at":null,"modified_at":null,"first_seen_at":"2026-10-27T09:05:13+00:00","fetched_at":"2026-10-27T09:05:13+00:00","note":null}],"documents":[{"id":5780,"url":"https://www.reddit.com/r/netsec/comments/1xgn2l1/a_community_translation_can_run_attackerchosen/","title":"r/netsec: A community translation can run attacker-chosen code in an exported Godot game","kind":"post","source":"reddit","text":"A community translation can run attacker-chosen code in an exported Godot game\n\nsubmitted by /u/bitbutter [link] [comments]","published_at":"2026-10-27T08:37:28+00:00","relation":"describes","confidence":null,"note":null},{"id":5800,"url":"https://www.openwall.com/lists/oss-security/2026/10/26/19","title":"Godot 4.x: arbitrary code execution via .po translation file Plural-Forms header","kind":"advisory","source":"analyst","text":"Godot 4.1.0 through 4.7.2. The .po loader stores Plural-Forms without validating against gettext grammar; header evaluated with Expression evaluator, can call bytes_to_var_with_objects() to deserialize a GDScript object with attacker source; static initializer runs in the game process. Runtime-confirmed on official 4.7-stable export. PoC: github.com/bitbutter/godot-security-pocs. Unpatched as of 2026-10-26 (master, 4.7.2); PRs #123130 and #123857 restrict evaluator function scope, not merged. CVE requested (CAN-2026-2040826). Original write-up: axeghost.offprint.app.","published_at":"2026-10-26T20:37:25+00:00","relation":"describes","confidence":null,"note":null}],"notice":"Free to read at a human pace. An API with keys and an MCP server are in preparation; early access: hello@infrastack.ai"}