Skip to content

fix(mcp-integrations): techdocs-mcp-extras actions use service credentials instead of the caller's, bypassing catalog permissions #4485

Description

@Elesiann

Summary

The three actions in workspaces/mcp-integrations/plugins/techdocs-mcp-extras (fetch-techdocs, retrieve-techdocs-content, analyze-techdocs-coverage) ignore the credentials provided by the actions registry (action: async ({ input }) =>) and call the catalog and the techdocs backend with auth.getOwnServiceCredentials() (src/service.ts, around lines 209, 289, 346, 463 and 532 on main).

Service principals are always allowed by the permission framework, so with permission.enabled: true any authenticated MCP user can list entities and read TechDocs content that catalog.entity.read would deny them in the UI. The techdocs backend itself gates /static/docs on the caller's catalog read permission (plugins/techdocs-backend/src/service/router.ts in backstage/backstage), so the MCP path bypasses a check the rest of the product enforces. Read-only, but it breaks the assumption that MCP tools inherit the caller's RBAC.

Tasks

  • Thread credentials from the action callback (action: async ({ input, credentials }) =>) in src/actions/*.ts into the TechDocsService methods
  • Use { credentials } for catalog calls and onBehalfOf: credentials when obtaining the techdocs plugin token in src/service.ts, replacing the auth.getOwnServiceCredentials() calls (around lines 209, 289, 346, 463, 532)
  • Remove this.logger.info(credentials) in src/service.ts (around line 290), which logs the credentials object at info level
  • Update src/service.test.ts / src/plugin.integration.test.ts to assert the caller's credentials are forwarded
  • Add a patch changeset for @red-hat-developer-hub/backstage-plugin-techdocs-mcp-extras

Acceptance Criteria

  • With permission.enabled: true, an MCP caller denied catalog.entity.read on an entity gets no entity metadata and no TechDocs content for it from any of the three actions
  • Catalog and techdocs backend requests made by the plugin carry the caller's identity (onBehalfOf: credentials), not the plugin's own service credentials
  • No credentials object is written to the log
  • Behaviour for callers that are allowed is unchanged

Context

The sibling plugins software-catalog-mcp-extras and scaffolder-mcp-extras in the same workspace already forward the caller's credentials, and the workspace's own .cursor/rules/port-mcp-tool.mdc requires "credentials from action callback".

Version: @red-hat-developer-hub/backstage-plugin-techdocs-mcp-extras 0.2.6 (main); the pattern dates back to the initial import of the plugin (#1491) and is unchanged since.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions