mbitai/secops-2k
SecOps-2k 2,000 synthetic security log lines with template labels in LogHub format. Parser papers mostly test on system logs (HDFS, BGL, Apache). No comparable set existed for security telemetry, so we built one: sshd, sudo, firewall, and audit lines, all invented. No real hosts, users, or IPs. Authors: TMFNK and MbitAI. Generator code: TMFNK/LogParser-Dataset. Archived release: doi:10.5281/zenodo.22341506. What is inside One host (secops-01), one day (14 Jun), 2… See the full description on the dataset page: https://huggingface.co/datasets/mbitai/secops-2k.
SecOps-2k
2,000 synthetic security log lines with template labels in LogHub format. Parser papers mostly test on system logs (HDFS, BGL, Apache). No comparable set existed for security telemetry, so we built one: sshd, sudo, firewall, and audit lines, all invented. No real hosts, users, or IPs.
Authors: TMFNK and MbitAI. Generator code: TMFNK/LogParser-Dataset. Archived release: doi:10.5281/zenodo.22341506.
What is inside
One host (secops-01), one day (14 Jun), 2,000 lines drawn from 25 templates:
Every IP is a documentation or private range (RFC 5737 / RFC 1918). Tokens that change at runtime are masked as <*> in the template.
Files
Ground-truth columns (LogHub shape, so LogHub eval code reads them as-is): LineId, Month, Day, Time, Host, Process, Pid, Content, EventId, EventTemplate, ParameterList.
Tight vs loose
Grouping strictness is a variable here, not a given. Tight keeps 25 templates apart: login outcome, invalid-user vs failed-password, process, firewall action and protocol, and auditd event type all stay fixed. Loose merges lines that describe the same security event from different daemons into 10 groups. A failed sshd password plus its pam failure line both become L_AUTH_FAIL, for example. Templates stay identical in both files, so parsing scores come out the same and only the grouping scores move. Full rules: docs/GROUPING-RULES.md in the code repo.
How it was made
scripts/generate.py reads configs/templates.yaml (the template registry, weights sum to 100) and emits the log plus both CSVs. Seed 42 gives byte-identical files; CI rejects any drift in the committed dataset after a regen. Nothing real went in: no production logs copied or anonymized. Lines are drawn independently from template weights, so there is no session correlation, clock skew, or noise from unrelated daemons.
Use
from datasets import load_dataset
tight = load_dataset("MbitAI/secops-2k", "tight")
loose = load_dataset("MbitAI/secops-2k", "loose")Score parsers with the four LogHub-2.0 metrics: GA (fraction of lines put in the right group), PA (fraction with an exactly matching template), FGA and FTA (the same two ideas, but every template counts the same no matter how rare). Pinned Drain baseline (st=0.5, depth=4), tight: GA 0.772, PA 0.6945, FGA 0.2947, FTA 0.2526. Scoring harness: TMFNK/LogParser-Harness. Parser with audit trail: TMFNK/LogParser-Trail (FGA / FTA 0.8627 on tight).
Good for: comparing parsers on security-flavored logs under two grouping strictnesses. Not for: training intrusion detectors, or claiming coverage of real SOC traffic.
Limits
Synthetic by design. 2k scale only. It runs anywhere; rare templates get few lines. Same tradeoff as LogHub-2k.
Privacy
Fully synthetic. Every line is generated from a fixed template registry. No production logs were copied or anonymized. IPs come only from documentation (RFC 5737) and private (RFC 1918) ranges. Usernames, hosts, and command arguments are invented pools inside the generator. Nothing in these files ever belonged to a real system.
Cite
@software{tmfnk_2026_secops_2k,
author = {TMFNK and MbitAI},
title = {SecOps-2k},
year = {2026},
version = {v0.1.2},
doi = {10.5281/zenodo.22341506},
url = {https://doi.org/10.5281/zenodo.22341506},
}Also cite the LogHub papers that defined the format and metrics: Jiang et al., ISSTA 2024 (arXiv:2308.10828); Zhu et al., ISSRE 2023 (arXiv:2008.06448).
