<?xml version='1.0' encoding='UTF-8'?>
<rfc xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" category="info" docName="draft-grimminck-safe-ioc-sharing-05" ipr="trust200902" xml:lang="en" version="3" submissionType="IETF">
  <front>
    <title abbrev="Safe-IOC Sharing">A Standard for Safe and Reversible Sharing of Malicious URLs and Indicators</title>
    <author fullname="Stefan Grimminck" role="editor">
      <address>
        <email>ietf@stefangrimminck.nl</email>
      </address>
    </author>
    <date year="2026" month="March" day="19"/>
    <abstract>
      <t>This document defines a consistent and reversible method for sharing potentially malicious indicators of compromise (IOCs), such as URLs, IP addresses, email addresses, and domain names. It introduces a safe obfuscation format to prevent accidental execution or activation when IOCs are displayed or transmitted. These techniques aim to standardize the safe dissemination of threat intelligence data. This specification uses the URI syntax defined in RFC 3986 and follows the key word conventions from RFC 2119.</t>
    </abstract>
  </front>
  <middle>
    <section title="Introduction">
      <t>The secure sharing of malicious artifacts is vital to threat intelligence, open-source intelligence (OSINT), and incident response efforts. However, sharing raw URLs, IP addresses, and email addresses associated with malware or threat actors poses a risk of accidental activation.</t>
      <t>The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/> when, and only when, they appear in all capitals, as shown here.</t>
      <t>This document defines a clear and reversible method for obfuscating and de-obfuscating IOCs to support safe sharing across various platforms, formats, and use cases. The requirements language (e.g., "MUST", "SHOULD") follows <xref target="RFC2119"/>, and URI syntax adheres to <xref target="RFC3986"/>.</t>
    </section>

    <section title="Terminology">
      <t><strong>Obfuscating:</strong> The process of altering an indicator so that it cannot be accidentally activated or clicked. This was previously referred to as "defanging".</t>
      <t><strong>De-obfuscating:</strong> The process of restoring an obfuscated indicator to its original, actionable form. This was previously referred to as "refanging".</t>
      <t><strong>IOC:</strong> Indicator of Compromise - data such as a URL, IP address, domain name, email address, or hash associated with malicious activity.</t>
    </section>

    <section title="Problem Statement">
      <t>Inconsistent obfuscation practices hinder the reliable and automated exchange of threat intelligence. For example:</t>
      <ul>
        <li>A URL obfuscated as "h**p://example[.]com" cannot be reliably parsed by tools expecting "hxxp://example[.]com".</li>
        <li>An IP address obfuscated with parentheses (e.g., "192.0.2(.)1") may fail to de-obfuscate in systems expecting "[.]".</li>
      </ul>
      <t>Such inconsistencies reduce the effectiveness of threat detection and response.</t>
    </section>

    <section title="Canonical Transformation Rule" anchor="canonical">
      <t>To prevent nested obfuscation (e.g., "hxxps://example[[.]]com") when an LLM or tool processes the same string twice or in the wrong order, implementations MUST apply transformations in the following strict order of operations. Implementations MUST treat already-obfuscated substrings (e.g., "[.]", "[@]") as opaque and MUST NOT apply transformations to them again; thus, the transformation is idempotent. Using encoded characters (such as %2e for ".") SHOULD be avoided to prevent ambiguity.</t>

      <section title="Step 1: Scheme">
        <t>Identify and replace the scheme first. Replace "http" with "hxxp" and "https" with "hxxps". For other schemes (e.g., "ftp"), apply analogous obfuscation (e.g., "fxp").</t>
      </section>

      <section title="Step 2: Userinfo">
        <t>Identify the "@" symbol in the userinfo subcomponent (per <xref target="RFC3986"/>) and replace it with "[@]". This applies to email addresses and URIs containing userinfo (e.g., "username:password@host").</t>
      </section>

      <section title="Step 3: Host">
        <t>Replace all "." (period) characters in the Host subcomponent with "[.]". This applies to domain names and IPv4 addresses, including standalone values (e.g., "evil.com" or "1.1.1.1" without a scheme). IPv6 addresses enclosed in square brackets (e.g., "[2001:db8::1]") MUST retain their colon-based syntax and brackets; do not alter colons or brackets within the IPv6 literal.</t>
      </section>

      <section title="Step 4: Stop">
        <t>Do not process the Path, Query, or Fragment components unless they contain nested URIs that require separate obfuscation. Applying transformations beyond the Host in the primary URI may cause incorrect results.</t>
      </section>
    </section>

    <section title="Formal ABNF Grammar" anchor="abnf">
      <t>The Safe-IOC format is defined using the Augmented BNF (ABNF) notation specified in <xref target="RFC5234"/>. This allows an LLM or tool to generate a parser that can validate whether a string is already obfuscated or needs processing.</t>
      <figure anchor="safe-ioc-abnf">
        <sourcecode type="abnf" name="safe-ioc-abnf"><![CDATA[; Safe-IOC obfuscation symbols
safe-scheme   = "hxxp" / "hxxps"
safe-dot      = "[" "." "]"
safe-at       = "[" "@" "]"

; Additional schemes (e.g., ftp -> fxp)
safe-other-scheme = "fxp" / "fxxps"   ; extensions for ftp, ftps]]></sourcecode>
      </figure>
      <t>A compliant implementation MUST recognize strings containing safe-scheme, safe-dot, and safe-at as obfuscated. A string that requires obfuscation is one that contains literal "http", "https", "." in host/domain contexts, or "@" in userinfo/email contexts without the Safe-IOC bracketing.</t>
    </section>

    <section title="De-obfuscation Techniques" anchor="deobfuscation">
      <t>Tools designed to ingest obfuscated data SHOULD automatically reverse these transformations in a deterministic manner:</t>
      <ul>
        <li>Convert "hxxp" and "hxxps" back to "http" and "https" respectively.</li>
        <li>Convert "[.]" back to ".".</li>
        <li>Convert "[@]" back to "@".</li>
      </ul>
      <t>The order of these replacements does not affect the result. De-obfuscation MUST maintain the original semantics of the data to avoid misinterpretation.</t>

      <section title="Safety Check for Reversibility">
        <t>De-obfuscation MUST only be performed when the output is written to a non-executable buffer (e.g., a variable, string, or file) that cannot be automatically interpreted, executed, or rendered as a clickable link by the system or application. The tool MUST NOT de-obfuscate a string if it is currently being rendered in a "live" environment (e.g., a web browser preview, an active document viewer, or any context where the resulting string could be automatically executed, resolved, or displayed as a clickable link).</t>
        <t>De-obfuscation SHOULD only occur in controlled contexts such as:</t>
        <ul>
          <li>Command-line tools with explicit user confirmation</li>
          <li>Isolated analysis environments (sandboxes)</li>
          <li>Backend processing pipelines that do not render output to users</li>
        </ul>
        <t>Accidental activation during the de-obfuscation process poses a security risk and MUST be prevented.</t>
      </section>
    </section>

    <section title="Example Use Cases">
      <t>Common scenarios include:</t>
      <ul>
        <li><strong>OSINT Sharing:</strong> A report lists obfuscated URLs (e.g., "hxxp://malware[.]com/payload") to prevent accidental clicks.</li>
        <li><strong>Email Communication:</strong> Security teams share obfuscated IOCs like "attacker[@]example[.]com" in email threads.</li>
        <li><strong>Threat Intelligence Platforms:</strong> Automated ingestion of obfuscated IPs (e.g., "192[.]0[.]2[.]1") for blocklist updates.</li>
      </ul>
    </section>

    <section title="Security Considerations" anchor="security">
      <t>While these obfuscation techniques reduce the risk of accidental activation of malicious indicators, obfuscated data SHOULD always be handled with caution.</t>

      <section title="Partial Obfuscation">
        <t>A compliant tool MUST obfuscate both the scheme and the delimiters (periods, at-sign) to be considered Safe-IOC Compliant. Partial obfuscation - for example, replacing only "." with "[.]" while leaving "https" unchanged - creates a false sense of security. A user may incorrectly assume a URL is safe because the period is bracketed, when the scheme remains active and could still trigger automatic linkification or execution in some environments. Implementations MUST NOT produce partially obfuscated output when full obfuscation is intended.</t>
      </section>

      <section title="Parser Confusion">
        <t>Implementations that parse Safe-IOC strings may become confused by malformed or inconsistently obfuscated input. For example, "hxxps://example.com" (scheme obfuscated but dots not) or "https://example[.]com" (dots obfuscated but scheme not) are not valid Safe-IOC formats. Parsers SHOULD validate that obfuscated strings conform to the canonical transformation rule and the ABNF grammar before de-obfuscation. Rejecting or flagging ambiguous input reduces the risk of misinterpretation.</t>
      </section>

      <section title="De-obfuscation in Non-Executable Contexts">
        <t>As stated in <xref target="deobfuscation"/>, de-obfuscation MUST only occur when the result is placed in a non-executable buffer. A non-executable buffer is one that cannot be automatically interpreted by the system (e.g., as a URI to fetch, a command to run, or a link to display). Writing de-obfuscated output into a live document, rich-text editor, or browser address bar before explicit user action creates an unacceptable risk of accidental activation.</t>
      </section>

      <section title="Additional Considerations">
        <ul>
          <li>Implementations that do not follow the canonical transformation rule (e.g., by not treating "[.]" and "[@]" as opaque) MAY produce nested or non-reversible output when obfuscation is applied repeatedly. Compliant implementations avoid this by design.</li>
          <li>Obfuscated URLs in PDFs may still be rendered as hyperlinks; use plain-text formatting.</li>
          <li>Systems processing obfuscated indicators MUST treat them as potentially harmful data, applying sandboxing or isolated environments for analysis.</li>
          <li>Credentials (e.g., <em>username:password</em>) SHOULD NOT be shared, even in obfuscated form, due to inherent security risks.</li>
        </ul>
      </section>
    </section>

    <section title="Implementation Guidance">
      <t>Software designed to parse threat intelligence feeds should explicitly support these obfuscation and de-obfuscation standards. Implementations SHOULD verify correct obfuscation and de-obfuscation through unit tests and validation scripts using the test vectors in <xref target="test-vectors"/>.</t>
    </section>

    <section title="Edge Cases and Special Handling">
      <t><strong>Internationalized Domain Names (IDNs):</strong> Obfuscate punycode domains similarly (e.g., "xn--n3h[.]example[.]com").</t>
      <t><strong>Non-Standard URI Schemes:</strong> For schemes like "ftp", apply analogous obfuscation (e.g., "fxp://example[.]com").</t>
      <t><strong>IPv6 Literals in URIs:</strong> Do not alter colon characters (":") or brackets ("[", "]") in IPv6 addresses. For example, "[2001:db8::1]" MUST remain unchanged. Only scheme names or domain elements surrounding them should be obfuscated.</t>
    </section>

    <section title="IANA Considerations">
      <t>This document has no IANA actions.</t>
    </section>

    <section title="Test Vectors" anchor="test-vectors">
      <t>The following provides a "golden set" of inputs and expected outputs. Implementations SHOULD use these vectors to ensure correct behavior and to avoid under-obfuscation (e.g., missing email addresses) or over-obfuscation (e.g., obfuscating IPv6 colons).</t>
      <ul>
        <li>Standard URL: https://bad.com -&gt; hxxps://bad[.]com</li>
        <li>URL with path: https://evil.example.com/path -&gt; hxxps://evil[.]example[.]com/path</li>
        <li>Deep-link URL: https://bad.com/path/to/page?q=1#frag -&gt; hxxps://bad[.]com/path/to/page?q=1#frag</li>
        <li>HTTP URL: http://attacker.com -&gt; hxxp://attacker[.]com</li>
        <li>FTP URL: ftp://files.example.com/ -&gt; fxp://files[.]example[.]com/</li>
        <li>IPv4 address: 1.1.1.1 -&gt; 1[.]1[.]1[.]1</li>
        <li>IPv4 in URL: http://192.0.2.1 -&gt; hxxp://192[.]0[.]2[.]1</li>
        <li>IPv6 in URL: http://[2001:db8::1]:8080 -&gt; hxxp://[2001:db8::1]:8080</li>
        <li>IPv4-mapped IPv6: http://[::ffff:192.0.2.1] -&gt; hxxp://[::ffff:192.0.2.1]</li>
        <li>Email address: phish@target.com -&gt; phish[@]target[.]com</li>
        <li>Punycode domain: xn--n3h.example.com -&gt; xn--n3h[.]example[.]com</li>
        <li>URL with userinfo: http://user:pass@attacker.com -&gt; hxxp://user:pass[@]attacker[.]com</li>
      </ul>
      <t>Note: The IPv6 rows demonstrate that colons and brackets within the IPv6 literal MUST NOT be altered, including IPv4-mapped IPv6 (::ffff:192.0.2.1). The deep-link row shows that Path, Query, and Fragment (per Step 4) are not processed. The Punycode row shows that IDN labels in punycode form receive the same "[.]" treatment as regular domain labels.</t>
    </section>
  </middle>

  <back>
    <references>
      <name>References</name>
      <references>
        <name>Normative References</name>
        <reference anchor="RFC2119">
          <front>
            <title>Key words for use in RFCs to Indicate Requirement Levels</title>
            <author initials="S." surname="Bradner" fullname="S. Bradner"/>
            <date year="1997" month="March"/>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="2119"/>
        </reference>
        <reference anchor="RFC3986">
          <front>
            <title>Uniform Resource Identifier (URI): Generic Syntax</title>
            <author initials="T." surname="Berners-Lee" fullname="T. Berners-Lee"/>
            <author initials="R." surname="Fielding" fullname="R. Fielding"/>
            <author initials="L." surname="Masinter" fullname="L. Masinter"/>
            <date year="2005" month="January"/>
          </front>
          <seriesInfo name="STD" value="66"/>
          <seriesInfo name="RFC" value="3986"/>
        </reference>
        <reference anchor="RFC5234">
          <front>
            <title>Augmented BNF for Syntax Specifications: ABNF</title>
            <author initials="D." surname="Crocker" fullname="D. Crocker"/>
            <author initials="P." surname="Overell" fullname="P. Overell"/>
            <date year="2008" month="January"/>
          </front>
          <seriesInfo name="STD" value="68"/>
          <seriesInfo name="RFC" value="5234"/>
        </reference>
      </references>
      <references>
        <name>Informative References</name>
        <reference anchor="RFC8174">
          <front>
            <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
            <author initials="B." surname="Leiba" fullname="B. Leiba"/>
            <date year="2017" month="May"/>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="8174"/>
        </reference>
      </references>
    </references>
  </back>
</rfc>
