16 IOC types
url, domain, ipv4, ipv6, email, md5, sha1, sha256, sha512, cve, attack, btc, eth, xmr, registry, filename (shortcuts: hash, ip, wallet).
GitHub Packages · MIT · Node ≥ 18
Extract indicators of compromise from threat reports, logs, emails and binaries, then export them as CSV, STIX 2.1, JSON or SARIF.
IOC extractor for threat intel and incident response: pulls URLs, domains, IPv4/IPv6, emails, MD5/SHA1/SHA256/SHA512, CVEs, ATT&CK IDs, crypto wallets and registry keys from text, logs and reports, refangs defanged IOCs, filters noise and exports JSON, CSV, STIX 2.1 and SARIF. Zero deps.
1 Point the @mrlouiswright scope at GitHub Packages in .npmrc
@mrlouiswright:registry=https://npm.pkg.github.com2 Install
npm i -D @mrlouiswright/ioc-sentinelPublished to GitHub Packages, not npmjs.com. GitHub Packages needs a GitHub token with read:packages to install, even for public packages: add //npm.pkg.github.com/:_authToken=${GITHUB_TOKEN} to .npmrc or run npm login --registry=https://npm.pkg.github.com.
$ npx ioc-sentinel report.txtioc-sentinel — 1 target(s) report.txt iocs: 6 url: 1 domain: 2 ipv4: 1 sha256: 1 email: 1 MEDIUM report.txt:2 SHA256: 275a021bbfb6489e54d471899f7db9d1663fc695ec2fe2a2c4538aabf651fd0f [ioc-hash] MEDIUM report.txt:1 URL: hxxp[://]evil-update[.]com/payload[.]bin [ioc-url] LOW report.txt:1 Domain: evil-update[.]com [ioc-domain] LOW report.txt:3 Domain: login-micros0ft[.]net [ioc-domain] LOW report.txt:3 Email: phish[@]login-micros0ft[.]net [ioc-email] LOW report.txt:1 IPv4: 185[.]220[.]101[.]45 [ioc-ipv4] 2 medium, 4 low✔ Passing (fail-on: critical).
ioc-sentinel pulls IOCs out of any text: URLs, domains, IPv4/IPv6 addresses, email addresses, MD5/SHA1/SHA256/SHA512 hashes, CVE IDs, MITRE ATT&CK IDs, Bitcoin/Ethereum/Monero wallets, Windows registry keys and suspicious file names. It refangs defanged indicators (“hxxps://evil[.]com”, “user[@]domain(dot)ru”) before matching, removes the usual noise (private IPs, example.com, XML namespaces, setup.py-style file names) and can fail a pipeline when an IOC matches your watchlist.
CLI, library and GitHub Action. Node.js 18+, zero runtime dependencies. Binaries are never executed: printable ASCII and UTF-16LE strings are read statically.
url, domain, ipv4, ipv6, email, md5, sha1, sha256, sha512, cve, attack, btc, eth, xmr, registry, filename (shortcuts: hash, ip, wallet).
hxxp, hXXps, fxp, [.], (.), {.}, [dot], \., [:], [://], [@], (at).
domains are checked against the gTLD/ccTLD list. Names ending in file extensions (.exe, .py, .md, .zip...) count as file names unless the analyst defanged them. Private, loopback, CGNAT, documentation, multicast and reserved IPs are dropped unless you pass --include-private. Repetitive hashes (000…) are ignored, Ethereum addresses aren't mistaken for SHA1, and legacy Bitcoin addresses are Base58Check-validated. A built-in benign-domain list can be replaced (--benign) or disabled (--no-benign).
(-w known-bad.txt): one IOC per line, defanged values accepted, with an optional label after a space, tab or comma. Supports IPv4 CIDR ranges, parent domains (evil.com also matches cdn.evil.com and URLs on it) and URL prefixes. Hits produce watchlist-match (critical), so the default --fail-on critical fails only on known-bad indicators.
files, whole directories (skips .git and node_modules), or stdin (-). Binary files are scanned via static string extraction.
--format csv|stix|list or --csv/--stix <file>, with --defang to make CSV/list output safe to paste. The STIX 2.1 bundle contains indicators with proper patterns ([file:hashes.'SHA-256' = '…']), plus vulnerability and attack-pattern objects for CVEs and ATT&CK IDs, using deterministic IDs. The JSON report has a deduplicated iocs array with counts and file:line sources.
# human-readable list, grouped by file
npx ioc-sentinel report.pdf.txt# Example
npx ioc-sentinel ./case-42/ --format csv --defang > iocs.csv# exit 1 on a watchlist hit
cat alert.eml | npx ioc-sentinel - -w known-bad.txt# Example
npx ioc-sentinel logs/ --types url,domain,ip --stix iocs.stix.json --sarif iocs.sarifpermissions:
contents: read
security-events: write # only for the SARIF upload
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with: { persist-credentials: false }
- uses: MrLouisWright/ioc-sentinel@v1
with:
targets: 'reports/'
fail-on: critical
sarif: ioc-sentinel.sarif
- uses: github/codeql-action/upload-sarif@v3
if: always()
with: { sarif_file: ioc-sentinel.sarif }
| Flag | Description |
|---|---|
| Extraction | |
-t, --types <list> | url, domain, ipv4, ipv6, email, md5, sha1, sha256, sha512, cve, attack, btc, eth, xmr, registry, filename (also: hash, ip, wallet). Default: all |
--include-private | Keep private/loopback/documentation IPs (dropped by default) |
--benign <list> | Domains to ignore (globs ok); replaces the built-in noise list |
--no-benign | Do not drop example.com, w3.org, schemas.microsoft.com etc. |
--no-refang | Do not refang hxxp://, [.] and friends before matching |
--no-binary | Skip binary files (default: extract printable strings statically) |
--file-name-domains | Treat names like "setup.py"/"invoice.zip" as domains too |
-w, --watchlist <file> | Known-bad IOCs (one per line; CIDR and *.domain ok). Hits are critical |
| Export | |
-f, --format <fmt> | text | json | sarif | markdown | csv | stix | list |
--defang | Defang values in csv/list output |
--csv <file> | Also write CSV; --stix <file> also write a STIX 2.1 bundle |
| Policy and output | |
-c, --config <file> | JSON config (default .ioc-sentinel.json if present) |
-f, --format <fmt> | text (default) | json | sarif | markdown |
--json/--sarif/--markdown <file> | Also write that format to a file |
--fail-on <sev> | critical | high | medium | low | info | none (default critical) |
--list-rules | Print rules and default severities |
--no-color | Disable colours |
Full reference, config file format and API in the README.
Support this project
I build free, open-source tools that help developers ship safer websites. Every coffee helps keep them maintained, documented and free for everyone.
Buy me a coffee (opens Stripe in a new tab)Secure checkout by Stripe