Skip to content
ATR-2026-01948criticalContext Exfiltrationdraft

netlicensing-mcp Path Traversal in product_number Bypasses Token Redaction (GHSA-hxpf-9xvq-wph8)

Detects GHSA-hxpf-9xvq-wph8 (CRITICAL): NetLicensing-MCP <= 0.1.5 interpolates the netlicensing_get_product tool's `product_number` parameter into a REST path without validation (products.py:22 -> nl_get(f"/product/{product_number}")). Supplying `../token` (or URL-encoded `%2e%2e/token`) produces `/product/../token`, which httpx normalizes to the `/token` endpoint. The response is wrapped as a Product instead of a token, skipping redact_token_read(), so the raw APIKEY ("number" field), "shopURL", and "console_url" plaintext secret are returned. This rule keys on the product_number = ../token traversal payload and its encoded variants reaching the netlicensing product tool/path.

Severity
critical
Category
Context Exfiltration
Scan Target
both
Author
ATR Community

Response Actions

alertblock input

References

OWASP Agentic
ASI06:2026 - Tool Misuse
OWASP LLM
LLM06:2025 - Excessive Agency
MITRE ATLAS
AML.T0049 - Exploit Public-Facing Application

Detection Conditions

Combinator: any
  1. 01
    netlicensing_get_product product_number parameter set to ../token or %2e%2e/token — the exact path-traversal payload that redirects /product to the /token endpoint
    field: contentop: regex
  2. 02
    Literal traversal path /product/../token (or encoded) that httpx normalizes to /token, leaking the raw APIKEY via skipped redact_token_read
    field: contentop: regex
  3. 03
    The netlicensing get_product tool invoked with a ../token traversal argument
    field: contentop: regex
  4. 04
    explicit GHSA framing combined with the traversal/redaction-bypass keywords
    field: contentop: regex

Attack Examples (Rule Triggers)

  1. netlicensing_get_product(product_number="../token")
  2. {"tool": "netlicensing_get_product", "arguments": {"product_number": "%2e%2e/token"}}
  3. GET /core/v2/rest/product/../token  (normalizes to /core/v2/rest/token and returns the raw number/APIKEY field)
  4. GHSA-hxpf-9xvq-wph8: set product_number to ../token to bypass redact_token_read and leak the console_url plaintext secret

Real-world attack payloads, sanitized and versioned alongside the rule as regression tests — so a future revision can't silently stop catching them.

Benign Examples (Rule Doesn't Trigger)

  1. Legitimate product lookup with a real alphanumeric product number, no traversal
    netlicensing_get_product(product_number="PRD-2026-0042")
  2. Doc describing the two endpoints separately without a ../token traversal payload
    The netlicensing-mcp server exposes /product/{number} and a separate /token endpoint for license management.
  3. Normal get_product tool call with a benign product number string
    {"tool": "netlicensing_get_product", "arguments": {"product_number": "STARTER-PLAN"}}

Known False Positive Contexts

  • A legitimate netlicensing_get_product call with a real alphanumeric product_number (e.g. product_number=PRD-001) that contains no ../ traversal.
  • Documentation describing the /product/{number} and /token REST endpoints separately without a traversal payload joining them.
  • Generic mention of the netlicensing-mcp server or its tools without the ../token product_number payload.

Full YAML Definition

Edit on GitHub →
title: "netlicensing-mcp Path Traversal in product_number Bypasses Token Redaction (GHSA-hxpf-9xvq-wph8)"
id: ATR-2026-01948
rule_version: 1
status: draft
description: >
  Detects GHSA-hxpf-9xvq-wph8 (CRITICAL): NetLicensing-MCP <= 0.1.5 interpolates the
  netlicensing_get_product tool's `product_number` parameter into a REST path without
  validation (products.py:22 -> nl_get(f"/product/{product_number}")). Supplying
  `../token` (or URL-encoded `%2e%2e/token`) produces `/product/../token`, which httpx
  normalizes to the `/token` endpoint. The response is wrapped as a Product instead of a
  token, skipping redact_token_read(), so the raw APIKEY ("number" field), "shopURL", and
  "console_url" plaintext secret are returned. This rule keys on the product_number =
  ../token traversal payload and its encoded variants reaching the netlicensing product
  tool/path.
author: "ATR Community"
date: "2026/06/29"
schema_version: "0.1"
detection_tier: pattern
maturity: test
severity: critical
references:
  owasp_llm:
    - "LLM06:2025 - Excessive Agency"
  owasp_agentic:
    - "ASI06:2026 - Tool Misuse"
  mitre_atlas:
    - "AML.T0049 - Exploit Public-Facing Application"
  mitre_attack:
    - "T1190 - Exploit Public-Facing Application"
  cve:
    - "GHSA-hxpf-9xvq-wph8"
metadata_provenance:
  mitre_atlas: human-reviewed
  owasp_llm: human-reviewed
  owasp_agentic: human-reviewed
compliance:
  eu_ai_act:
    - article: "15"
      context: "Article 15 (accuracy, robustness, cybersecurity) — runtime detection of this technique is a cybersecurity control for high-risk AI systems. Technique: netlicensing-mcp Path Traversal in product_number Bypasses Token Redaction (GHSA-hxpf-9xvq-wph8)."
      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. Technique: netlicensing-mcp Path Traversal in product_number Bypasses Token Redaction (GHSA-hxpf-9xvq-wph8)."
      strength: secondary
  nist_ai_rmf:
    - subcategory: "MP.5.1"
      context: "NIST AI RMF MAP 5.1 — likelihood and impact of the identified attack are characterised; this rule detects the adversarial input at runtime. Technique: netlicensing-mcp Path Traversal in product_number Bypasses Token Redaction (GHSA-hxpf-9xvq-wph8)."
      strength: primary
    - subcategory: "MG.3.2"
      context: "NIST AI RMF MANAGE 3.2 — runtime monitoring/maintenance control that surfaces this attack class. Technique: netlicensing-mcp Path Traversal in product_number Bypasses Token Redaction (GHSA-hxpf-9xvq-wph8)."
      strength: secondary
  iso_42001:
    - clause: "8.1"
      context: "ISO/IEC 42001 Clause 8.1 (operational planning and control) — detection of this payload is an operational control. Technique: netlicensing-mcp Path Traversal in product_number Bypasses Token Redaction (GHSA-hxpf-9xvq-wph8)."
      strength: primary
    - clause: "8.3"
      context: "ISO/IEC 42001 Clause 8.3 (AI risk treatment) — this rule implements runtime detection as a treatment control. Technique: netlicensing-mcp Path Traversal in product_number Bypasses Token Redaction (GHSA-hxpf-9xvq-wph8)."
      strength: secondary
tags:
  category: context-exfiltration
  subcategory: rest-path-traversal-token-leak
  scan_target: both
  confidence: high
  source: cve-disclosure
  vendor_sources: netlicensing-mcp-ghsa-hxpf-9xvq-wph8
agent_source:
  type: llm_io
  framework:
    - any
  provider:
    - any
detection:
  condition: any
  false_positives:
    - "A legitimate netlicensing_get_product call with a real alphanumeric product_number (e.g. product_number=PRD-001) that contains no ../ traversal."
    - "Documentation describing the /product/{number} and /token REST endpoints separately without a traversal payload joining them."
    - "Generic mention of the netlicensing-mcp server or its tools without the ../token product_number payload."
  conditions:
    - field: content
      operator: regex
      value: '(?i)product_number\s*[=:]\s*["\x27]?\s*(?:\.\.|%2e%2e)\s*[/\\]\s*token'
      description: >
        netlicensing_get_product product_number parameter set to ../token or %2e%2e/token —
        the exact path-traversal payload that redirects /product to the /token endpoint
    - field: content
      operator: regex
      value: '(?i)/product/\s*(?:\.\.|%2e%2e)\s*[/\\]\s*token'
      description: >
        Literal traversal path /product/../token (or encoded) that httpx normalizes to
        /token, leaking the raw APIKEY via skipped redact_token_read
    - field: content
      operator: regex
      value: '(?i)(?:netlicensing[_-]?get[_-]?product|get_product)[\s\S]{0,120}(?:\.\.|%2e%2e)[/\\]token'
      description: >
        The netlicensing get_product tool invoked with a ../token traversal argument
    - field: content
      operator: regex
      value: '(?i)GHSA-hxpf-9xvq-wph8[\s\S]{0,200}(?:path\s*traversal|product_number|\.\./token|redact|token\s*redaction)'
      description: "explicit GHSA framing combined with the traversal/redaction-bypass keywords"
response:
  actions:
    - alert
    - block_input
  message_template: >
    [ATR-2026-01948] CRITICAL: netlicensing-mcp product_number path traversal (../token)
    bypasses token redaction and leaks the raw NetLicensing APIKEY. Block and upgrade to
    netlicensing-mcp >= 0.1.8.
confidence: 80
wild_fp_rate: 0
test_cases:
  true_positives:
    - input: 'netlicensing_get_product(product_number="../token")'
      expected: triggered
      description: "Exact GHSA-hxpf-9xvq-wph8 PoC: product_number=../token traverses /product to /token leaking the APIKEY"
    - input: '{"tool": "netlicensing_get_product", "arguments": {"product_number": "%2e%2e/token"}}'
      expected: triggered
      description: "URL-encoded %2e%2e/token traversal payload in the tool arguments"
    - input: "GET /core/v2/rest/product/../token  (normalizes to /core/v2/rest/token and returns the raw number/APIKEY field)"
      expected: triggered
      description: "Literal /product/../token path that httpx normalizes to the token endpoint"
    - input: "GHSA-hxpf-9xvq-wph8: set product_number to ../token to bypass redact_token_read and leak the console_url plaintext secret"
      expected: triggered
      description: "Explicit advisory reference with the traversal + redaction-bypass exploit description"
  true_negatives:
    - input: 'netlicensing_get_product(product_number="PRD-2026-0042")'
      expected: not_triggered
      description: "Legitimate product lookup with a real alphanumeric product number, no traversal"
    - input: "The netlicensing-mcp server exposes /product/{number} and a separate /token endpoint for license management."
      expected: not_triggered
      description: "Doc describing the two endpoints separately without a ../token traversal payload"
    - input: '{"tool": "netlicensing_get_product", "arguments": {"product_number": "STARTER-PLAN"}}'
      expected: not_triggered
      description: "Normal get_product tool call with a benign product number string"

Revision History

Created
2026-06-29
Last modified
2026-07-02
View full commit history on GitHub →