qarbaal
Extract, normalize, validate, and export indicators of compromise from text and files.
Documentation: https://ahur4.github.io/Qarbaal/
qarbaal reads reports, logs, and message files on your machine and returns classified indicators. It refangs defanged text, records where each value came from, and writes CSV, JSON, STIX 2.1, MISP, OpenIOC, and network rules. The base install uses only the Python standard library. It does not call an enrichment API.
Installation
Python 3.10 or newer.
pip install qarbaal
That install has no runtime dependencies.
Installing optional extras
Text, JSON, CSV, XML, EML, and MBOX are read with the standard library. The other readers are extras, so a text-only install does not pull them in.
One extra:
pip install "qarbaal[html]"
Several at once:
pip install "qarbaal[html,pdf,docx]"
Every optional extra:
pip install "qarbaal[all]"
| Input | Extra |
|---|---|
| Text, JSON, CSV, XML, EML, MBOX | none |
| HTML | html |
pdf |
|
| DOCX | docx |
| YAML | yaml |
| PCAP | pcap |
A missing extra raises OptionalDependencyError and names the install command.
Pydantic models
pip install "qarbaal[pydantic]"
That extra enables qarbaal.adapters.to_pydantic(indicator) and extraction_to_pydantic(result). Each call returns a pydantic BaseModel (QarbaalIndicator) for validation and serialization in pydantic-based apps and APIs. Core results stay plain dataclasses, so the base install keeps zero runtime dependencies. Calling either adapter without pydantic raises OptionalDependencyError with the install hint.
Quickstart
from qarbaal import IOCExtractor, extract
report = """
From: support[at]corp-it-desk[.]com
Lure: hxxps://login[.]corp-it-desk[.]com/session
Beacon: 185.220.101.42
MD5: d41d8cd98f00b204e9800998ecf8427e
"""
result = extract(report)
for indicator in result:
print(indicator.type, indicator.value, indicator.tags, indicator.line)
extractor = IOCExtractor(
extract_types=["ipv4", "domain", "url", "hash", "email"],
normalize=True,
validate=True,
deduplicate=True,
)
same = extractor.extract(report, source="ticket-14")
extract() uses the default type set. File paths, mutex names, and User-Agent strings stay out of that set until you ask for them with extract_types or "all".
A synthetic incident is included:
from qarbaal import SAMPLE, extract
print(extract(SAMPLE).stats.counts)
What you get back
Each indicator keeps three strings:
| Field | Meaning |
|---|---|
value |
First-seen sieve form. Hashes are lower case, CVE IDs are upper case. |
raw |
Exact slice of the source, which may still be defanged. |
normalized |
Canonical form used for the fingerprint. |
It also carries:
- Provenance on every sighting: source label, line, character offset, and page number for PDF.
- A SHA-256 fingerprint of the type and the normalized value.
raw,value, andnormalizedare all kept. - Local enrichment only. Address flags, a best-effort domain split, and URL parts are computed on the machine. Nothing is sent to a network service.
- Deduplication and cross-source correlation.
occurrencescounts sightings.Extraction.shared()lists indicators that appear in more than one named source. - Custom
PatternSpecpatterns, allow and deny globs, and custom validators. - Streaming through
extract_iterfor large text, with offsets preserved across chunks. - Noise tags, a structural confidence heuristic, and pivot links you open yourself.
Exports are CSV, JSON, JSONL, a defanged list, STIX 2.1, MISP, OpenIOC, and Suricata and Snort rules for addresses, domains, and URLs.
Command line
qarbaal report.txt
qarbaal mail.eml notes.json -f stix -o bundle.json
qarbaal --hide-private --defang -f table alerts.log
qarbaal --types all -f suricata capture.txt
With no file, qarbaal reads stdin. Formats: table, csv, json, jsonl, stix, list, misp, openioc, suricata, snort.
Further reading
Metadata
Release files for qarbaal 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| qarbaal-0.1.1.tar.gz | 60.0 kB | Without provenance | Details for qarbaal-0.1.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| qarbaal-0.1.1-py3-none-any.whl | Python 3 | none | any | Details for qarbaal-0.1.1-py3-none-any.whl |
Total release size: 113.9 kB
Release files / qarbaal-0.1.1.tar.gz
| Download URL | qarbaal-0.1.1.tar.gz |
|---|---|
| Size | 60.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7d897340c1412aa93bd989238a1705cb5aeff1229a7e9fa543afe3bf16d89ae1
|
|
BLAKE2b-256 checksum How to use checksums |
17c5819020195564c6202481cc3264ac820bd0730c5677ae03cbe6c4f17cb7fe
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.5
|
Release files / qarbaal-0.1.1-py3-none-any.whl
| Download URL | qarbaal-0.1.1-py3-none-any.whl |
|---|---|
| Size | 54.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b6f694160b72b388dbf29eaec2cde639932b1dbeb10afae282ef69b07a105623
|
|
BLAKE2b-256 checksum How to use checksums |
5b767ee4e8a3b9600c8b7511e33c046500af0af453a497afc886e8dd9a6eded2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.5
|
Security for qarbaal 0.1.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.