Skip to content

feat: let a safe argument take kinds off a sink call - #122

Merged
SizzleUnrlsd merged 2 commits into
mainfrom
feat/safe-arguments
Sep 24, 2026
Merged

SizzleUnrlsd merged 2 commits into
mainfrom
feat/safe-arguments

Conversation

@SizzleUnrlsd

Copy link
Copy Markdown
Contributor

Closes #121.

Why

yaml.load(data, Loader=yaml.SafeLoader) — the documented safe way to load YAML — was reported as a critical insecure-deserialization: the yaml.load sink ignored its arguments.

What

  • SafeArgument(symbol, argument, values, position=None, kinds=ALL) (coretrace_python.taint): a call to the sink whose argument, by keyword or at position, denotes one of values is not a sink for kinds. Values are written as call sites record them (Advisories: check argument conditions at the call site #110): a symbol by canonical name, a constant as Python writes it.
  • Only a value given explicitly makes the call safe. An absent argument, another value, a variable or unpacked arguments leave the sink: a doubt is always reported.
  • Applied in _TaintProblem.guarded() where the taint engine reports a sink, directly and through a callee's summary; it takes off only the model's kinds (a sink with other kinds stays for them).
  • Arguments.given(keyword, position): the one reading of a call's arguments, moved out of the advisory correlation, which now uses it too.
  • Shipped for yaml.load: SafeLoader, BaseLoader, CSafeLoader, CBaseLoader, each under its two spellings (yaml.X and yaml.loader.X / yaml.cyaml.X), for DESERIALIZATION only — the advisory conditions decide the ADVISORY kind on their own.
  • Part of the model table, so part of the cache configuration key (repr(models)).

Tests

tests/test_safe_arguments.py (17): the table accessor; safe by keyword and position vs absent, another value, a variable and **options; safe through a callee; only the model's kinds taken off; end to end, yaml.load(request.data, …) with SafeLoader, CSafeLoader, yaml.loader.SafeLoader and yaml.cyaml.CBaseLoader is no finding, while no loader, yaml.Loader, FullLoader and UnsafeLoader still are. test_docs.py now requires the model in the plugin guide.

968 passed; ruff and mypy clean. No regression-corpus project passes a safe loader, so snapshots should not move (the CI regression job checks it).

Only a safe value given explicitly, by keyword or at its position, takes
the model's kinds off the sink, directly or through a callee, and only
those kinds; an absent argument, another value, a variable or unpacked
arguments leave it. yaml.load with SafeLoader, CSafeLoader, the
yaml.loader spelling or CBaseLoader is no insecure deserialization; with
no loader, Loader, FullLoader or UnsafeLoader it still is. The plugin
guide must document the model.
yaml.load(data, Loader=yaml.SafeLoader) was reported as a critical
insecure deserialization. A SafeArgument model names the argument, by
keyword or position, and the values that make a call to the sink safe
for some kinds; the taint engine applies it where it reports a sink,
directly and through a callee's summary. The reading of a call's
arguments moves to Arguments.given, shared with the advisory
conditions. Shipped for yaml.load with SafeLoader, BaseLoader and their
C versions under every spelling.

Closes #121
@SizzleUnrlsd SizzleUnrlsd self-assigned this Sep 24, 2026
@SizzleUnrlsd
SizzleUnrlsd merged commit 7710b56 into main Sep 24, 2026
10 checks passed
@SizzleUnrlsd
SizzleUnrlsd deleted the feat/safe-arguments branch September 24, 2026 14:27
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.

Precision: a sink call made safe by one of its arguments (yaml.load with SafeLoader)

1 participant