Skip to content

fix: load YAML files with the safe loader - #66

Merged
gipert merged 1 commit into
mainfrom
yaml-safe-loader
Nov 1, 2026
Merged

gipert merged 1 commit into
mainfrom
yaml-safe-loader

Conversation

@gipert

@gipert gipert commented Oct 15, 2026

Copy link
Copy Markdown
Owner

load_dict (and therefore TextDB, Props.read_from and Catalog.read_from) read YAML with yaml.CLoader, which is PyYAML's full loader. A YAML file containing Python tags such as !!python/object/apply:os.system [...] makes it create arbitrary Python objects and call functions while the file is read. Metadata repositories are shared and cloned from remotes, so reading one should never run code. This PR switches to yaml.CSafeLoader (falling back to yaml.SafeLoader without libyaml) and adds a test that a !!python/... tag is rejected.

What stops working: only the !!python/* tags: !!python/tuple, !!python/complex, !!python/name, !!python/module, !!python/object, !!python/object/new, !!python/object/apply, and the !!python/str|unicode|bytes|int|long|float|bool|none|dict|list variants. Loading such a file now raises yaml.constructor.ConstructorError. All standard YAML keeps working, including timestamps (datetime), !!set, !!binary, !!omap, !!pairs, anchors/aliases and merge keys (<<).

Round-trip caveat: write_dict (used by Props.write_to and Catalog.write_to) still uses the default yaml.dump, which emits Python tags for some objects. Such files can no longer be read back:

  • an AttrsDict (or any dict subclass) at any level, e.g. the result of Props.add_to, is written as !!python/object/new:dbetto.attrsdict.AttrsDict
  • tuples (!!python/tuple)
  • numpy scalars such as np.float64 and np.int64 (!!python/object/apply:numpy._core.multiarray.scalar)
  • complex numbers

Plain dict/list/str/int/float/bool/None/datetime values are unaffected (Catalog.write_to only writes those). Calling code should convert to plain types before writing (e.g. attrs.to_dict(), float(x), list(t)). A follow-up could make write_dict do this itself, so it never writes tags the loader rejects.

Verified: nox -s tests (32 passed) and pre-commit on the changed files. I also checked by hand which types written by yaml.dump fail to load with CSafeLoader.

🤖 Generated with Claude Code

CLoader is PyYAML's full loader: a YAML file with Python tags such as
!!python/object/apply can make it create arbitrary Python objects and
call functions while the file is read. Metadata repositories are often
shared, so reading one should not run code. CSafeLoader only builds
standard YAML types.

Assisted-by: Generative AI
@gipert

gipert commented Oct 15, 2026

Copy link
Copy Markdown
Owner Author

@ggmarshall this speeds up the read and I'm rather confident that it should not break anything. do you agree?

@gipert
gipert merged commit 058d742 into main Nov 1, 2026
12 checks passed
@gipert
gipert deleted the yaml-safe-loader branch November 1, 2026 13:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant