GitHub Packages · MIT · Node ≥ 18

defang-sentinel

Defang and refang indicators of compromise, and stop live malicious links from getting into threat reports, tickets and docs.

Defang and refang IOCs (hxxps://evil[.]com) in text, logs and reports with several styles, and a CI check that fails when threat reports, tickets or docs contain live, clickable or half-defanged URLs, domains, IPs or emails. CLI, library and GitHub Action. Zero deps.

  1. 1 Point the @mrlouiswright scope at GitHub Packages in .npmrc

    @mrlouiswright:registry=https://npm.pkg.github.com
  2. 2 Install

    npm i -D @mrlouiswright/defang-sentinel
Installing from GitHub Packages needs a token

Published 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.

~/project — zsh
$ npx defang-sentinel notes.mddefang-sentinel — 1 target(s) notes.md  HIGH     notes.md:1  Live url hxxp://evil-update[.]com/payload.bin [live-url]           ↳ fix: Write it as hxxp://evil-update[.]com/payload.bin (run: defang-sentinel defang --write notes.md).  MEDIUM   notes.md:1  Live IP address 185[.]220[.]101[.]45 [live-ip]           ↳ fix: Write it as 185[.]220[.]101[.]45 (run: defang-sentinel defang --write notes.md). 1 high, 1 medium✖ Failing (fail-on: medium).
Real output from running defang-sentinel locally on a test fixture.

Why it exists

Threat-intel write-ups, incident tickets and detection repos are full of malicious URLs, domains and IPs. A single clickable “https://” link to a C2 server in a Markdown report is an accident waiting to happen. defang-sentinel does three jobs:

1. defang: rewrite live indicators as safe text (“https://evil.com” → “hxxps://evil[.]com”) in four styles. 2. refang: turn defanged indicators back into usable ones for tooling (“hxxps[://]evil[.]com” → “https://evil.com”). 3. check (default): scan files or directories and fail CI when a report contains live, clickable or half-defanged indicators.

Features

Detects

URLs (http/https/ftp/sftp/ws), domains (validated against gTLD/ccTLD lists, with file names such as setup.py ignored), public IPv4/IPv6 addresses (private, loopback and documentation ranges ignored unless --include-private; version strings like v1.2.3.4 skipped) and email addresses.

Clickable link detection

(live-link, high): Markdown links text, reference links, autolinks <https://…> and HTML href attributes. Defanged link text doesn't help if the href is still live.

Half-defanged detection

(partial-defang): hxxp://evil.com or evil[.]com.badhost.ru look safe at a glance but still contain a live host.

Reference allowlist

links to MITRE ATT&CK, NVD, CVE.org, CISA, NCSC, VirusTotal, abuse.ch, urlscan, GitHub and others are expected in reports and allowed by default (--no-reference-domains turns this off). Add your own with --ignore-domain or ignoreDomains in the config.

Defang styles

(--style): brackets (default) hxxps://www[.]evil[.]com/a.php, full hxxps[://]www[.]evil[.]com/a[.]php, dot hxxps://www[dot]evil[dot]com, minimal hxxps://www.evil[.]com. Emails become user[@]domain[.]com; IPv6 colons become [:].

Refang

understands hxxp, hXXps, h[xx]p, fxp, [.], (.), {.}, [dot], (dot), \., [:], [://], [@], (at), [at].

Usage

# Example

 echo 'C2: https://evil.com/gate.php 45.9.148.3' | npx defang-sentinel defang -

# Example

 npx defang-sentinel refang iocs.txt > iocs-live.txt

# Example

 npx defang-sentinel defang --write reports/2026-10-apt.md

# Example

 npx defang-sentinel reports/ --skip-code --ignore-domain 'mycompany.com,*.mycompany.com'

CI / GitHub Action

permissions:
  contents: read
  security-events: write   # only for the SARIF upload
steps:
  - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
    with: { persist-credentials: false }
  - uses: MrLouisWright/defang-sentinel@v1
    with:
      targets: 'reports/'
      fail-on: medium
      sarif: defang-sentinel.sarif
  - uses: github/codeql-action/upload-sarif@v3
    if: always()
    with: { sarif_file: defang-sentinel.sarif }

Options & flags

FlagDescription
Defang/refang
--style <s>brackets | full | dot | minimal (default brackets)
-w, --writeRewrite the file in place instead of printing
Check
--include-privateAlso flag private/loopback IPs
--skip-codeIgnore fenced code blocks in Markdown
--ext <list>Extensions to scan in directories (default .md,.markdown,.txt,.rst,.adoc,.html,...)
Policy and output
-c, --config <file>JSON config (default .defang-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 medium)
--list-rulesPrint rules and default severities
--no-colorDisable colours

Full reference, config file format and API in the README.

Support this project

Support open-source security tools

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

Portrait of Louis Wright

About the author

Louis Wright

Cyber security researcher and software engineer based in the UK.

More tools by Louis Wright

58 tools

Sentinels security scanners & CI gates · 19