pinchflat-mcp: stop leaking the API token, gate admin tools, allow retention #17

Merged
hermes-agent merged 1 commits from fix/pinchflat-mcp-secrets into main 2026-10-18 15:21:52 +02:00
Collaborator

Two problems, one root cause: the server treated every Pinchflat endpoint as fair game.

1. get_settings leaked the app's own API token. Pinchflat's settings record embeds api_token; the tool returned the whole row verbatim, so any tool caller received a credential that outlives the MCP session and grants full API access. Fixed by scrubbing at the transport boundary (_scrub), not per-tool: every response from _get/_post/_put/_delete now redacts api_token, api_key, token, secret, password, password_hash, youtube_api_key, and apprise_server, recursively (nested dicts and lists included).

2. Admin/config tools were exposed to every caller. get_settings and get_app_info describe the installation, not a subscription. They now live in an admin tier that is not registered unless PINCHFLAT_MCP_TOOLSET asks for it:

  • subscriptions (default): sources, media, profiles, tasks — no settings, no app info.
  • admin / all: the above plus get_settings and get_app_info.

Registration is conditional (@tool("admin") simply doesn't register), so the tools are absent from tools/list rather than present-and-refusing — nothing to discover or probe.

3. update_source could not set retention. The whitelist omitted retention_period_days, which forced a direct REST call with the leaked token to do routine retention work. Added retention_period_days, prevent_culling and download_media to update_source, and retention_period_days to create_source. An empty update now returns a message instead of issuing an empty PUT.

Also folded delete_media's hand-rolled request into _delete (same scrubbing, same timeout) and documented that delete_source does not delete files from disk.

Verified offline with stubbed fastmcp/httpx: default toolset exposes 18 tools with neither admin tool present; admin exposes both plus the subscription tools; nested api_token/youtube_api_key/password all come back [redacted]; update_source(retention_period_days=30) emits the expected PUT payload.

Two problems, one root cause: the server treated every Pinchflat endpoint as fair game. **1. `get_settings` leaked the app's own API token.** Pinchflat's settings record embeds `api_token`; the tool returned the whole row verbatim, so any tool caller received a credential that outlives the MCP session and grants full API access. Fixed by scrubbing at the transport boundary (`_scrub`), not per-tool: every response from `_get`/`_post`/`_put`/`_delete` now redacts `api_token`, `api_key`, `token`, `secret`, `password`, `password_hash`, `youtube_api_key`, and `apprise_server`, recursively (nested dicts and lists included). **2. Admin/config tools were exposed to every caller.** `get_settings` and `get_app_info` describe the installation, not a subscription. They now live in an `admin` tier that is not registered unless `PINCHFLAT_MCP_TOOLSET` asks for it: - `subscriptions` (default): sources, media, profiles, tasks — no settings, no app info. - `admin` / `all`: the above plus `get_settings` and `get_app_info`. Registration is conditional (`@tool("admin")` simply doesn't register), so the tools are absent from `tools/list` rather than present-and-refusing — nothing to discover or probe. **3. `update_source` could not set retention.** The whitelist omitted `retention_period_days`, which forced a direct REST call with the leaked token to do routine retention work. Added `retention_period_days`, `prevent_culling` and `download_media` to `update_source`, and `retention_period_days` to `create_source`. An empty update now returns a message instead of issuing an empty PUT. Also folded `delete_media`'s hand-rolled request into `_delete` (same scrubbing, same timeout) and documented that `delete_source` does not delete files from disk. Verified offline with stubbed `fastmcp`/`httpx`: default toolset exposes 18 tools with neither admin tool present; `admin` exposes both plus the subscription tools; nested `api_token`/`youtube_api_key`/`password` all come back `[redacted]`; `update_source(retention_period_days=30)` emits the expected PUT payload.
hermes-agent added 1 commit 2026-10-18 15:18:24 +02:00
pinchflat-mcp: redact credentials, gate admin tools, expose retention
NixOS Configuration CI / Nix Flake Check (pull_request) Successful in 15s
80d0352d1e
hermes-agent merged commit 4709b47c1e into main 2026-10-18 15:21:52 +02:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: luis/mcp-servers#17