[Bug Hunt][Cycle 2][Config] Type validation bypass in JSON config parsing #7130

Open
opened 2026-04-10 08:02:20 +00:00 by HAL9000 · 1 comment
Owner

Metadata

  • Branch: fix/bug-hunt-cycle2/actor-config-type-validation-bypass
  • Commit Message: fix(actor): enforce dict type validation on YAML parsing path in ActorConfiguration
  • Milestone: None (Backlog)
  • Parent Epic: #5502

Background

The actor configuration parser (src/cleveragents/actor/config.py) has inconsistent type validation between its JSON and YAML parsing paths inside ActorConfiguration.load_yaml_text(). The JSON path correctly validates that the parsed result is a dictionary, but the YAML path returns the raw parsed value without any type check. This means a YAML file containing a bare scalar (e.g., 42 or "hello") silently bypasses validation and returns a non-dict value, violating the method's declared return type of dict[str, Any] and the project's type-safety and fail-fast principles.

Current Behavior

@staticmethod
def load_yaml_text(text: str) -> dict[str, Any]:
    try:
        data = json.loads(text)
    except json.JSONDecodeError:
        data = ActorConfiguration._load_v2_yaml_content(text)
    else:
        if data is None:
            return {}
        if not isinstance(data, dict):
            raise ValueError("Config must be a JSON or YAML object")
        return cast(dict[str, Any], data)
    return data  # ← YAML path returns without dict validation

A YAML document containing only a scalar value (e.g., 42) will cause _load_v2_yaml_content() to return an int, which is then returned directly — bypassing the isinstance(data, dict) guard that exists only in the JSON branch.

Expected Behavior

Both JSON and YAML parsing paths must perform identical type validation. After either parse path completes, the result must be checked:

# After both JSON and YAML parsing
if data is None:
    return {}
if not isinstance(data, dict):
    raise ValueError("Config must be a JSON or YAML object")
return cast(dict[str, Any], data)

Acceptance Criteria

  • ActorConfiguration.load_yaml_text() raises ValueError("Config must be a JSON or YAML object") when YAML input parses to a non-dict, non-None value (e.g., a scalar or list)
  • ActorConfiguration.load_yaml_text() returns {} when YAML input parses to None
  • The JSON parsing path behaviour is unchanged
  • load_blob_from_file() is reviewed for the same pattern and fixed if affected
  • A TDD issue-capture test tagged @tdd_issue, @tdd_issue_<N>, and @tdd_expected_fail is created and merged before the fix is implemented
  • All nox stages pass after the fix
  • Coverage ≥ 97%

Supporting Information

  • File: src/cleveragents/actor/config.py
  • Function: ActorConfiguration.load_yaml_text()
  • Lines: 46–55
  • Severity: High — type contract violation; can cause downstream AttributeError or silent misconfiguration
  • Category: type-safety
  • Discovered during: Bug Hunt Cycle 2

TDD Note

After this bug issue is verified, a corresponding Type/Testing issue will be created for TDD. The test will use tags: @tdd_issue, @tdd_issue_<this-issue-number>, and @tdd_expected_fail to prove the bug exists before the fix is implemented.

Subtasks

  • Write a failing TDD test (@tdd_expected_fail) that passes a scalar YAML string to load_yaml_text() and asserts ValueError is raised
  • Refactor load_yaml_text() to apply the None/dict type guard after both JSON and YAML parse paths
  • Review load_blob_from_file() for the same inconsistency and apply the same fix if needed
  • Remove @tdd_expected_fail tag once the fix is in place and the test passes
  • Update docstrings to document the validation behaviour explicitly

Definition of Done

  • load_yaml_text() raises ValueError for any non-dict, non-None YAML input
  • load_blob_from_file() has consistent validation (fixed if affected)
  • TDD test exists, was merged as @tdd_expected_fail, and now passes without the tag
  • All nox stages pass
  • Coverage ≥ 97%

Backlog note: This issue was discovered during autonomous operation
on milestone v3.5.0. It does not block milestone completion and has been
placed in the backlog for human review and future milestone assignment.


Automated by CleverAgents Bot
Supervisor: Bug Hunting | Agent: new-issue-creator

## Metadata - **Branch**: `fix/bug-hunt-cycle2/actor-config-type-validation-bypass` - **Commit Message**: `fix(actor): enforce dict type validation on YAML parsing path in ActorConfiguration` - **Milestone**: None (Backlog) - **Parent Epic**: #5502 ## Background The actor configuration parser (`src/cleveragents/actor/config.py`) has inconsistent type validation between its JSON and YAML parsing paths inside `ActorConfiguration.load_yaml_text()`. The JSON path correctly validates that the parsed result is a dictionary, but the YAML path returns the raw parsed value without any type check. This means a YAML file containing a bare scalar (e.g., `42` or `"hello"`) silently bypasses validation and returns a non-dict value, violating the method's declared return type of `dict[str, Any]` and the project's type-safety and fail-fast principles. ## Current Behavior ```python @staticmethod def load_yaml_text(text: str) -> dict[str, Any]: try: data = json.loads(text) except json.JSONDecodeError: data = ActorConfiguration._load_v2_yaml_content(text) else: if data is None: return {} if not isinstance(data, dict): raise ValueError("Config must be a JSON or YAML object") return cast(dict[str, Any], data) return data # ← YAML path returns without dict validation ``` A YAML document containing only a scalar value (e.g., `42`) will cause `_load_v2_yaml_content()` to return an `int`, which is then returned directly — bypassing the `isinstance(data, dict)` guard that exists only in the JSON branch. ## Expected Behavior Both JSON and YAML parsing paths must perform identical type validation. After either parse path completes, the result must be checked: ```python # After both JSON and YAML parsing if data is None: return {} if not isinstance(data, dict): raise ValueError("Config must be a JSON or YAML object") return cast(dict[str, Any], data) ``` ## Acceptance Criteria - [ ] `ActorConfiguration.load_yaml_text()` raises `ValueError("Config must be a JSON or YAML object")` when YAML input parses to a non-dict, non-None value (e.g., a scalar or list) - [ ] `ActorConfiguration.load_yaml_text()` returns `{}` when YAML input parses to `None` - [ ] The JSON parsing path behaviour is unchanged - [ ] `load_blob_from_file()` is reviewed for the same pattern and fixed if affected - [ ] A TDD issue-capture test tagged `@tdd_issue`, `@tdd_issue_<N>`, and `@tdd_expected_fail` is created and merged before the fix is implemented - [ ] All nox stages pass after the fix - [ ] Coverage ≥ 97% ## Supporting Information - **File**: `src/cleveragents/actor/config.py` - **Function**: `ActorConfiguration.load_yaml_text()` - **Lines**: 46–55 - **Severity**: High — type contract violation; can cause downstream `AttributeError` or silent misconfiguration - **Category**: type-safety - **Discovered during**: Bug Hunt Cycle 2 ### TDD Note After this bug issue is verified, a corresponding `Type/Testing` issue will be created for TDD. The test will use tags: `@tdd_issue`, `@tdd_issue_<this-issue-number>`, and `@tdd_expected_fail` to prove the bug exists before the fix is implemented. ## Subtasks - [ ] Write a failing TDD test (`@tdd_expected_fail`) that passes a scalar YAML string to `load_yaml_text()` and asserts `ValueError` is raised - [ ] Refactor `load_yaml_text()` to apply the `None`/dict type guard after both JSON and YAML parse paths - [ ] Review `load_blob_from_file()` for the same inconsistency and apply the same fix if needed - [ ] Remove `@tdd_expected_fail` tag once the fix is in place and the test passes - [ ] Update docstrings to document the validation behaviour explicitly ## Definition of Done - [ ] `load_yaml_text()` raises `ValueError` for any non-dict, non-None YAML input - [ ] `load_blob_from_file()` has consistent validation (fixed if affected) - [ ] TDD test exists, was merged as `@tdd_expected_fail`, and now passes without the tag - [ ] All nox stages pass - [ ] Coverage ≥ 97% > **Backlog note:** This issue was discovered during autonomous operation > on milestone v3.5.0. It does not block milestone completion and has been > placed in the backlog for human review and future milestone assignment. --- **Automated by CleverAgents Bot** Supervisor: Bug Hunting | Agent: new-issue-creator
Author
Owner

Verified — Bug: type validation bypass in JSON config parsing. MoSCoW: Should-have. Priority: Medium.


Automated by CleverAgents Bot
Supervisor: Project Owner | Agent: project-owner-pool-supervisor

✅ **Verified** — Bug: type validation bypass in JSON config parsing. MoSCoW: Should-have. Priority: Medium. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: project-owner-pool-supervisor
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference
cleveragents/cleveragents-core#7130
No description provided.