hardened-terminal-mcp

hardened-terminal-mcp

Security-hardened MCP server that runs only allowlisted commands with no shell, jailed to a single directory, and bounded execution.

Category
访问服务器

README

hardened-terminal-mcp

A security-hardened terminal MCP server. It exposes a small, policy-gated shell surface to an MCP client over stdio — allowlisted commands only, no shell, jailed to a single directory.

Guarantees

  • Deny by default. A command whose name is not on the allowlist is refused. Deny wins: a name on both lists is denied.
  • No shell. Commands run via subprocess with shell=False on a parsed argv. Shell metacharacters (; | & < > \ $(...)`) are rejected before any policy check — no chaining, redirection, or substitution.
  • Jailed cwd. Execution is confined to a configured jail root; traversal (..), symlink, and absolute-path escapes are refused.
  • Scrubbed environment. The child gets a minimal env (PATH, HOME, LANG) so parent-process secrets can't leak into it.
  • Bounded. Wall-clock timeout with process kill; stdout/stderr are capped.
  • Errors are data. No Python traceback ever reaches the client; every result is a CommandResult envelope with a typed ResultCode.
  • Audited. Every invocation of both tools is appended to a JSONL trail (byte counts only, never output content). Under fail-closed, a command that can't be logged is not run. The audit log must live outside the jail root or startup is refused.
  • Redacted. Secrets (API keys, tokens, private keys, JWTs, auth headers, KEY=value/--password X values) are stripped from tool output and from audit command_raw/argv. Output is redacted before truncation, so a secret can never be split across the cap and left half-visible.

How it works

policy.py decides (explain), executor.py runs (run), server.py wires both behind two FastMCP tools and maps every outcome onto one envelope.

Install

uv sync

Run

uv run hardened-terminal-mcp        # serves over stdio

Configuration (env vars, both optional):

  • HTMCP_POLICY_FILE — path to policy.toml (default: policy.toml).
  • HTMCP_JAIL_ROOT — directory commands are jailed to (default: process cwd).
  • HTMCP_AUDIT_LOG — path to the JSONL audit trail (default: audit.jsonl).
  • HTMCP_AUDIT_FAIL_MODE — closed (default) or open (see Audit trail).

Startup fails loudly if the policy is missing/invalid or the jail root is not a directory. Edit policy.toml to change the allow/deny lists and argument rules.

Tool reference

Both tools return a CommandResult: { ok, code, stdout, stderr, exit_code, duration_ms, policy_reason }.

  • run_command(command, cwd=None) — evaluate against policy and, if allowed, run it sandboxed. cwd (if given) must resolve inside the jail root.
  • explain_command(command) — dry run: return the verdict only, with empty output and exit_code=None. Never executes.

ResultCode values:

Code Meaning
OK Executed and returned (exit_code carries the result).
POLICY_DENIED Denied by policy (list, arg rule, metacharacter, empty).
PARSE_ERROR Command could not be parsed into an argv.
TIMEOUT Wall-clock timeout; process killed.
OUTPUT_TRUNCATED Ran, but output hit the cap.
CWD_ESCAPE cwd escaped the jail root.
EXECUTOR_ERROR Allowed command couldn't run (not found, permission, etc.).
AUDIT_UNAVAILABLE Fail-closed: the audit record couldn't be written; not run.
INTERNAL_ERROR Unexpected server error; generic message only.

Audit trail

Every call to either tool is appended to audit_log (one JSON object per line). Records carry byte counts (stdout_bytes, stderr_bytes) but never the output content — secret redaction is a separate concern.

An executed command writes two records sharing one event_id: an attempt record before execution and an outcome record after — told apart by the explicit record_type field ("attempt" | "outcome"), not by inference. The attempt record is written first so a crash mid-execution can never leave a silently-unlogged command. Denials, parse errors, cwd escapes, and dry runs write a single "outcome" record.

command_raw and argv are redacted (see Redaction); output content is still never recorded — only byte counts.

audit_fail_mode controls what happens when a record can't be written:

  • closed (default) — refuse to execute; return AUDIT_UNAVAILABLE.
  • open — execute anyway and emit a warning to stderr.

Redaction

[redaction] in policy.toml scrubs secrets from tool output and audit records:

[redaction]
enabled = true
entropy_fallback = false
extra_patterns = []   # e.g. [{ name = "internal_id", regex = "INT-[0-9]{8}" }]

Built-in patterns cover OpenAI/GitHub/Slack/LangSmith keys, AWS access and secret keys, private-key blocks, JWTs, Authorization: headers, KEY=value assignments, and --password/--token/-p flag values. Each secret becomes [REDACTED:<pattern_name>]; for keyed secrets only the value is replaced, so an operator still sees that a secret appeared and which kind. Operator extra_patterns are validated at startup — an invalid regex fails loudly rather than being silently skipped.

entropy_fallback (off by default) additionally redacts unrecognised high-entropy tokens. It is noisy: it trips on hashes, UUIDs, and base64 data, so enable it only when false positives are acceptable.

Tests

uv run pytest

License

MIT

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选