GHSA-83x6-42hr-jc76: Input Validation

Published Sep 2, 2026
·
Updated

Summary

The ckangetmqaquality and ckangetmqaqualitydetails tools restrict their serverurl argument to dati.gov.it via a regular expression. The regex is anchored only at the start and places no boundary after the host, so any URL whose host merely begins with dati.gov.it — or that uses dati.gov.it as URL userinfo before an @ — passes validation while actually targeting an attacker-controlled host.

Affected code

js // src/tools/quality.ts const ALLOWEDSERVERPATTERNS = [ /^https?:\/\/(www\.)?dati\.gov\.it/i // <-- no end anchor / host boundary ]; export function isValidMqaServer(serverUrl: string): boolean { return ALLOWEDSERVERPATTERNS.some(pattern => pattern.test(serverUrl)); }

All of the following return true:

| URL | Real host | |-----|-----------| | https://dati.gov.it.attacker.com/x | dati.gov.it.attacker.com (attacker) | | http://dati.gov.it.evil.example/api | dati.gov.it.evil.example (attacker) | | https://dati.gov.it@attacker.com/x | attacker.com (userinfo trick) |

After passing this check, serverurl flows into getMqaQuality/getMqaQualityDetails, which call makeCkanRequest(serverUrl, "packageshow", { id }). The server therefore issues a request to the attacker-controlled host and returns its (parsed) response to the caller.

Impact

- The intended "dati.gov.it only" trust boundary for the MQA tools is defeated; they can be driven against arbitrary external hosts. - The attacker host receives the request (including the datasetid) and controls the response body that is surfaced back to the model/user — enabling response spoofing and, in an agentic setting, indirect prompt-injection content delivered under the guise of a trusted-portal tool. - Contributes to SSRF surface: while makeCkanRequest blocks private/internal IPs, this bypass removes the domain restriction that the code intends to enforce for these tools.

The @-userinfo variant is the most severe form because validation passes on a string whose actual host is fully attacker-chosen.

Proof of concept

poc/mqa-allowlist-poc.mjs runs the verbatim regex over benign and malicious URLs:

accepted expectedlegit url true true https://dati.gov.it/opendata <- legit true false https://dati.gov.it.attacker.com/x <- BYPASS true false http://dati.gov.it.evil.example/api <- BYPASS true false https://dati.gov.it@attacker.com/x <- BYPASS

Remediation

Validate the parsed host, not the raw string. For example:

js function isValidMqaServer(serverUrl) { let u; try { u = new URL(serverUrl); } catch { return false; } if (u.protocol !== "https:") return false; const h = u.hostname.toLowerCase(); return h === "dati.gov.it" || h === "www.dati.gov.it"; // or: h === "dati.gov.it" || h.endsWith(".dati.gov.it") }

Anchoring the regex end-to-end (/^https:\/\/(www\.)?dati\.gov\.it(\/|$)/i) also closes the suffix trick, but URL-parsing + exact host comparison is the robust fix and also neutralizes the @-userinfo variant.

Affected Software

1 affected componentFixes available
npm/@aborruso/ckan-mcp-server<0.4.112
0.4.112

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade npm/@aborruso/ckan-mcp-server to a version that resolves this vulnerability.

    Fixed in 0.4.112
  2. Configuration

    Replace the current regex-only check (e.g., /^https?:\/\/(www\.)?dati\.gov\.it/i) with URL parsing and exact host comparison. Validate the parsed hostname (u.hostname.toLowerCase()) against an allowlist of only 'dati.gov.it' and 'www.dati.gov.it', so bypasses like 'https://dati.gov.it.evil.example/api', 'https://dati.gov.it.attacker.com/x', and 'https://dati.gov.it@attacker.com/x' are rejected.

    src/tools/quality.ts (isValidMqaServer / server_url validation for CKAN MQA tools: ckan_get_mqa_quality, ckan_get_mqa_quality_details) Allowed server URL/hostname validation = Parse URL and validate exact hostname (e.g., u.hostname == 'dati.gov.it' OR 'www.dati.gov.it'), not regex match on raw serverUrl

Event History

Sep 2, 2026
Advisory Published
via GitHub·02:52 PM
Data Sourced
via GitHub·02:52 PM
DescriptionSeverityWeaknessAffected Software

Frequently Asked Questions

1

What access does an attacker need to exploit this issue?

An attacker needs to be able to supply the server_url argument to either ckan_get_mqa_quality or ckan_get_mqa_quality_details. The supplied value can use a host beginning with dati.gov.it or use dati.gov.it as URL userinfo before an @ to pass validation while directing the request elsewhere.

2

Which requests can be redirected to an attacker-controlled server?

Requests made after validation by getMqaQuality or getMqaQualityDetails can be redirected, because they pass server_url to makeCkanRequest for the package_show operation. Examples include https://dati.gov.it.attacker.com/x and https://dati.gov.it@attacker.com/x.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203