Is @modelcontextprotocol/sdk safe?
- Node.js shell/command execution
- Node.js network egress
- Delegated authentication (OAuth 2.0 / OIDC)
@modelcontextprotocol/sdk is an AI npm_package analyzed by SkillTotal's deterministic static scanner. The scan found no malicious indicators, though 4 risky constructs are reported for review. It can: delegated authentication, mcp tools detected, network egress and shell execution — capabilities are what the code can do, not a verdict on intent. Risk score 0/100 (low).
@modelcontextprotocol/sdk 1.30.0
Automated static-analysis result. It can contain false positives and false negatives, and is not a claim about the intent of @modelcontextprotocol/sdk's authors. Report a false positive.
Behavioral traits
How this component maps to the CSA agentic threat model. Descriptive — it never affects the risk score.
Findings (4)
The component can run operating-system commands or spawn processes.
const match = regex.exec(authenticateHeader);
import { IOType } from 'node:child_process';const cross_spawn_1 = __importDefault(require("cross-spawn"));const match = regex.exec(authenticateHeader);
import { IOType } from 'node:child_process';import spawn from 'cross-spawn';
this._process = spawn(this._serverParams.command, this._serverParams.args ?? [], {Why it matters: Powerful and often legitimate — confirm the commands aren't built from untrusted input.
Fix: Confirm the command and its arguments are fully controlled and not derived from untrusted input; prefer execFile with an argument array.
The component makes outbound network requests.
import { IncomingMessage, ServerResponse } from 'node:http';import { IncomingMessage, ServerResponse } from 'node:http';* async fetch(request: Request): Promise<Response> {* async fetch(request: Request): Promise<Response> {import { IncomingMessage, ServerResponse } from 'node:http';import { IncomingMessage, ServerResponse } from 'node:http';* async fetch(request: Request): Promise<Response> {* async fetch(request: Request): Promise<Response> {Why it matters: Usually legitimate, but confirm the destinations are expected and no sensitive data leaves.
Fix: Confirm the destination hosts are expected and that no sensitive data is sent off-host.
An OAuth 2.0 / OpenID Connect delegated-authentication flow was detected (authorization-code / refresh-token / token-exchange grant, an OIDC authorize/discovery endpoint or id_token, or a delegation library). Tools authenticate with the end user's delegated, scoped credentials rather than a long-lived embedded service credential. (25 occurrence(s) shown as evidence).
// OIDC: https://example.com/.well-known/openid-configuration
url: new URL(`/.well-known/openid-configuration`, url.origin),
// RFC 8414 style: Insert /.well-known/openid-configuration before the path
url: new URL(`/.well-known/openid-configuration${pathname}`, url.origin),// OIDC Discovery 1.0 style: Append /.well-known/openid-configuration after the path
url: new URL(`${pathname}/.well-known/openid-configuration`, url.origin),authorizationUrl = new URL(metadata.authorization_endpoint);
grant_type: 'authorization_code',
grant_type: 'refresh_token',
grant_type: 'authorization_code',
grant_type: 'refresh_token',
const authorization_endpoint = '/authorize';
authorization_endpoint: new URL(authorization_endpoint, baseUrl || issuer).href,
router.use(new URL(oauthMetadata.authorization_endpoint).pathname, (0, authorize_js_1.authorizationHandler)({ provider: options.provider, ...options.authorizationOptions }));authorization_endpoint: z.ZodURL;
authorization_endpoint: z.ZodURL;
authorization_endpoint: z.ZodURL;
id_token: z.ZodOptional<z.ZodString>;
authorization_endpoint: exports.SafeUrlSchema,
authorization_endpoint: exports.SafeUrlSchema,
id_token: z.string().optional(), // Optional for OAuth 2.1, but necessary in OpenID Connect
// OIDC: https://example.com/.well-known/openid-configuration
url: new URL(`/.well-known/openid-configuration`, url.origin),
// RFC 8414 style: Insert /.well-known/openid-configuration before the path
Fix: Delegated auth is a lower-blast-radius execution context than an embedded static credential. Confirm the requested scopes are minimal and that tokens are never logged or forwarded off-host.
An MCP tool surface (manifest or tool definitions) was found.
* const server = new Server(
* const server = new Server(
Why it matters: Just context — review which tools it offers and their permissions.
Fix: Review the declared MCP tools and their permissions.
Check your own component
Run the same evidence-backed scan on any MCP server, agent skill, or package.
Scan your own componentHow we determine this: deterministic static analysis (regex + AST), evidence-anchored, no code execution. Methodology →