Module 08 — Driving Security Tools¶
Type 7 · Build-&-Operate — drive a MISP/VirusTotal integration with pymisp: create an event, add and tag IOC attributes, pull VT-shaped enrichment backed by real abuse.ch threat intel, and attach it back to the event. (Secondary: Tool-Build — the reusable glue script that operates the integration end to end.) Go to the hands-on lab →
Last reviewed: 2026-06
Python for Security — the best tool is the one you can script; scripting it means you can scale it.
In 60 seconds
Every security platform — MISP, VirusTotal, TheHive, Shodan — has an API, and the engineer who
scripts it processes hundreds of IOCs while the analyst clicks through one. pymisp wraps the MISP
REST API into Python objects: create an event, add typed attributes (ip-dst, sha256), tag it
(TLP, ATT&CK), enrich from a VT-shaped feed, and attach the verdict back. The operational rule:
never publish automatically at scale — false-positive IOC sharing is a trust problem that's hard
to undo.
Why this matters¶
Security platforms — MISP, VirusTotal, TheHive, Shodan — all have APIs. The analyst who uses them through a browser clicks through one IOC at a time. The engineer who scripts them processes hundreds of IOCs in the same time, logs every action, and can replay the run next week with the same inputs. At enterprise scale, the difference is incident closure time.
Objective¶
Use pymisp (the official MISP Python library) and direct HTTP to interact with a local MISP
instance (your system-of-record): create an event, add attributes (IOCs), tag them, and then
query a VirusTotal-shaped API — backed by real abuse.ch threat intel (Feodo Tracker +
URLhaus) — to pull enrichment and attach it back to the event.
The core idea¶
pymisp is a thin wrapper around the MISP REST API — every operation it exposes is a structured
HTTP call with JSON. The reason to use pymisp rather than raw httpx for MISP operations is
that it handles the object model (events, attributes, tags) and the MISP-specific auth header
(Authorization: <api_key>) correctly, and it gives you Python objects rather than raw
dictionaries to work with. But the principle applies to any security platform: understand the
REST API first, then decide whether the library saves enough boilerplate to be worth the
dependency.
The mental model
pymisp is a thin wrapper over structured HTTP-with-JSON — the same shape as any platform API. The
rule generalizes: understand the REST API first, then decide whether the library saves enough
boilerplate to justify the dependency. The library is a convenience, not a substitute for knowing
what it sends.
Creating a MISP event from an alert is a four-step operation: create the event (metadata — who
reported it, when, what threat level), add attributes (the actual IOCs with their type: ip-dst,
domain, sha256, md5), tag the event (TLP, MISP taxonomies, ATT&CK technique), and publish.
These four steps map directly to four API calls. The model for a "MISP attribute" is: type +
value + category + comment — every IOC in a MISP event is described by those four fields.
The integration pattern — query VirusTotal for an IOC, attach the VT verdict as a MISP comment
or a MISP object — is the same pattern used in automated enrichment pipelines across the
industry. The VT response tells you the detection ratio (how many engines flagged it); you attach
that as a comment or a vt-report object to the MISP attribute. The event then carries both
the raw IOC and the enrichment in one place, queryable and shareable via MISP's federated sync.
flowchart LR
E["create event<br/>(metadata)"] --> A["add attributes<br/>(ip-dst, sha256)"]
A --> T["tag<br/>(TLP, ATT&CK)"]
A --> VT["query VT-shaped feed"]
VT --> AB["attach verdict back<br/>(comment / vt-report)"]
T --> H{"human review"}
AB --> H
H -->|approved| P["publish / sync"]
The gotcha
Write automation that produces events you'd be comfortable having a human review — and gate it. Never create MISP events automatically at scale without a human-in-the-loop step, at least for the first run against a new source. Sharing a known-good IP to your MISP community as malicious is a trust problem that's hard to undo, and it propagates through federated sync before you notice.
The operational discipline is exactly that human-review gate, designed in from the start.
Learn (~2.5 hrs)¶
MISP API and pymisp (~1.5 hrs)
- PyMISP — Official documentation — read "Getting started" and "Event management"; the examples are the fastest path to understanding the object model.
- MISP REST API documentation — skim "Authentication" and "Events"; this is the underlying API pymisp wraps; knowing it makes debugging easier.
- MISP Taxonomies — circl.lu — understand TLP, PAP, and the MISP threat taxonomy; knowing which tags are standard is what separates a well-formed event from a private blob.
VirusTotal API (~1 hr)
- VirusTotal API v3 — File/IP/Domain lookups — read the response structure for an IP lookup: last_analysis_stats, reputation, as_owner; these are the fields you'll attach back to MISP.
Key concepts¶
- MISP event anatomy: event → attributes → tags → publish
- MISP attribute type vocabulary:
ip-dst,domain,sha256,md5,url pymisp.MISPEventandpymisp.MISPAttributeas Python objects- TLP and PAP tagging: standard community labels for sharing sensitivity
- Enrichment attach-back: VT verdict as MISP comment or object
- Human-in-the-loop gate: never publish automatically at scale without review
AI acceleration¶
Ask a model to write the MISP event creation and attribute-adding code. It will get the
pymisp API mostly right but will often confuse event.add_attribute() with
misp.add_attribute(event) — one modifies the in-memory object, the other sends an API call.
Run its code against the local MISP and check whether the event actually appears in the MISP UI.
If it doesn't, read the traceback — it will tell you exactly which API call failed.
AI caveat
Models get the pymisp object model mostly right but routinely confuse event.add_attribute()
(mutates the in-memory object) with misp.add_attribute(event) (sends an API call) — so the code
runs clean and nothing appears in MISP. Verify against the live UI, not the absence of a traceback.
Check yourself
- What four fields describe every MISP attribute, and what do the four event-creation steps map to?
- Why understand the underlying REST API even when you're using
pymisp? - Why must automated MISP publishing carry a human-in-the-loop gate on a new data source?
Comments
Sign in with GitHub to comment. Choose the type: Feedback (errors or suggestions on this page) · Hints (help for fellow learners — no spoilers) · General (anything else).