Exports¶
Exports live in qarbaal.export.
Machine-readable formats keep live indicator values. The defanged list rewrites them for a report.
Writing a file¶
Every exporter accepts path and filename. path is the directory. filename is the file name, without a directory. The directory is created when it does not exist. Pass a directory and omit filename to use the default name for that format:
| Format | Default file name |
|---|---|
| CSV | qarbaal.csv |
| JSON | qarbaal.json |
| JSONL | qarbaal.jsonl |
| Defanged list | qarbaal.defanged.txt |
| STIX 2.1 | qarbaal.stix.json |
| MISP | qarbaal.misp.json |
| OpenIOC | qarbaal.openioc.xml |
| Suricata | qarbaal.suricata.rules |
| Snort | qarbaal.snort.rules |
Omit path and the file is written in the current working directory. Omit both arguments and the function returns the serialized text.
A call that writes a file returns an ExportFile:
| Field | Meaning |
|---|---|
path |
Absolute path of the written file |
filename |
File name |
size |
Size in bytes |
format |
Format name, such as csv or stix |
count |
Indicators represented in the file. Suricata and Snort count emitted rules. A STIX bundle counts the objects in the bundle. |
sha256 |
SHA-256 digest of the file bytes |
from qarbaal import extract, to_json
result = extract("8.8.8.8 evil.example")
written = to_json(result, path="exports", filename="iocs.json")
print(written.path, written.size, written.count, written.sha256)
ExportFile is a pydantic model. filename must be a single path component. A name that contains a slash is rejected.
CSV¶
to_csv writes a UTF-8 BOM, CRLF line endings, and quotes every field. There is no trailing CRLF. The compact columns are type, value, tags. The detailed form adds normalized, fingerprint, source, line, offset, page, occurrences, confidence, and valid.
JSON¶
Compact JSON is one object:
Empty types are omitted. There is no trailing newline. generated is UTC with millisecond precision and a Z suffix.
Detailed JSON is the same envelope with truncated, stats, and an indicators array. Each object carries provenance, validation, enrichment, and sightings. JSONL is one indicator object per line, with a trailing newline when the list is not empty.
Defanged list¶
to_defanged_list is one defanged value per line, joined with \n, with no trailing newline. Types follow the display order.
STIX 2.1¶
to_stix builds a bundle with uuid and json. It does not import the stix2 package.
| Indicator | STIX object |
|---|---|
| IPv4, IPv6, domain, URL, hashes, email, registry, MAC, mutex, ASN | indicator with a STIX pattern |
| CVE | vulnerability SDO |
CIDR, JA3, JA3S, JARM, paths, User-Agent strings, wallets, and ATT&CK IDs are omitted. A CIDR is not an ipv4-addr, and the omitted types have no pattern that a STIX consumer can use without inventing a vocabulary. Registry and mutex values escape backslashes. URL patterns escape quotes. The indicator label is qarbaal-extracted.
MISP¶
to_misp writes a MISP event as JSON. Addresses and CIDR ranges are ip-dst (direction is not inferred). The other mappings are domain, url, md5, sha1, sha256, sha512, email-src, vulnerability, regkey, btc, mac-address, AS, ja3-fingerprint-md5, ja3s-fingerprint-md5, jarm-fingerprint, mutex, filename for paths, user-agent, and text for ATT&CK IDs. to_ids is false for CVE, MAC, ASN, User-Agent, and ATT&CK attributes.
OpenIOC¶
to_openioc writes an OpenIOC 1.1 document with xml.etree and a pretty-printed body. Each value is an IndicatorItem under an OR group. The Context document and search names follow the type (Network / ipv4, File / md5, and so on).
Suricata and Snort¶
Rules are emitted only for IPv4, IPv6, CIDR, domains, and URLs.
- An address or CIDR becomes an IP rule.
- A domain becomes a Suricata
dns.querycontent rule and a Snort UDP/53 content rule. - A URL becomes a Suricata
http.hostplushttp.urirule, and a Snort rule with both contents.
Values that contain a quote, a backslash, a semicolon, or a newline are skipped so the rule stays valid. If nothing qualifies, the output is the comment # qarbaal: no network indicators to emit.
Hashes, emails, CVEs, and the other types do not become Suricata or Snort rules. A lone hash is not a network signature.
YARA and Sigma¶
YARA and Sigma generation are out of scope. A hash set is not a useful YARA rule: YARA has no standard condition that matches a file hash, and inventing a string rule from a digest would not detect the file. Sigma needs a log source and a field mapping that this library does not have. Write those rules in a tool that knows the log source.
Pydantic¶
Extraction and Indicator are pydantic models. model_dump(mode="json") serializes an indicator, with type written as the short key ("ip", "domain", and so on).