Skip to content

Unauthenticated schema disclosure + XPath injection in iTopSchemaTools (follow-up to #19) #20

Open

Description

@SyedAnas01

Following up on the TLS-verification report in #19 — found a second, separate issue while reviewing the MCP tool set, this time in the schema tools.

Summary: iTopSchemaTools (the iTop-list-all-classes and iTop-get-class-schema tools) is built only on DatamodelService, which just parses the local data/datamodel-production.xml file. Unlike every other tool in this server, it never goes through iTopClientInterface / Security::getUser(). Combined with config/packages/security.yaml having an empty access_control and a lazy/stateless main firewall, and McpController::handle() performing no authorization check of its own, these two tools fully execute for a POST /_mcp request that carries no Authorization header at all — meaning anyone who can reach the /_mcp endpoint gets the target instance's complete class list, custom fields, enum values, and workflow/life-cycle state machines, with zero credentials.

Where:

  • src/Tools/schema/iTopSchemaTools.php:10-91 — no Security/iTopClientInterface dependency anywhere in the class
  • config/packages/security.yaml — empty access_control
  • vendor/symfony/mcp-bundle/src/Controller/McpController.php:36-48 — no IsGranted/security check before the MCP server runs

This is a clean, complete bypass of the "every tool call needs the caller's iTop credentials" model for these 2 of 16 tools — every other tool (get/create/update/apply-stimulus/get-related/natural-language-search) does correctly require a Bearer token, so this looks like an oversight specific to the schema tools rather than an intentional design choice.

Second, related issue: DatamodelService::getClassSchemaFromXml() (src/Service/DatamodelService.php:86,98) builds its XPath lookup by directly concatenating the caller-supplied className argument (from get-class-schema) into the query string with no escaping. I confirmed locally (against the repo's own test fixture, no live instance touched) that a crafted className value containing a single quote breaks out of the intended class[@id='...'] predicate and changes which nodes match — going from matching exactly 1 class to matching all 139 classes in the test datamodel. That's a textbook XPath injection (CWE-643); I'm keeping the exact payload out of this public issue since it's a real working primitive, but happy to share it privately if useful — feel free to open a private security advisory (I noticed GHSA private reporting isn't enabled on this repo yet, might be worth turning on) or ping me and I'll send the PoC directly.

Suggested fix direction: route iTopSchemaTools through the same iTopClientInterface/Security check as the other 14 tools (or add an explicit access_control entry for /_mcp requiring authentication), and parameterize/escape $className before building the XPath query rather than string-concatenating it.

Happy to provide more detail or help verify a fix.

— Syed Anas Mohiuddin

Activity

  1. dflaven commented on Sep 22, 2026

    @dflaven
    Contributor

    This version is still a prototype. The authentication will be addressed in the final version.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions