Skip to content

No top_k in pipeline_kwargs gives a typeerror #318

@snackattas

Description

@snackattas

Describe the bug

"""
Bug: MaliciousURLs scanner crashes when using custom Model without top_k parameter

When providing a custom Model to MaliciousURLs scanner, if the pipeline_kwargs
don't include `top_k=None`, the scanner crashes with:

    TypeError: string indices must be integers, not 'str'

This happens because the HuggingFace classification pipeline returns different
formats based on whether top_k is specified:
- With top_k=None: Returns list of dicts [{"label": "...", "score": ...}]
- Without top_k: Returns just the top label as a string

The MaliciousURLs scanner expects the dict format but gets strings.

To reproduce:
    pip install llm-guard torch transformers
    python llm_guard_bug_repro.py

Environment:
    - Python: 3.12
    - llm-guard: 0.3.16
    - transformers: 4.x
"""

from llm_guard import scan_output
from llm_guard.model import Model
from llm_guard.output_scanners import MaliciousURLs

TEST_TEXT = """
Here is some information you requested.
Download the file here: http://example-malware-site.com/payload.exe
Let me know if you need anything else.
"""


def test_default_config():
    """Default config works - includes top_k=None internally."""
    print("=" * 60)
    print("TEST 1: Default MaliciousURLs() - WORKS")
    print("=" * 60)
    
    scanner = MaliciousURLs()
    run_scan(scanner)


def test_custom_model_no_top_k():
    """Custom Model without top_k - CRASHES."""
    print("\n" + "=" * 60)
    print("TEST 2: Custom Model without top_k - CRASHES")
    print("=" * 60)
    
    custom_model = Model(
        path="DunnBC22/codebert-base-Malicious_URLs",
        pipeline_kwargs={"max_length": 512, "truncation": True},
        # Missing: top_k=None
    )
    scanner = MaliciousURLs(model=custom_model)
    run_scan(scanner)


def test_custom_model_with_top_k():
    """Custom Model with top_k=None - WORKS."""
    print("\n" + "=" * 60)
    print("TEST 3: Custom Model with top_k=None - WORKS")
    print("=" * 60)
    
    custom_model = Model(
        path="DunnBC22/codebert-base-Malicious_URLs",
        pipeline_kwargs={"max_length": 512, "truncation": True, "top_k": None},
    )
    scanner = MaliciousURLs(model=custom_model)
    run_scan(scanner)


def run_scan(scanner):
    """Run the scanner and report result."""
    try:
        _, is_valid, risk_score = scan_output(
            scanners=[scanner],
            prompt="",
            output=TEST_TEXT
        )
        print(f"✓ SUCCESS - is_valid={is_valid}, risk_score={risk_score}")
    except TypeError as e:
        print(f"✗ CRASHED: {e}")


if __name__ == "__main__":
    test_default_config()
    test_custom_model_no_top_k()
    test_custom_model_with_top_k()
    
    print("\n" + "=" * 60)
    print("SUMMARY")
    print("=" * 60)
    print("""
The MaliciousURLs scanner crashes when using a custom Model if
pipeline_kwargs doesn't include `top_k=None`.

Suggested fix: MaliciousURLs scanner should either:
1. Document that top_k=None is required in custom Model configs
2. Automatically add top_k=None to pipeline_kwargs if not present
3. Handle both string and dict return formats from the pipeline
""")

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions