- MAYA_SKIP_USER_SETUP=1 will disable usersetup.py
- To disable script node execution, you want
cmds.optionVar(iv= ("fileExecuteSN", 0)) - I should have said “mayapy” – i was thinking you’d make a tool which fired up mayapy (in a process with MAYA_SKIP_USER_SETUP=1), used the optionVar to disable script node execution, and then looped through all the files you care about cataloging and/or deleting their script node contents.
Here’s the shell of a script you could use, though it needs to be beefed up – it just audits for fiiles with any script nodes other than the two standard ones (sceneConfigurationScriptNode and uiConfigurationScriptNode). A clever attacker could hijack those, so this is NOT production quality security – but it could be turned into such with some attention.
# usage :
# mayapy.exe quick_scan.py path/to/directory/to/scan
# recursively scanes all maya files in path/to/directory/to/scan
import sys
import logging
logger = logging.getLogger("mayascan")
logger.setLevel(logging.INFO)
import os
os.environ['MAYA_SKIP_USER_SETUP'] = "1"
logger.info("usersetup disabled")
import maya.standalone
maya.standalone.initialize()
logger.info("maya initialized")
import maya.cmds as cmds
cmds.optionVar(iv= ("fileExecuteSN", 0))
logger.info("scriptnodes disabled")
file_list = []
counter = 0
for root, _, files in os.walk(sys.argv[-1]):
for mayafile in files:
lower = mayafile.lower()
if lower.endswith(".ma") or lower.endswith(".mb"):
counter += 1
abspath = os.path.join(root, mayafile)
logger.info("scanning {}".format(abspath))
cmds.file(abspath, open=True)
scriptnodes = cmds.ls(type='script')
# almost all Maya files will contain two nodes named
# 'sceneConfigurationScriptNode' and 'uiConfigurationScriptNode'
# a proper job wouldd make sure that they contained only trivial MEL
# but youd have to really inspect the contents to make sure
# a smart attacker hadn't hidden inside those nodes. For demo purposes
# I'm just ignoring them but that is a clear vulnerability
if len(scriptnodes) > 2:
# here's where you'd want to nuke and resave the file if you were really cleaning house,
# or you could loop through them applying your own safety test
logger.warning("file {} contains {} scriptnodes".format(abspath, len(scriptnodes) - 2 ))
file_list.append(abspath)
logger.info("scanned {} files".format(counter))
if file_list:
logger.warning ("=" * 72)
logger.warning ("filenodes found in:")
for f in file_list:
logger.warning(f)