The chat client hides delete_project, the model refuses to select it, and the UI requires confirmation for destructive actions. A direct HTTP client sends a valid JSON-RPC tools/call request to the MCP endpoint. The server has no caller authentication of its own and executes the tool with its configured backend credential. Three controls existed, but all three lived on a path the request bypassed.
An MCP server exposed over a network is an API and capability gateway. Chat, model, and confirmation UI are clients or decision aids; they do not own the protected effect. Any reachable caller can attempt the protocol directly, so identity, tenant, tool permission, resource authorization, and approval state must be enforced at the server and again where the downstream change occurs.
Deployment model still matters. A single-user local server over standard input/output has a different boundary from a shared remote HTTP service. The engineering requirement follows reachability and authority: once multiple principals can reach privileged tools, protocol possession cannot stand in for authentication or authorization.
Key Takeaways
- A model refusal, hidden button, client-side allowlist, or chat approval does not protect a tool endpoint that can be invoked directly.
- Every network-reachable MCP request needs a deployment-appropriate trust decision; session handles, connection state, IP address, and knowledge of the endpoint are not identities.
- Authentication answers who called. Authorization must still bind the caller to the tool, tenant, target resource, arguments, downstream credential, and permitted effect.
- HTTP deployments should validate tokens for the intended MCP resource, reject passthrough or wrong-audience tokens, and apply authorization to every request when protected access is configured.
- Localhost reduces exposure but does not make an unauthenticated HTTP server harmless; same-host processes, containers, proxies, and DNS rebinding can change reachability.
- Autonomous pentesting should compare chat-mediated and direct protocol paths with synthetic tools, controlled credentials, and protected-state evidence.
Follow the Effect, Not the Interface
Consider an assistant that offers tools for querying logs, creating documents, changing cloud resources, sending messages, or deploying code. The expected path may be:
user -> chat client -> model decision -> approval UI -> MCP request
-> MCP server -> downstream API -> protected effect
Security reviewers often inspect prompt injection, model tool selection, and approval screens. An attacker instead starts here:
attacker -> direct HTTP JSON-RPC request -> MCP server
-> downstream API -> protected effect
If the second path lacks equivalent controls, everything to its left in the first diagram is advisory. The system has put policy in a client while authority lives on a server.
The Server Usually Holds More Authority Than the Caller
MCP servers frequently store platform tokens, cloud credentials, database access, or service-account identity. A direct caller may not know those secrets. They do not need to if the server acts as an unauthenticated proxy. The tool handler receives a request and performs the operation using its own credentials.
This is a confused authority pattern: reachability to the gateway becomes use of the gateway's identity. The fix is not to return the server token to each client. It is to authenticate clients, authorize requested operations, use least-privileged downstream credentials, and preserve end-user or workload context where the downstream service needs it.
Protocol Optionality Does Not Remove the Threat Model
MCP supports local and remote transports. A local standard-input/output process is commonly launched by one client and inherits credentials from its environment. HTTP introduces a different boundary because multiple processes, hosts, users, or tenants may reach the endpoint.
Current authorization guidance provides a framework for protected HTTP transports. When used, it requires resource-oriented token handling, appropriate discovery, bearer tokens in authorization headers, validation on every request, and binding tokens to their intended MCP resource. It also forbids treating tokens meant for another service as if they were valid for this one.
The important nuance is:
- Protocol authorization is optional because some deployments do not need a network authorization flow.
- A protected remote deployment must enforce its chosen authentication and authorization model because privileged tools cannot safely accept arbitrary callers.
- A local unauthenticated design must remain genuinely local and single-user, with exposure and limitations documented.
Teams should not cite protocol optionality as a reason to expose an unauthenticated HTTP port. They should select a transport and control model that matches actual reachability and authority.
Session IDs, Connections, and Hostnames Are Not Authentication
Several values can look like identity without proving it.
Session Handle
A session ID correlates protocol state. Unless the server derives and verifies an authenticated principal on every request and binds the session to that principal, possession of the ID may allow impersonation or state injection. A session should never be the sole authentication credential by accident.
Source IP
IP allowlists can reduce exposure but are brittle as user identity. Proxies, containers, NAT, service meshes, VPNs, and same-host workloads can share or rewrite addresses. Network policy is defense-in-depth, not object-level authorization.
Localhost
Binding to loopback is safer than 0.0.0.0, but browser-based DNS rebinding, malicious local processes, exposed container ports, desktop extensions, and reverse proxies can make a supposedly local service reachable. Prefer standard input/output or restricted local IPC for truly single-client local servers. If HTTP is required, use host/origin protections and authorization appropriate to the environment.
Host and Origin Headers
Validating host and origin helps prevent DNS rebinding and cross-origin abuse. These headers do not establish the user's identity or permission to call a tool. They complement authentication.
Knowledge of the Port or URL
An unadvertised endpoint is not a secret. Port scanning, process inspection, logs, browser errors, container manifests, and default documentation reveal it. Security through obscurity does not create principal identity.
Authentication Is Only the First Decision
A token can be cryptographically valid and still be wrong for the request. The server needs a layered decision:
authenticated principal
+ intended MCP audience
+ client/workload identity
+ tenant and organization context
+ permitted tool
+ permitted target resources
+ semantic argument policy
+ approval and risk requirements
+ current account/tool state
= authorized dispatch
Validate the Token for This Resource
Check issuer, signature, expiry, audience/resource, client binding where applicable, and relevant scopes or claims. Do not accept a token merely because the same identity provider issued it. A token for an unrelated API must not become a universal credential for the MCP server.
Map Scopes to Capabilities Carefully
A broad scope such as tools:call may be too coarse. Tools differ dramatically. Reading a synthetic status metric is not equivalent to creating a notebook, deleting an environment, or sending customer data. Map scopes, roles, and policy to concrete tool capabilities and constrain target resources inside handlers.
Reauthorize Objects Near the Effect
The MCP server can determine that principal P may call read_document. The document service must still verify that P may read document D in tenant T. If the server always uses one administrator credential and drops principal context, its internal object IDs can become cross-tenant capabilities.
Treat Arguments as Security-Relevant
Schema validation confirms shape and types. Semantic authorization checks whether the requested path, query, account, environment, recipient, or resource is permitted. A string can be valid JSON and still select another tenant's object.
Bind Approval to the Exact Call
For sensitive operations, approval should cover the authenticated principal, tool, canonical arguments, resolved target, tenant, purpose, expiry, and run. A client-side confirmation cannot protect a direct API path unless the server verifies an approval artifact or implements server-side workflow state.
A Tool Endpoint Threat Model
| Layer | Unsafe assumption | Failure | Strong invariant |
|---|---|---|---|
| Network | Only our client knows the port | Arbitrary caller reaches HTTP endpoint | Exposure is explicit and restricted |
| Transport | Protocol session identifies user | Session theft or direct calls impersonate | Every protected request has authenticated principal |
| Token | Any valid token is acceptable | Wrong-audience or passthrough token accepted | Token is issued for this MCP resource |
| Server | Authentication permits all tools | Low-privileged user invokes sensitive tool | Tool-level capability policy applies |
| Arguments | Schema-valid means authorized | Caller targets foreign tenant/resource | Semantic and object-level checks apply |
| Approval | Chat UI confirms risky calls | Direct request bypasses UI | Server verifies exact-call approval where required |
| Downstream | Server credential may act globally | Caller inherits service-account authority | Least privilege and principal context constrain access |
| Session state | Existing run remains authorized | Role revoked but pending calls execute | Current authorization checked at dispatch |
| Local deployment | Loopback means unreachable | Local process or rebinding invokes tools | IPC/host/origin/token controls match risk |
| Audit | Backend logs identify caller | All actions appear as one service account | End-to-end actor, client, tenant, tool, target recorded |
The table also clarifies why adding one bearer-token check may not close the issue. Authentication without tool and resource authorization can turn an anonymous proxy into an authenticated overprivileged proxy.
A Secure Request Path
1. Choose the Right Transport
For a single local client, prefer standard input/output or restricted operating-system IPC. For remote or multi-client use, use HTTPS and an explicit authorization model. Do not expose a development HTTP mode to shared networks by default.
2. Establish the Principal on Every Request
Validate credentials and derive principal, client, tenant, and assurance from trusted claims. Do not accept these identities from request arguments or headers that are not integrity-protected by the authentication system.
3. Validate Audience and Scope
Ensure the token was issued for this MCP server and is active. Interpret scopes under a documented capability map. Return appropriate unauthenticated versus insufficient-permission errors without leaking sensitive tool data.
4. Bind Protocol State to the Principal
If sessions, resumable streams, or tasks are used, bind them to authenticated identity and tenant. Recheck on every inbound request. Prevent one principal from listing, resuming, or completing another principal's state.
5. Authorize Tool Discovery and Invocation
Do not assume every authenticated user should see every tool. Filter discovery according to capability, but also enforce at invocation because clients can call names directly. Tool visibility is user experience; invocation policy is security.
6. Validate Semantic Arguments
Resolve object ownership, tenant, environment, path, destination, and action. Apply allowlists and business invariants. Treat tool annotations and client-provided metadata as hints, not authority.
7. Verify Approval and Guardrails
Require server-verifiable approval for actions that need it. Apply rate, cost, concurrency, network, filesystem, data-classification, and destructive-action policies before dispatch.
8. Use Scoped Downstream Authority
Prefer delegated or short-lived credentials tied to the principal and requested operation. If a service account is unavoidable, implement explicit downstream object authorization and narrowly scope its permissions.
9. Audit the Effect
Record principal, client, tenant, token audience, session, tool, canonical argument digest, target, approval, downstream identity, outcome, and effect reference. Redact tokens, secrets, sensitive query text, and customer data.
Direct Invocation Must Be a First-Class Test
Testing only through a supported chat client gives false confidence. Build equivalent requests at the protocol layer.
Discover Reachability Safely
Inventory bind addresses, ports, container exposure, service definitions, reverse proxies, ingress rules, local desktop bridges, and development flags. Test from expected client, same host, sibling container, adjacent network, and an explicitly unauthorized network location in a controlled environment.
Use Synthetic Tools and Credentials
Create tools that read and write only disposable tenant records, return canary data, or emit a marker to a controlled sink. Give the MCP server a narrowly scoped test credential. Do not point direct-invocation tests at production logs, cloud accounts, customer sessions, or destructive operations.
Compare Paths
For the same semantic operation, test:
- Chat client with authenticated user and approval.
- Direct HTTP call without credentials.
- Direct call with malformed or expired token.
- Direct call with a valid token for another audience.
- Authenticated caller without tool permission.
- Caller with tool permission targeting another tenant's object.
- Valid caller bypassing the client approval UI.
- Reused session ID under another principal.
- Same-host and DNS-rebinding-style controlled reachability.
Verify Protected State
The primary oracle is the synthetic downstream state. A 401, 403, or JSON-RPC error is useful only if no tool action, queued job, audit side effect, or downstream request occurred. For permitted calls, verify that exactly one attributable effect occurs under the expected scoped identity.
For teams using SecureHup, direct-path validation can answer whether an apparently protected agent capability is actually reachable without the chat, model, or approval path. Users gain verified impact instead of a configuration suspicion, a clear request-to-effect trace for developers, lower triage effort, and a repeatable regression that proves the server boundary remains enforced. The value is the outcome and evidence, not a description of internal product mechanics.
Direct Invocation Boundary Tests
| Caller/path | Credential and context | Tool/target | Expected result |
|---|---|---|---|
| Approved chat path | Valid principal, exact approval | Allowed synthetic write | One attributable effect |
| Direct HTTP | No credential | Any protected tool | Reject before tool execution |
| Direct HTTP | Malformed/expired token | Any protected tool | 401; no effect |
| Direct HTTP | Valid wrong-audience token | Any protected tool | 401; token not passed downstream |
| Direct HTTP | Valid principal, insufficient scope | Sensitive tool | 403; no effect |
| Direct HTTP | Tool hidden from discovery | Direct known name | Invocation still denied |
| Direct HTTP | Valid tool scope | Foreign tenant object | Object-level denial |
| Direct HTTP | Valid read capability | Write-like semantic arguments | Semantic policy denial |
| Direct HTTP | Approval-required tool, no approval | Allowed target | Server denies despite bypassed UI |
| Direct HTTP | Approval for changed arguments | Different target/value | Approval-binding mismatch |
| Session replay | Session from principal A, token for B | Any tool | Principal/session mismatch denied |
| Role revocation | Valid pending session, role removed | Sensitive tool | Current authorization denies |
| Localhost probe | Unauthorized same-host process | Protected tool | IPC/token/host policy denies |
| Concurrent duplicate | Same approved call twice | Non-idempotent tool | At most one protected effect |
| Rate exhaustion | Valid low-privileged caller | Repeated safe tool | Bounded by principal/tenant policy |
The matrix should include both HTTP and any alternative transports the deployment supports. Controls may legitimately differ, but authority must not increase merely by changing adapters.
Evidence of Principal Substitution
A strong finding records:
- Server version, transport mode, bind address, port, proxy, and deployment topology.
- The network position from which the endpoint was reachable.
- Whether any authentication header, session, origin, or host validation was required.
- The exact protocol method and synthetic tool category, with dangerous arguments redacted.
- Server and downstream credentials in reference form, never raw value.
- Principal, tenant, scope, audience, and approval state.
- Downstream request and protected-state change.
- Whether model, chat UI, or approval workflow ran.
- Audit attribution and correlation IDs.
- Preconditions such as explicit HTTP mode, broad bind address, container exposure, or same-host access.
- Fixed-build replay and valid authorized baseline.
Severity follows reachability and tool authority. An unauthenticated server bound only to a developer's isolated test namespace is different from one exposed on a shared network with credentials that can read sensitive telemetry or write resources. Localhost exposure can be lower risk without being zero. A direct call that lists harmless tool names is different from one producing a protected downstream effect.
Do not demonstrate impact by deleting resources, exposing customer data, or invoking a live privileged tool. A synthetic canary with equivalent authorization path is sufficient. If a real unauthenticated invocation occurred, isolate the service, review downstream audit logs, revoke server credentials and sessions as warranted, and investigate every reachable tool.
Restore the Caller-to-Tool Binding
- Upgrade the affected server or integration to a release that closes the known unauthenticated path.
- Disable remote HTTP mode until appropriate controls are configured.
- Bind local-only deployments to restricted IPC or loopback with rebinding defenses.
- Require and validate authentication for every protected HTTP request.
- Validate token audience/resource and prohibit token passthrough.
- Add tool, tenant, object, and semantic argument authorization.
- Make approvals server-verifiable and exact-call bound.
- Replace broad backend credentials with scoped identities where possible.
- Add rate, budget, concurrency, and destructive-action guardrails.
- Review exposure logs and rotate credentials if unauthenticated access was possible.
- Preserve direct-invocation cases as automated regressions.
Putting the endpoint behind a reverse proxy helps only if all alternate ports and internal routes are closed and the server trusts proxy identity safely. Defense should not depend on one deployment diagram remaining perfect.
Release Controls for Direct Invocation
An MCP server can become remotely reachable through one flag, container port, ingress template, desktop bridge, or proxy change. Auth code can regress through protocol upgrades or new transport adapters.
Maintain:
- Startup tests for safe bind defaults and explicit remote opt-in.
- Transport conformance tests for authenticated and intentionally local-only modes.
- Token issuer, signature, expiry, audience/resource, and scope tests.
- Session/task/run principal-binding tests.
- Tool discovery and invocation authorization parity tests.
- Object-level and multi-tenant argument tests for every sensitive tool.
- Approval-binding and direct-call bypass tests.
- Host, origin, proxy, loopback, and DNS-rebinding defenses in controlled environments.
- Scoped downstream credential and token-passthrough tests.
- Rate, budget, duplicate, and audit-redaction tests.
- End-to-end synthetic effects from every reachable network zone.
Useful metrics include unauthenticated requests, wrong-audience tokens rejected, direct calls denied, tools lacking explicit policy, sessions without principal binding, cross-tenant target denials, approval mismatches, servers bound beyond approved interfaces, broad downstream credentials, uncorrelated effects, and time to revoke a server identity. "Only used by the chat" is not an observable control.
Direct Tool Call Review Questions
Before deploying an MCP server, verify:
- Transport choice matches single-user, local, remote, or multi-tenant reality.
- Remote HTTP exposure is explicit and protected by HTTPS.
- Every protected inbound request establishes a current authenticated principal.
- Tokens are validated for this exact MCP audience/resource.
- Session IDs and task handles are never used as standalone authentication.
- Tool discovery and direct invocation enforce the same capability policy.
- Each tool validates tenant, object, action, and semantic arguments near the effect.
- Approval-required actions carry server-verifiable exact-call approval.
- Current role and account state are rechecked at dispatch.
- Downstream authority is least-privileged and does not blindly proxy global service credentials.
- Local HTTP modes have host/origin/rebinding defenses or use restricted IPC instead.
- Rate, concurrency, cost, data, filesystem, network, and destructive limits apply.
- Audit records preserve actor, client, tenant, tool, target, and effect without secrets.
- Direct protocol tests run independently of the chat client.
- Synthetic protected-state assertions prove denied calls caused no effect.
Frequently Asked Questions
Is authentication mandatory for every MCP server?
No. The protocol supports local single-user transports where a network authorization flow may not apply. But a network-reachable server exposing protected tools must implement a trust model appropriate to its callers and authority. Protocol optionality is not permission to expose privileged unauthenticated HTTP services.
Does binding an MCP server to localhost make it safe without authentication?
It reduces remote exposure but does not eliminate same-host, container, proxy, extension, or DNS-rebinding risks. For truly local single-client use, standard input/output or restricted IPC is often safer. If HTTP is necessary, add host/origin protection and authentication based on the environment.
Why is a session ID not enough to identify the caller?
A session ID normally correlates state and may be stolen, guessed, replayed, or moved between clients. The server should derive identity from validated credentials on each protected request and bind session state to that identity.
Can client-side approval secure a direct tool call?
Only if the server receives and verifies an approval artifact bound to the exact caller, tool, arguments, target, tenant, purpose, and expiry. A dialog enforced only by one client is bypassed when another client sends the protocol request directly.
How can teams test direct invocation safely?
Use a non-production MCP server, synthetic tools, scoped test credentials, disposable tenant data, controlled network positions, and protected-state assertions. Avoid real customer data, broad cloud credentials, destructive tools, and public exposure during the test.
The Server Still Has to Defend Itself
Testing an MCP server without its usual chat client tends to clarify the architecture quickly. The exercise exposes which protections belong to the UI and which remain when a caller reaches the protocol directly. Transports, proxies, middleware, tool registration, and downstream credentials all shape that result, so a single successful authentication test tells only part of the story.
We would keep a compact direct-call suite covering missing or unsuitable credentials, cross-tenant targets, stale state, and absent approval, with the protected resource observed after each attempt. The server can legitimately accept protocol messages while refusing to lend its backend authority to an unauthorized caller. That distinction is the boundary the test is meant to make visible.
#MCP #AISecurity #APISecurity #ToolSecurity #Authentication #Authorization #AutonomousPentesting
Find issues like this in your own codebase
SecureHup runs this exact exploit chain — discovery, enumeration and cross-tenant validation — on every deployment, automatically.