Skip to content

Loop detection can be bypassed via JSON formatting differences #47

@galic1987

Description

@galic1987

Summary

In src/agent/execution.rs, the detect_repetition function (line 196) hashes the raw args_str string to detect repeated tool calls:

let mut hasher = std::collections::hash_map::DefaultHasher::new();
args_str.hash(&mut hasher);

Semantically identical JSON with different formatting produces different hashes, so {"path": "foo"} and {"path":"foo"} are treated as different calls.

Practical Impact

Low. Most LLM providers normalize JSON output consistently, and the 10-call window is tight. This is a defense-in-depth improvement.

Fix

Normalize args before hashing:

let normalized = serde_json::from_str::<serde_json::Value>(args_str)
    .map(|v| serde_json::to_string(&v).unwrap_or_default())
    .unwrap_or_else(|_| args_str.to_string());
normalized.hash(&mut hasher);

Source

Gemini code review (validated, severity downgraded from original)

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions