CVE-2026-57496
NetLicensing MCP Server: REST Path Traversal Bypasses Token Redaction
NetLicensing MCP Server is a natural-language interface that enables agentic applications to manage the software-licensing lifecycle in Labs64 NetLicensing. Prior to 0.1.8, netlicensing_get_product passes the caller-controlled product_number to src/netlicensing_mcp/tools/products.py, which interpolates it into a REST path consumed by nl_get() in src/netlicensing_mcp/client.py without path-segment validation. A traversal segment can be normalized from the intended product path to the /token endpoint, after which the response is serialized through _wrap_json instead of _wrap_json_token_read, bypassing redact_token_read() protections for APIKEY number and SHOP shopURL fields. An authenticated MCP client with a non-administrative API key can retrieve plaintext token values, and a recovered administrative token can provide broad read, write, and delete access to the NetLicensing account. This issue is fixed in version 0.1.8.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- Low
- User interaction
- None
What an attacker can affect
- Confidentiality
- High
- Integrity
- High
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used
9.6
NetLicensing MCP Server: REST Path Traversal Bypasses Token Redaction
NetLicensing MCP Server is a natural-language interface that enables agentic applications to manage the software-licensing lifecycle in Labs64 NetLicensing. Prior to 0.1.8, netlicensing_get_product passes the caller-controlled product_number to src/netlicensing_mcp/tools/products.py, which interpolates it into a REST path consumed by nl_get() in src/netlicensing_mcp/client.py without path-segment validation. A traversal segment can be normalized from the intended product path to the /token endpoint, after which the response is serialized through _wrap_json instead of _wrap_json_token_read, bypassing redact_token_read() protections for APIKEY number and SHOP shopURL fields. An authenticated MCP client with a non-administrative API key can retrieve plaintext token values, and a recovered administrative token can provide broad read, write, and delete access to the NetLicensing account. This issue is fixed in version 0.1.8.
- Record
CVE-2026-57496- CVSS 3.1
- 9.6 Critical
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N - Weakness
- CWE-22
- Updated
- 2026-11-02
EUVDEUVD-2026-102319
9.6
NetLicensing MCP Server is a natural-language interface that enables agentic applications to manage the software-licensing lifecycle in Labs64 NetLicensing. Prior to 0.1.8, netlicensing_get_product passes the caller-controlled product_number to src/netlicensing_mcp/tools/products.py, which interpolates it into a REST path consumed by nl_get() in src/netlicensing_mcp/client.py without path-segment validation. A traversal segment can be normalized from the intended product path to the /token endpoint, after which the response is serialized through _wrap_json instead of _wrap_json_token_read, bypassing redact_token_read() protections for APIKEY number and SHOP shopURL fields. An authenticated MCP client with a non-administrative API key can retrieve plaintext token values, and a recovered administrative token can provide broad read, write, and delete access to the NetLicensing account. This issue is fixed in version 0.1.8.
- Record
EUVD-2026-102319- CVSS 3.1
- 9.6 Critical
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-hxpf-9xvq-wph8
9.6
netlicensing-mcp: REST Path Traversal Bypasses Token Redaction
Summary
The netlicensing_get_product MCP tool in netlicensing-mcp interpolates a caller-controlled product_number argument directly into a REST URL path without any validation. Passing ../token as the product number causes httpx to normalize /product/../token into /token, silently redirecting the request to the NetLicensing token endpoint instead of the intended product endpoint. The response is then serialized through the generic _wrap_json wrapper rather than the token-specific _wrap_json_token_read wrapper, bypassing all APIKEY number and SHOP shopURL redaction. An authenticated MCP client can recover plaintext API key values that the token read tools intentionally mask, including admin-level APIKEY credentials.
Details
The vulnerability is a path traversal (CWE-22) that exploits the interaction between unsanitized string interpolation and httpx's WHATWG URL normalization.
Source — src/netlicensing_mcp/tools/products.py:22
async def get_product(product_number: str) -> dict:
"""Get a single product by its number."""
return strip_output_fields(await nl_get(f"/product/{product_number}"))
product_number is inserted directly into the REST path with no validation. A value of ../token produces the path /product/../token.
Sink — src/netlicensing_mcp/client.py:143
async def nl_get(path: str, params: dict[str, str] | None = None) -> dict[str, Any]:
client = _get_client()
url = f"{BASE_URL}{path}"
...
r = await client.get(url, headers=_headers(), params=params or {})
httpx constructs the full URL as {BASE_URL}/product/../token and, per WHATWG URL normalization rules applied to absolute URLs, resolves it to {BASE_URL}/token. The HTTP request is therefore sent to the NetLicensing /core/v2/rest/token endpoint.
Redaction bypass — src/netlicensing_mcp/server.py:336 and src/netlicensing_mcp/redaction.py:180-239
The tool handler wraps the response via _wrap_json(entity, "Product"), which calls only the generic _json() redaction. The token-specific path _wrap_json_token_read() → redact_token_read() is never invoked. The function redact_token_read() at redaction.py:180-239 is the only code that masks APIKEY number and SHOP shopURL fields; because it is not on this code path, the raw API key value is returned verbatim in the MCP tool output.
Complete data flow:
server.py:312-321— MCP dispatcher receives attacker-controlledproduct_numberand callsproducts.get_product(product_number).tools/products.py:22— value interpolated intof"/product/{product_number}"without validation.client.py:143—url = f"{BASE_URL}{path}";httpxnormalizes../and sends request to/tokenendpoint.server.py:336— response wrapped as"Product"via_wrap_json, not_wrap_json_token_read.server.py:160-165— generic_json()redaction applies only default-field masking.redaction.py:180-239—redact_token_read()with APIKEY/SHOP-specific masking is never reached.
PoC
Prerequisites
- Python 3.10+
netlicensing-mcp0.1.5 (or local commitc8a3fec) installed or available viaPYTHONPATHhttpx,python-dotenv,mcp[cli]installed
Option A — Docker (recommended, reproduces Phase 2 result)
# Build from the repository root (requires repo/ and vuln-001/ directories)
docker build -t netlicensing-vuln-001 \
-f vuln-001/Dockerfile \
reports/pypiAi_1561_Labs64__NetLicensing-MCP/
# Run — exit code 0 confirms the vulnerability
docker run --rm netlicensing-vuln-001
Option B — Direct Python
cd /path/to/Labs64__NetLicensing-MCP
PYTHONPATH=src python3 - <<'PY'
import asyncio, json, threading
from http.server import BaseHTTPRequestHandler, HTTPServer
seen = []
secret = "actual-api-key-value-5678"
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
seen.append(self.path)
if…
- Record
GHSA-hxpf-9xvq-wph8- CVSS 3.1
- 9.6 Critical
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N - Weakness
- CWE-22
- Updated
- 2026-11-02
NVD
9.6
NetLicensing MCP Server is a natural-language interface that enables agentic applications to manage the software-licensing lifecycle in Labs64 NetLicensing. Prior to 0.1.8, netlicensing_get_product passes the caller-controlled product_number to src/netlicensing_mcp/tools/products.py, which interpolates it into a REST path consumed by nl_get() in src/netlicensing_mcp/client.py without path-segment validation. A traversal segment can be normalized from the intended product path to the /token endpoint, after which the response is serialized through _wrap_json instead of _wrap_json_token_read, bypassing redact_token_read() protections for APIKEY number and SHOP shopURL fields. An authenticated MCP client with a non-administrative API key can retrieve plaintext token values, and a recovered administrative token can provide broad read, write, and delete access to the NetLicensing account. This issue is fixed in version 0.1.8.
- Record
CVE-2026-57496- CVSS 3.1
- 9.6 Critical
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N - Weakness
- CWE-22
- Updated
- 2026-11-02
OSV
9.6
NetLicensing MCP Server: REST Path Traversal Bypasses Token Redaction
NetLicensing MCP Server is a natural-language interface that enables agentic applications to manage the software-licensing lifecycle in Labs64 NetLicensing. Prior to 0.1.8, netlicensing_get_product passes the caller-controlled product_number to src/netlicensing_mcp/tools/products.py, which interpolates it into a REST path consumed by nl_get() in src/netlicensing_mcp/client.py without path-segment validation. A traversal segment can be normalized from the intended product path to the /token endpoint, after which the response is serialized through _wrap_json instead of _wrap_json_token_read, bypassing redact_token_read() protections for APIKEY number and SHOP shopURL fields. An authenticated MCP client with a non-administrative API key can retrieve plaintext token values, and a recovered administrative token can provide broad read, write, and delete access to the NetLicensing account. This issue is fixed in version 0.1.8.
- Record
CVE-2026-57496- CVSS 3.1
- 9.6 Critical
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N - Weakness
- CWE-22
- Updated
- 2026-11-02
OSVGHSA-hxpf-9xvq-wph8
9.6
netlicensing-mcp: REST Path Traversal Bypasses Token Redaction
Summary
The netlicensing_get_product MCP tool in netlicensing-mcp interpolates a caller-controlled product_number argument directly into a REST URL path without any validation. Passing ../token as the product number causes httpx to normalize /product/../token into /token, silently redirecting the request to the NetLicensing token endpoint instead of the intended product endpoint. The response is then serialized through the generic _wrap_json wrapper rather than the token-specific _wrap_json_token_read wrapper, bypassing all APIKEY number and SHOP shopURL redaction. An authenticated MCP client can recover plaintext API key values that the token read tools intentionally mask, including admin-level APIKEY credentials.
Details
The vulnerability is a path traversal (CWE-22) that exploits the interaction between unsanitized string interpolation and httpx's WHATWG URL normalization.
Source — src/netlicensing_mcp/tools/products.py:22
async def get_product(product_number: str) -> dict:
"""Get a single product by its number."""
return strip_output_fields(await nl_get(f"/product/{product_number}"))
product_number is inserted directly into the REST path with no validation. A value of ../token produces the path /product/../token.
Sink — src/netlicensing_mcp/client.py:143
async def nl_get(path: str, params: dict[str, str] | None = None) -> dict[str, Any]:
client = _get_client()
url = f"{BASE_URL}{path}"
...
r = await client.get(url, headers=_headers(), params=params or {})
httpx constructs the full URL as {BASE_URL}/product/../token and, per WHATWG URL normalization rules applied to absolute URLs, resolves it to {BASE_URL}/token. The HTTP request is therefore sent to the NetLicensing /core/v2/rest/token endpoint.
Redaction bypass — src/netlicensing_mcp/server.py:336 and src/netlicensing_mcp/redaction.py:180-239
The tool handler wraps the response via _wrap_json(entity, "Product"), which calls only the generic _json() redaction. The token-specific path _wrap_json_token_read() → redact_token_read() is never invoked. The function redact_token_read() at redaction.py:180-239 is the only code that masks APIKEY number and SHOP shopURL fields; because it is not on this code path, the raw API key value is returned verbatim in the MCP tool output.
Complete data flow:
server.py:312-321— MCP dispatcher receives attacker-controlledproduct_numberand callsproducts.get_product(product_number).tools/products.py:22— value interpolated intof"/product/{product_number}"without validation.client.py:143—url = f"{BASE_URL}{path}";httpxnormalizes../and sends request to/tokenendpoint.server.py:336— response wrapped as"Product"via_wrap_json, not_wrap_json_token_read.server.py:160-165— generic_json()redaction applies only default-field masking.redaction.py:180-239—redact_token_read()with APIKEY/SHOP-specific masking is never reached.
PoC
Prerequisites
- Python 3.10+
netlicensing-mcp0.1.5 (or local commitc8a3fec) installed or available viaPYTHONPATHhttpx,python-dotenv,mcp[cli]installed
Option A — Docker (recommended, reproduces Phase 2 result)
# Build from the repository root (requires repo/ and vuln-001/ directories)
docker build -t netlicensing-vuln-001 \
-f vuln-001/Dockerfile \
reports/pypiAi_1561_Labs64__NetLicensing-MCP/
# Run — exit code 0 confirms the vulnerability
docker run --rm netlicensing-vuln-001
Option B — Direct Python
cd /path/to/Labs64__NetLicensing-MCP
PYTHONPATH=src python3 - <<'PY'
import asyncio, json, threading
from http.server import BaseHTTPRequestHandler, HTTPServer
seen = []
secret = "actual-api-key-value-5678"
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
seen.append(self.path)
if…
- Record
GHSA-hxpf-9xvq-wph8- CVSS 3.1
- 9.6 Critical
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N - Weakness
- CWE-22
- Updated
- 2026-11-02
OSVPYSEC-2026-3489
9.6
netlicensing-mcp: REST Path Traversal Bypasses Token Redaction
REST Path Traversal Bypasses Token Redaction in netlicensing-mcp
Summary
The netlicensing_get_product MCP tool in netlicensing-mcp interpolates a caller-controlled product_number argument directly into a REST URL path without any validation. Passing ../token as the product number causes httpx to normalize /product/../token into /token, silently redirecting the request to the NetLicensing token endpoint instead of the intended product endpoint. The response is then serialized through the generic _wrap_json wrapper rather than the token-specific _wrap_json_token_read wrapper, bypassing all APIKEY number and SHOP shopURL redaction. An authenticated MCP client can recover plaintext API key values that the token read tools intentionally mask, including admin-level APIKEY credentials.
Details
The vulnerability is a path traversal (CWE-22) that exploits the interaction between unsanitized string interpolation and httpx's WHATWG URL normalization.
Source — src/netlicensing_mcp/tools/products.py:22
async def get_product(product_number: str) -> dict:
"""Get a single product by its number."""
return strip_output_fields(await nl_get(f"/product/{product_number}"))
product_number is inserted directly into the REST path with no validation. A value of ../token produces the path /product/../token.
Sink — src/netlicensing_mcp/client.py:143
async def nl_get(path: str, params: dict[str, str] | None = None) -> dict[str, Any]:
client = _get_client()
url = f"{BASE_URL}{path}"
...
r = await client.get(url, headers=_headers(), params=params or {})
httpx constructs the full URL as {BASE_URL}/product/../token and, per WHATWG URL normalization rules applied to absolute URLs, resolves it to {BASE_URL}/token. The HTTP request is therefore sent to the NetLicensing /core/v2/rest/token endpoint.
Redaction bypass — src/netlicensing_mcp/server.py:336 and src/netlicensing_mcp/redaction.py:180-239
The tool handler wraps the response via _wrap_json(entity, "Product"), which calls only the generic _json() redaction. The token-specific path _wrap_json_token_read() → redact_token_read() is never invoked. The function redact_token_read() at redaction.py:180-239 is the only code that masks APIKEY number and SHOP shopURL fields; because it is not on this code path, the raw API key value is returned verbatim in the MCP tool output.
Complete data flow:
server.py:312-321— MCP dispatcher receives attacker-controlledproduct_numberand callsproducts.get_product(product_number).tools/products.py:22— value interpolated intof"/product/{product_number}"without validation.client.py:143—url = f"{BASE_URL}{path}";httpxnormalizes../and sends request to/tokenendpoint.server.py:336— response wrapped as"Product"via_wrap_json, not_wrap_json_token_read.server.py:160-165— generic_json()redaction applies only default-field masking.redaction.py:180-239—redact_token_read()with APIKEY/SHOP-specific masking is never reached.
PoC
Prerequisites
- Python 3.10+
netlicensing-mcp0.1.5 (or local commitc8a3fec) installed or available viaPYTHONPATHhttpx,python-dotenv,mcp[cli]installed
Option A — Docker (recommended, reproduces Phase 2 result)
# Build from the repository root (requires repo/ and vuln-001/ directories)
docker build -t netlicensing-vuln-001 \
-f vuln-001/Dockerfile \
reports/pypiAi_1561_Labs64__NetLicensing-MCP/
# Run — exit code 0 confirms the vulnerability
docker run --rm netlicensing-vuln-001
Option B — Direct Python
cd /path/to/Labs64__NetLicensing-MCP
PYTHONPATH=src python3 - <<'PY'
import asyncio, json, threading
from http.server import BaseHTTPRequestHandler, HTTPServer
seen = []
secret = "actual-api-key-value-5678"
class…
- Record
PYSEC-2026-3489- CVSS 3.1
- 9.6 Critical
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N - Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
netlicensing-mcpPyPI |
before 0.1.8 | 0.1.8 |
netlicensing-mcpPyPI |
before 0.1.8, plus listed versions 0.0.60.1.00.1.10.1.20.1.3 Show 4 moreShow less0.1.40.1.50.1.60.1.7 |
0.1.8 |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-57496 is a critical vulnerability (CVSS 9.6) in Labs64 Netlicensing-mcp, published June 18, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.43%, the 37th percentile. Fixed in netlicensing-mcp 0.1.8.
References
github.com/Labs64/NetLicensing-MCP/security/advisories/GHSA-hxpf-9xvq-wph8
github.com/Labs64/NetLicensing-MCP/pull/6
github.com/Labs64/NetLicensing-MCP/commit/b8fd0ea76d533202573eb24add9fb2fbd9331496
github.com/Labs64/NetLicensing-MCP/releases/tag/0.1.8
nvd.nist.gov/vuln/detail/CVE-2026-57496
github.com/pypa/advisory-database/tree/main/vulns/netlicensing-mcp/PYSEC-2026-3489.yaml
Left out here: the rest of 3 source descriptions. The JSON record has them.