fix(tests): add missing Behave step definitions for pyyaml_security Scenario 2
CI / benchmark-publish (pull_request) Has been skipped
CI / quality (pull_request) Successful in 1m19s
CI / lint (pull_request) Successful in 1m26s
CI / typecheck (pull_request) Successful in 1m33s
CI / security (pull_request) Successful in 1m34s
CI / unit_tests (pull_request) Failing after 2m34s
CI / docker (pull_request) Has been skipped
CI / build (pull_request) Successful in 28s
CI / push-validation (pull_request) Successful in 26s
CI / helm (pull_request) Successful in 46s
CI / integration_tests (pull_request) Successful in 4m35s
CI / e2e_tests (pull_request) Successful in 4m56s
CI / coverage (pull_request) Failing after 3m3s
CI / status-check (pull_request) Failing after 5s

Scenario 2 in features/pyyaml_security.feature referenced three step
definitions that were not implemented in the step file, causing
StepDefinitionNotFoundError and CI unit_tests failure:

- When I call load_yaml_text with YAML text "..."
- Then the load_yaml_text result should have key "..." equal to "..."

Added both missing step definitions with proper type annotations.
Also fixed dead code (except (ValueError, Exception) -> except Exception,
ruff B014) and toned down the alarmist assertion message per reviewer
feedback.
This commit is contained in:
2026-05-05 19:48:49 +00:00
parent 6b2cf7fa3b
commit b48ac21485
+27 -3
View File
@@ -8,6 +8,7 @@ code execution (CVE-2017-18342 mitigation, issue #9055).
from __future__ import annotations
from importlib.metadata import version as pkg_version
from typing import Any
from behave import given, then, when # type: ignore[import-untyped]
from behave.runner import Context # type: ignore[import-untyped]
@@ -50,6 +51,30 @@ def step_assert_pyyaml_version(context: Context) -> None:
# ── yaml_loader safe_load enforcement ───────────────────────────────
@when('I call load_yaml_text with YAML text "{yaml_text}"')
def step_load_yaml_text(context: Context, yaml_text: str) -> None:
"""Call load_yaml_text with the given YAML text and store the result.
The YAML text is passed as a quoted string in the step, with ``\\n``
escape sequences representing literal newlines.
"""
normalised = yaml_text.replace("\\n", "\n")
context.load_yaml_result: dict[str, Any] = load_yaml_text(normalised)
@then('the load_yaml_text result should have key "{key}" equal to "{value}"')
def step_assert_yaml_result_key(context: Context, key: str, value: str) -> None:
"""Assert that the parsed YAML result contains the expected key/value pair."""
result: dict[str, Any] = context.load_yaml_result
assert key in result, (
f"Expected key '{key}' in load_yaml_text result, but it was not found. "
f"Actual keys: {list(result.keys())}"
)
assert result[key] == value, (
f"Expected result['{key}'] == '{value}', but got '{result[key]}'."
)
@when("I call load_yaml_text with unsafe YAML containing a Python object tag")
def step_load_unsafe_yaml(context: Context) -> None:
"""Attempt to load YAML with a Python object constructor tag.
@@ -62,7 +87,7 @@ def step_load_unsafe_yaml(context: Context) -> None:
unsafe_yaml = "!!python/object/apply:os.system ['echo pwned']"
try:
load_yaml_text(unsafe_yaml)
except (ValueError, Exception) as exc:
except Exception as exc:
context.caught_error = exc
@@ -71,6 +96,5 @@ def step_assert_value_error_raised(context: Context) -> None:
"""Assert that an error was raised when loading unsafe YAML."""
assert context.caught_error is not None, (
"Expected an error when loading YAML with Python object tags, "
"but none was raised. This indicates yaml.load() with an unsafe "
"Loader may be in use — a critical security vulnerability."
"but none was raised. This may indicate unsafe YAML loading is in use."
)