How to Parse and Interpret Patator XML and CSV Output Formats

Patator writes machine-readable attack results through CSVFormatter and XMLFormatter classes located in src/patator/patator.py, storing them in a structured log directory created by build_logdir that includes runtime logs, result files, and individual response dumps.

When conducting brute-force or fuzzing campaigns, analyzing results programmatically is critical for automation. The Patator framework provides native support for structured data export, enabling security engineers to integrate findings directly into parsing pipelines without manual log scraping.

Where Patator's Output Formatters Are Implemented

Both output formatters inherit from Python’s logging.Formatter and are defined in the core engine file src/patator/patator.py.

CSVFormatter Class

The CSVFormatter resides at lines 86–100 in src/patator/patator.py. This class formats each request result as a comma-separated line containing temporal data, log level, response indicators, and the tested candidate string.

XMLFormatter Class

The XMLFormatter follows immediately at lines 102–123 in the same file. It serializes results into XML elements, providing identical data to the CSV format but with additional structural metadata including a <target> element containing the raw target string.

The process_logs Entry Point

The process_logs function (lines 32–73) serves as the entry point for Patator’s logging subprocess. When you invoke Patator with --csv or --xml options, this function instantiates the appropriate formatter, checks for existing files to write headers only once, and attaches handlers to the logger.

Understanding the Log Directory Structure

Patator constructs its output workspace through a dedicated directory builder that supports both manual and automatic path generation.

How build_logdir Creates the Output Location

The build_logdir function (lines 890–899 in src/patator/patator.py) validates and prepares the logging directory. Called during Controller.__init__, it accepts the --log-dir (-l) path and handles directory creation with optional user confirmation via --assume-yes.

Automatic Timestamped Directories with create_time_dir

When using the -L SFX flag, Patator invokes create_time_dir (lines 914–928) to generate a time-stamped subdirectory under /tmp/patator. The naming convention follows YYYY-MM-DD/HHMMSS_<suffix>/, preventing result collisions across multiple runs.

Directory Contents and File Layout

A typical Patator log directory contains:

  • RUNTIME.log – Raw command-line arguments and execution timestamps
  • RESULTS.csv – CSV output (when --csv is specified)
  • RESULTS.xml – XML output (when --xml is specified)
  • HITS – Flat text file listing successful candidates (one per line)
  • Response dumps – Raw HTTP/TCP responses saved as <num>_<indicators>.txt (e.g., 001_200_532_0.450.txt)

The response dumps are written by Logger.save_response (lines 55–58), which embeds the iteration number and indicator values (status code, size, time) directly into filenames for immediate correlation with CSV or XML entries.

Parsing Patator CSV Output Format

The CSV file includes a header row written by process_logs using the pattern 'time,level,%s\n' % ','.join(names), where names represents the dynamic indicator list. Standard columns include time, level, code, size, time (elapsed), candidate, num (iteration), and mesg.

import csv
from pathlib import Path

csv_path = Path("/tmp/patator/2024-03-05/153012_ftp/RESULTS.csv")

with csv_path.open(newline="") as f:
    reader = csv.DictReader(f, delimiter=",")
    for row in reader:
        print(f"[{row['time']}] {row['candidate']}: {row['mesg']} (HTTP {row['code']})")

Use csv.DictReader to automatically map the header fields, allowing direct access to columns by name rather than index.

Parsing Patator XML Output Format

The XML structure wraps all results in a <root> element. Each request generates a <result> tag with time and level attributes, plus child elements for each indicator and a <target> element containing connection details.

import xml.etree.ElementTree as ET
from pathlib import Path

xml_path = Path("/tmp/patator/2024-03-05/153012_ftp/RESULTS.xml")
tree = ET.parse(xml_path)

for result in tree.getroot().findall("result"):
    candidate = result.findtext("candidate")
    code = result.findtext("code")
    mesg = result.findtext("mesg")
    
    # Access target attributes if needed

    target_elem = result.find("target")
    target_str = target_elem.text if target_elem is not None else "N/A"
    
    print(f"{candidate} -> {mesg} (code={code}, target={target_str})")

The XML format preserves the same data as CSV but structures multi-word messages unambiguously and includes the raw target string in the <target> element, useful for forensic reconstruction of complex pivot attacks.

Practical Command-Line Examples

Generate both formats in an auto-managed directory:

patator http_fuzz url=FILE0 method=GET 0=urls.txt -L webscan --csv RESULTS.csv --xml RESULTS.xml

This creates /tmp/patator/2024-XX-XX/XXXXXX_webscan/ containing both structured files plus the HITS file and response dumps.

Save only CSV to a specific location:

patator ssh_login host=10.0.0.1 user=FILE0 password=FILE1 0=users.txt 1=pass.txt -l /var/log/patator --csv scan.csv

Inspect successful candidates without parsing structured files:

cat /var/log/patator/HITS

Summary

  • Patator XML and CSV output formats are generated by XMLFormatter and CSVFormatter classes in src/patator/patator.py, activated via --xml and --csv command-line switches.
  • The process_logs function manages formatter initialization and header writing, appending results as the scan progresses.
  • build_logdir and create_time_dir construct the output hierarchy, defaulting to /tmp/patator when using the -L flag.
  • The log directory contains RUNTIME.log, result files, a HITS summary, and individual response dumps named with iteration numbers and indicator values.
  • Parse CSV output using Python’s csv.DictReader and XML using xml.etree.ElementTree to extract candidate strings, response codes, and timing data for further analysis.

Frequently Asked Questions

What columns appear in Patator's CSV output?

Patator’s CSV includes the columns: time, level, code, size, time (response time in milliseconds), candidate, num (iteration number), and mesg (response message). The header is generated dynamically in process_logs based on the module’s indicator configuration.

How does Patator name response dump files?

Response dumps follow the format <num>_<code>_<size>_<time>.txt, where <num> is the zero-padded iteration number and the remaining fields represent response indicators. These files are written by Logger.save_response in the log directory when logging is enabled.

Can I generate both CSV and XML output simultaneously?

Yes. Patator accepts both --csv FILE and --xml FILE arguments in the same command. The process_logs function creates separate handlers and formatters for each, writing both formats concurrently to the specified log directory.

Where does Patator store logs by default?

When using -L <suffix>, Patator stores logs in a timestamped subdirectory under /tmp/patator. When using -l <dir>, it stores them in the specified directory. If the directory does not exist, build_logdir creates it after user confirmation (unless --assume-yes is passed).

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →