Defang / Refang — Python source
Make URLs, IPs, and emails safe to paste by defanging indicators (https:// → hxxps[://], . → [.], @ → [@]) - and reverse refanged text back to its original form. Runs entirely in your browser, with a shareable link to your exact input and mode.
This is the Python implementation — the same logic the interactive tool runs, in a shareable, citable form.
"""defang-refang — make URLs, IPs, and emails safe to paste (and reverse it).
Language: Python (3.9+, standard library only)
Source: CosmoDev polyglot showcase port of the Defang/Refang tool, ported from
src/lib/defang.ts (the canonical TypeScript implementation) and held
in lock-step with cli/defang-refang/defang-refang.go.
License: display source — part of CosmoDev's polyglot tool pages.
Design goals:
- Pure + deterministic; never raises.
- Functionally equivalent to the TS / Go reference: same inputs -> same outputs.
- Self-contained: stdlib only (str.replace is built into the language — no
imports beyond ``annotations`` for forward-compat typing).
Algorithm: ``defang`` replaces ``https://`` / ``http://`` schemes with
``hxxps[://]`` / ``hxxp[://]``, then brackets EVERY dot as ``[.]`` and every
at-sign as ``[@]`` — the standard threat-intel indicator-defanging convention.
``refang`` is its exact inverse: scheme markers are restored first, then
``[.]`` / ``[@]`` are unbracketed, so ``refang(defang(x)) == x`` for typical
URLs, IPs, emails, and plain text.
Ordering note: scheme replacements run BEFORE dot/at bracketing so the dots and
colon inside the resulting ``[://]`` marker are not themselves re-bracketed
(which would corrupt the scheme marker). Note that EVERY dot is bracketed, not
just the domain separator — so defang is NOT idempotent by design: apply it
once to fresh text. ``str.replace`` replaces every occurrence by default,
matching the ``replaceAll`` semantics of the TS source.
"""
from __future__ import annotations
__all__ = ["defang", "refang"]
def defang(text: str) -> str:
"""Defang text so URLs, IPs, and emails are no longer clickable or auto-linked.
Mirrors ``defang()`` in src/lib/defang.ts and ``Defang()`` in the Go twin,
and must agree with both on every shared vector. Scheme replacements run
first so the dots and colon inside the resulting ``[://]`` marker are not
themselves re-bracketed. EVERY dot is bracketed, not just the domain
separator. Empty input returns empty; text with no indicators passes through
unchanged.
"""
return (
text.replace("https://", "hxxps[://]")
.replace("http://", "hxxp[://]")
.replace(".", "[.]")
.replace("@", "[@]")
)
def refang(text: str) -> str:
"""Reverse defanging — restore ``hxxps[://]`` / ``hxxp[://]`` to real schemes
and unbracket ``[.]`` / ``[@]``. Mirrors ``refang()`` in src/lib/defang.ts
and ``Refang()`` in the Go twin: the exact inverse of :func:`defang`.
Scheme markers are restored before ``[.]`` / ``[@]`` are unbracketed, so a
marker like ``hxxps[://]`` reassembles into ``https://`` rather than being
split by an earlier dot/at substitution. Empty input returns empty.
"""
return (
text.replace("hxxps[://]", "https://")
.replace("hxxp[://]", "http://")
.replace("[.]", ".")
.replace("[@]", "@")
)
Also available in 13 other languages
Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →