In this article
コマンドインジェクションに脆弱なMCPサーバーを悪用する
MCPサーバーが急速に普及しています。MCPサーバーを使ってLLMの機能を拡張するワークフローは、ますます広く採用されています。しかし、その代償は何でしょうか?さまざまなセキュリティ上の脆弱性を抱えるエージェント型AIやLLMのワークフローにMCPサーバーを追加すると、何が起きるのでしょうか?
MCPサーバーは、Claude DesktopやRaycastなどの日常的なAIアプリケーションで利用できます。しかし、AI支援コーディングや自律型ソフトウェア開発のワークフローと組み合わせると、より大きな脅威となる可能性があります。
AIを活用した開発を安全に進めるためのベストプラクティス
AIを活用した開発のメリットを最大限に生かしながら、潜在的なリスクを効果的に軽減するための、開発者やセキュリティ担当者向けの10のヒントをご紹介します。
脆弱なMCPサーバーがソフトウェア開発者にとってリスクとなる理由
開発者は、AI支援コーディングやバイブコーディングのセッションを強化するためにMCPサーバーを利用します。たとえば、GitHubと連携してコードリポジトリのIssueに関する情報を取得できます。

一方、開発者のノートPCは、悪意ある攻撃者に狙われやすい資産です。特権レベルの高い環境やデータベース、クラウドインフラストラクチャのAPIキー、認証情報、知的財産、その他の機密情報が保存されていることが多いためです。
さらに、開発者は多忙で、作業中に頻繁に文脈を切り替える必要があることを考えてみてください。スピードが求められる環境では、十分に考えずに素早く行動したり、日々の多くの作業を無意識にこなしたりしがちです。
タスクを解決するために新しいオープンソースの依存関係を追加する場合、ターミナルを開いて
npm install <package>を実行します。新しいMCPサーバーを追加する場合は、CursorのMCP定義ファイル
.cursor/mcp.jsonを開き、新しいサーバーを定義します。
残念ながら、開発者はプロジェクトに追加するサードパーティー依存関係のソースコードを監査する際、必要な精査やレビューを怠りがちです。MCPサーバーのソースコードについても同じことが言えます。
脆弱なMCPサーバー
意図的に脆弱で安全でないコーディング手法を取り入れた、シンプルなMCPサーバーを構築しましょう。
このMCPサーバーは、CursorなどのMCPクライアントに、npmレジストリからパッケージ情報を検索する機能を提供します。
以下は、MCPサーバー経由で提供されるnpmパッケージ検索機能の主なソースコードです。
const server = new McpServer({
name: "npm JavaScript package management tools",
version: "1.0.0",
description: "Provides tools to get information about open source npm packages from the npmjs registry"
});
server.tool(
"getNpmPackageInfo",
"Get information about an npm package",
{
packageName: z.string()
},
async ({ packageName }) => {
const output = execSync(`npm view ${packageName}`, {
encoding: "utf-8",
});
return {
content: [
{
type: "text",
text: output
},
],
};
}
);Cursor用の新しいMCPサーバーを定義する
開発者がCursor、VS CodeなどのIDEに新しいMCPサーバーを追加すると、どうなるでしょうか?Node.jsランタイムで実行されるプロセスを使ったローカルMCPサーバーを追加してみましょう。
{
"mcpServers": {
"npm-package-info": {
"command": "node",
"args": ["/Users/lirantal/projects/repos/mcp-server-npm"]
}
}続いて、このようなMCPサーバーが安全でないコーディング手法に従っていると、コマンドインジェクション攻撃につながる可能性があることを見ていきましょう。
CursorのTabで、次のようなプロンプトを入力します。
What is the last release date of the nodemon npm packageCursorは利用可能なツールを調べ、getNpmPackageInfoというツールを呼び出せることを見つけます。このツールはパッケージ名の文字列を受け取ります。プロンプトからnodemonという文字列を抽出し、このパラメーターを指定してツールを呼び出します。
しかし、プロンプトにコマンドインジェクションを引き起こすシェル文字が含まれていて、npm info <package name>コマンドを迂回し、新たなコマンドが実行されたらどうなるでしょうか?
コマンドインジェクションとは何でしょうか?簡単に言うと、サーバーサイドのNode.jsプログラムにおけるコマンドインジェクションは、ユーザーが指定した入力を適切に無害化せずに、MCPサーバーが実行するシステムコマンドに直接組み込むことで発生します。これにより攻撃者は、意図されたコマンドを書き換え、サーバー上で任意のOSコマンドを実行できます。
次の概念実証では、Cursorにreact; touch /tmp/hi:というライブラリの情報を検索するよう求めています。

これは、次のようにNode.jsの子プロセスAPIに依存するMCPサーバーの脆弱なコードが原因です。
const output = execSync(`npm view ${packageName}`, {
encoding: "utf-8",
});攻撃者は、チャットでのやり取りを通じてさまざまな方法でプロンプトを作成できます(たとえば、悪意あるCursorルールやその他の手法)。これにより、コマンドインジェクションが引き起こされる可能性があります。
MCPサーバーのコマンドインジェクション脆弱性を悪用する
まとめると、次の動画では、攻撃者が脆弱なMCPサーバーを悪用してコマンドインジェクション攻撃を実行する方法を紹介しています。

PythonやGolangでMCPサーバーを構築している場合は、こうしたコマンドインジェクション脆弱性の軽減方法について、ぜひ以下をお読みください。