For YAML from any source you do not control, use yaml.safe_load. The PyYAML documentation says yaml.load is as powerful as pickle.load and may call any Python function, so it is not safe on untrusted input. safe_load limits results to simple types.
What the two functions do
yaml.load(stream, Loader=...) takes a loader class. The full Loader supports all predefined tags and, in the docs' words, "may construct an arbitrary Python object." A YAML document can therefore contain tags that make the parser build and call objects of the document author's choosing.
yaml.safe_load(stream) uses SafeLoader, which recognizes only standard YAML tags and does not construct class instances. You get dictionaries, lists, strings, numbers, booleans, dates and null.
import yaml
with open("config.yml") as f:
config = yaml.safe_load(f)
"But it is just our config file"
A config file feels trusted until you ask who can change it. Think about:
- Files read from a repository that outside contributors can open pull requests against.
- Config uploaded through an admin screen.
- Files fetched from a URL or object store.
- Fixtures and test data that tools load automatically.
If the answer is anyone other than the people who already have code execution on that host, use safe_load. The cost of switching is almost always zero.
What if you need your own classes
Sometimes people reach for the full loader because they want YAML to produce their own objects. The docs describe a way to keep safe loading: derive your class from yaml.YAMLObject and set its yaml_loader to yaml.SafeLoader. That makes the class an explicit, reviewed exception rather than opening the door to every Python tag.
A simpler pattern is to load plain data with safe_load and then construct your objects in code after validating the fields. Validation in your own code is easier to test than tag handling in the parser.
Fixing old code
Search your codebase for these patterns:
yaml.load(without a loader argument.yaml.load(..., Loader=yaml.Loader)oryaml.Loaderanywhere.yaml.load_all(andyaml.full_load(.
Replace them with safe_load and safe_load_all, run your tests, and see which fail. A failure usually means the file uses Python specific tags, which is worth a conversation on its own.
Do not stop at the parser
Safe parsing means the YAML cannot run code during loading. It does not mean the values are valid. After safe_load, check types, ranges and allowed keys before using them, especially for anything that ends up in a file path, shell command or SQL string.
Safeguard's dependency scanning and reachability analysis can show whether a YAML library version in your tree has known issues and whether your code reaches the affected function. A free scan is at gold.safeguard.sh/scan.
Quick check
Is yaml.load with SafeLoader the same as yaml.safe_load?
Functionally close, since safe_load uses SafeLoader. The safe_load name makes the intent obvious in review and removes the chance of picking the wrong loader.
Does safe_load validate my config?
No. It only prevents arbitrary object construction. You still need to check the values.
Sources
Last reviewed: 19 October 2026.