Skip to Content
Free during beta·npx -y @inkog-io/cli scan .·Get API Key →
TutorialsSecuring MCP Servers

Securing MCP Servers

Audit your MCP server for security vulnerabilities in 10 minutes.

Why MCP Servers Need Security Auditing

Model Context Protocol (MCP) servers give AI assistants access to tools and data. A vulnerable MCP server can allow:

  • Tool injection — Attacker-controlled tool descriptions that manipulate the AI
  • Excessive permissions — Tools with unrestricted filesystem or network access
  • Missing input validation — Tools that accept arbitrary input without checks
  • Credential exposure — API keys or secrets hardcoded in tool implementations

1. Scan

# Scan your MCP server project npx -y @inkog-io/cli scan ./my-mcp-server # Or scan a specific directory inkog scan ./src/tools

Example output:

tools/file-reader.ts:12:1: CRITICAL [code_injection] Tool executes user input without validation | 11 | const content = fs.readFileSync(args.path) 12 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | CWE-22 | OWASP LLM07 tools/search.ts:8:1: HIGH [missing_input_validation] Tool parameter has no validation constraints | 7 | inputSchema: { 8 | type: "object", | ^^^^^^^^^^^^^^^^ 9 | properties: { query: { type: "string" } } | OWASP LLM07 --------------------------------------------- 2 findings (1 critical, 1 high)

2. Fix

Fix 1: Validate tool inputs

Vulnerable
No path validation — directory traversal possible
server.tool("read_file", async ({ path }) => {
// Attacker can read any file: "../../etc/passwd"
const content = fs.readFileSync(path, "utf-8");
return { content: [{ type: "text", text: content }] };
});
Secure
Path restricted to allowed directory
import path from "path";

const ALLOWED_DIR = "/app/data";

server.tool("read_file", async ({ filePath }) => {
const resolved = path.resolve(ALLOWED_DIR, filePath);

// Prevent directory traversal
if (!resolved.startsWith(ALLOWED_DIR)) {
  throw new Error("Access denied: path outside allowed directory");
}

const content = fs.readFileSync(resolved, "utf-8");
return { content: [{ type: "text", text: content }] };
});

Fix 2: Add input schemas with constraints

Vulnerable
Unconstrained string input
server.tool("search", {
description: "Search documents",
inputSchema: {
  type: "object",
  properties: {
    query: { type: "string" }
  }
}
}, async ({ query }) => {
return db.search(query);
});
Secure
Input validated with max length and pattern
server.tool("search", {
description: "Search documents",
inputSchema: {
  type: "object",
  properties: {
    query: {
      type: "string",
      maxLength: 200,
      pattern: "^[a-zA-Z0-9 .,!?-]+$"
    }
  },
  required: ["query"]
}
}, async ({ query }) => {
return db.search(query);
});

Fix 3: Remove hardcoded credentials

Vulnerable
API key in source code
const client = new APIClient({
apiKey: "sk-proj-abc123...",
baseUrl: "https://api.example.com"
});
Secure
Credentials from environment variables
const client = new APIClient({
apiKey: process.env.API_KEY,
baseUrl: process.env.API_BASE_URL
});

if (!process.env.API_KEY) {
throw new Error("API_KEY environment variable required");
}

3. Verify

inkog scan ./my-mcp-server

Expected:

--------------------------------------------- 0 findings Security Gate: PASSED

4. Add to CI

# .github/workflows/security.yml name: MCP Security on: [push, pull_request] jobs: scan: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: inkog-io/inkog-action@v1 with: path: . fail-on: critical,high

Common Fixes

FindingFix
code_injectionValidate and restrict tool inputs
missing_input_validationAdd maxLength, pattern, enum constraints
hardcoded_credentialsUse environment variables
path_traversalResolve and validate paths against allowed directory
excessive_permissionsScope tools to minimum required access

Next

Scan your MCP server
$npx -y @inkog-io/cli scan .
Free during beta · 60s scan · Get API Key →
Last updated on