Config files that execute code are everywhere
YAML, TOML, and JSON parsers can run arbitrary code during deserialization. Most dependency scanners miss them entirely.
I learned today that config files are a supply chain blind spot. Not because they reference dependencies badly, but because they can execute code during parsing.
YAML is the worst offender. Python’s PyYAML lets you instantiate arbitrary objects through !!python/object tags. If an attacker controls a YAML file in your repo or a dependency’s repo, they control what runs when you parse it. Ruby’s YAML parser has the same problem with !ruby/object.
TOML and JSON are not safe either. TOML parsers in Go have crashed on malformed input. JSON parsers in JavaScript will happily call JSON.parse(userInput) and trigger prototype pollution if the schema is not locked down.
The article lists twelve different config formats that can execute code: YAML, TOML, JSON with reviver functions, XML with XInclude, INI files that shell out, Python pickle files, Java property files with JNDI lookups, and more. Most SBOM tools only track explicit dependencies in package manifests. They do not parse every YAML file in every subdirectory of every transitive dependency.
This hit me because I parse YAML all the time for ML model configs and detection rules. I assumed deserialization was safe because I wrote the files myself. But if a malicious PR adds a !!python/object tag to a config file, my local editor or CI pipeline runs it before I finish reading the diff.
The fix is to use safe loaders. Python has yaml.safe_load(). Ruby has YAML.safe_load(). Both strip the executable tags. The problem is that most tutorials and Stack Overflow answers use the unsafe version because it is shorter to type.
I checked my repos. Three of them use yaml.load() without Loader=yaml.SafeLoader. That is three places where a supply chain attack could land without tripping a single scanner.
Source: Config Files That Run Code: Supply Chain Security Blindspot