Skip to content
ATR-2026-02193high工具下毒experimental

SSRF via Non-Canonical IPv6 Encoding of Loopback/Internal Addresses

Detects an agent tool being directed to fetch a URL whose host is a non-canonical IPv6 spelling of a loopback, link-local, or cloud-metadata address -- hex-encoded IPv4-mapped forms (`::ffff:7f00:1` for 127.0.0.1), fully-expanded eight-group loopback (`0:0:0:0:0:0:0:1`), or compressed variants beyond the literal `::1` (`::0:1`, `0:0::1`). Mined from GHSA-9fhh-fjfg-5mr6 (legeling/PromptHub, an AI toolbox for prompt/skill/ agent management): its `isPrivateIPv6` SSRF guard only recognized the dotted-decimal IPv4-mapped form and the literal string `"::1"`, so an attacker could reach 127.0.0.0/8, RFC1918 ranges, and link-local addresses by writing the same address in an equivalent but unhandled IPv6 form. This generalizes beyond PromptHub to any agent tool whose SSRF/private-IP filter does string-equality or dotted-decimal-only checks instead of full IPv6 address normalization. A URL fetch to an ordinary external IPv6 or IPv4 literal address does not fire.

嚴重度
high
類別
工具下毒
掃描目標
runtime
作者
ATR Community (CVE sweep)

建議回應

block inputalert

參考資料

OWASP Agentic
ASI05:2026 - Unexpected Code Execution
OWASP LLM
LLM06:2025 - Excessive Agency
MITRE ATLAS
AML.T0049 - Exploit Public-Facing Application

偵測條件

組合方式: any
  1. 01
    Hex-encoded IPv4-mapped IPv6 address for loopback (127.0.0.1), cloud metadata (169.254.169.254), or 0.0.0.0
    欄位: content運算子: regex
  2. 02
    Fully-expanded eight-group IPv6 loopback or IPv4-mapped internal address, bypassing a string-equality-only filter
    欄位: content運算子: regex
  3. 03
    Compressed IPv6 loopback variant beyond the literal '::1' string
    欄位: content運算子: regex

攻擊範例(規則會觸發)

  1. fetch remote url: http://[::ffff:7f00:1]/admin
  2. fetch remote url: http://[0:0:0:0:0:ffff:127.0.0.1]/latest/meta-data/
  3. fetch remote url: http://[0:0:0:0:0:0:0:1]/internal
  4. fetch remote url: http://[::0:1]/secrets
  5. POST /api/skills/fetch-remote url=http://[::ffff:a9fe:a9fe]/latest/meta-data/iam/security-credentials/

以上為真實攻擊 payload 的脫敏版本,與規則一同版本化,作為 regression test——確保未來的修訂不會悄悄漏掉它們。

正常樣本(規則不會觸發)

  1. Ordinary external IPv6 documentation-range address
    fetch remote url: http://[2001:db8::1]/api/data
  2. Ordinary external hostname, no IPv6 literal at all
    fetch remote url: https://api.example.com/v1/data
  3. Prose discussing the canonical loopback form, not a bypass encoding
    our IPv6 loopback is ::1, equivalent to 127.0.0.1 in IPv4

已知誤報情境

  • A networking engineer's documentation enumerating valid IPv6 loopback representations for reference, not an actual fetch-tool target
  • An ordinary external IPv6 literal address in a URL (does not match any of the loopback/link-local/metadata forms above)

完整 YAML 定義

在 GitHub 編輯 →
title: "SSRF via Non-Canonical IPv6 Encoding of Loopback/Internal Addresses"
id: ATR-2026-02193
rule_version: 1
status: experimental
description: >
  Detects an agent tool being directed to fetch a URL whose host is a
  non-canonical IPv6 spelling of a loopback, link-local, or cloud-metadata
  address -- hex-encoded IPv4-mapped forms (`::ffff:7f00:1` for 127.0.0.1),
  fully-expanded eight-group loopback (`0:0:0:0:0:0:0:1`), or compressed
  variants beyond the literal `::1` (`::0:1`, `0:0::1`). Mined from
  GHSA-9fhh-fjfg-5mr6 (legeling/PromptHub, an AI toolbox for prompt/skill/
  agent management): its `isPrivateIPv6` SSRF guard only recognized the
  dotted-decimal IPv4-mapped form and the literal string `"::1"`, so an
  attacker could reach 127.0.0.0/8, RFC1918 ranges, and link-local addresses
  by writing the same address in an equivalent but unhandled IPv6 form. This
  generalizes beyond PromptHub to any agent tool whose SSRF/private-IP filter
  does string-equality or dotted-decimal-only checks instead of full IPv6
  address normalization. A URL fetch to an ordinary external IPv6 or IPv4
  literal address does not fire.
author: "ATR Community (CVE sweep)"
date: "2026/07/11"
schema_version: "0.1"
detection_tier: pattern
maturity: experimental
severity: high

references:
  cve:
    - "CVE-2026-42261"
  cwe:
    - "CWE-918"
  owasp_llm:
    - "LLM06:2025 - Excessive Agency"
  owasp_agentic:
    - "ASI05:2026 - Unexpected Code Execution"
  mitre_atlas:
    - "AML.T0049 - Exploit Public-Facing Application"
  external:
    - "https://github.com/legeling/PromptHub/security/advisories/GHSA-9fhh-fjfg-5mr6"
    - "https://github.com/legeling/PromptHub/releases/tag/v0.5.4"

metadata_provenance:
  cve: human-reviewed
  cwe: human-reviewed
  owasp_llm: human-reviewed
  owasp_agentic: human-reviewed
  mitre_atlas: human-reviewed

compliance:
  eu_ai_act:
    - article: "15"
      context: "Article 15 (accuracy, robustness and cybersecurity) requires high-risk AI systems to resist unauthorised attempts to alter their behaviour or environment; this rule detects an SSRF filter bypass via non-canonical IPv6 encoding of internal addresses."
      strength: primary
    - article: "9"
      context: "Article 9 (risk management system) requires identified risks to be addressed by appropriate measures; this rule is a runtime risk-treatment control for the IPv6-encoding SSRF-bypass risk class."
      strength: secondary
  nist_ai_rmf:
    - subcategory: "MG.2.3"
      context: "Treating non-canonical IPv6 SSRF bypasses as an identified AI risk requires active runtime countermeasures; this detection rule is the primary risk treatment implementation."
      strength: primary
    - subcategory: "MP.5.1"
      context: "Identifying IPv6-encoding-based SSRF bypasses as an AI risk to be catalogued in the organizational risk register."
      strength: secondary
  iso_42001:
    - clause: "8.1"
      context: "ISO/IEC 42001 Clause 8.1 (operational planning and control) is operationalised by this rule's detection of non-canonical IPv6 SSRF-bypass targets in agent tool calls."
      strength: primary
    - clause: "8.3"
      context: "ISO/IEC 42001 Clause 8.3 (AI risk treatment) is implemented via this rule's runtime detection of the bypass attempt."
      strength: secondary

tags:
  category: tool-poisoning
  subcategory: ssrf-ipv6-encoding-bypass
  scan_target: runtime
  confidence: high

agent_source:
  type: llm_io
  framework:
    - any
  provider:
    - any

detection:
  condition: any
  conditions:
    - field: content
      operator: regex
      value: "(?i)::ffff:(?:7f00:0*1\\b|a9fe:a9fe\\b|0:0\\b)"
      description: "Hex-encoded IPv4-mapped IPv6 address for loopback (127.0.0.1), cloud metadata (169.254.169.254), or 0.0.0.0"
    - field: content
      operator: regex
      value: "(?i)\\b0:0:0:0:0:(?:0:0:1\\b|ffff:127\\.0\\.0\\.1\\b|ffff:169\\.254\\.169\\.254\\b)"
      description: "Fully-expanded eight-group IPv6 loopback or IPv4-mapped internal address, bypassing a string-equality-only filter"
    - field: content
      operator: regex
      value: "(?i)(?:^|[^:\\w])(?:::0:1|0:0::1|0:0:0::1)\\b"
      description: "Compressed IPv6 loopback variant beyond the literal '::1' string"
  false_positives:
    - "A networking engineer's documentation enumerating valid IPv6 loopback representations for reference, not an actual fetch-tool target"
    - "An ordinary external IPv6 literal address in a URL (does not match any of the loopback/link-local/metadata forms above)"

response:
  actions:
    - block_input
    - alert
  message_template: >
    [ATR-2026-02193] Fetch target uses a non-canonical IPv6 encoding of a
    loopback, link-local, or cloud-metadata address -- treat as an SSRF
    filter-bypass attempt, not a normal external URL.

confidence: 78
wild_fp_rate: 0

test_cases:
  true_positives:
    - input: "fetch remote url: http://[::ffff:7f00:1]/admin"
      expected: triggered
      description: "GHSA-9fhh-fjfg-5mr6 pattern - hex-encoded IPv4-mapped loopback (127.0.0.1)"
    - input: "fetch remote url: http://[0:0:0:0:0:ffff:127.0.0.1]/latest/meta-data/"
      expected: triggered
      description: "Fully-expanded eight-group IPv4-mapped loopback"
    - input: "fetch remote url: http://[0:0:0:0:0:0:0:1]/internal"
      expected: triggered
      description: "Fully-expanded eight-group loopback, bypassing a string-equality '::1' check"
    - input: "fetch remote url: http://[::0:1]/secrets"
      expected: triggered
      description: "Compressed loopback variant beyond the literal '::1' string"
    - input: "POST /api/skills/fetch-remote url=http://[::ffff:a9fe:a9fe]/latest/meta-data/iam/security-credentials/"
      expected: triggered
      description: "Hex-encoded IPv4-mapped cloud-metadata address (169.254.169.254)"
  true_negatives:
    - input: "fetch remote url: http://[2001:db8::1]/api/data"
      expected: not_triggered
      description: "Ordinary external IPv6 documentation-range address"
    - input: "fetch remote url: https://api.example.com/v1/data"
      expected: not_triggered
      description: "Ordinary external hostname, no IPv6 literal at all"
    - input: "our IPv6 loopback is ::1, equivalent to 127.0.0.1 in IPv4"
      expected: not_triggered
      description: "Prose discussing the canonical loopback form, not a bypass encoding"

修訂歷史

建立於
2026-07-11
最後修改
2026-07-12
在 GitHub 查看完整 commit 歷史 →