improve: c3_shell robustness, guard observability, MCP host check, TOML dedup (v2.34.0)#14
Merged
Merged
Conversation
…ML dedup (v2.34.0) From the tooling-exploration review. c3_shell: force UTF-8 in child env (fix cp1252 UnicodeEncodeError on Windows), self-sweep stray 0-byte ghost files created during a command (install-independent; only new files), and stop auto-filtering git status/diff/log output. Security: startup log + /api/health web_guard field confirm the localhost guard is active; the Oracle MCP transport (:3332) gains a Host-header allowlist middleware (anti DNS-rebinding) on top of the Bearer gate. Refactor: extract the drifted MCP-section TOML helpers from cli/server.py + cli/hub_server.py into a single shared core/mcp_toml.py (reconciled: quote-stripped keys, unlink emptied file). Tests: +23 (test_shell_robustness, test_mcp_host_guard, test_mcp_toml); full suite 381 passing. Bump 2.33.0 -> 2.34.0; CHANGELOG + discovery-api docs updated. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR strengthens c3_shell robustness and security guard observability, adds a Host-header allowlist to the Oracle MCP transport, and consolidates duplicated MCP TOML parsing/writing logic into a shared helper module.
Changes:
- Make
c3_shellmore Windows/Unicode-safe (force UTF-8 env + decode) and more robust (ghost-file self-sweep, don’t auto-filter key git diagnostics). - Add MCP transport Host-header allowlist middleware for DNS-rebinding defense-in-depth, and expose web-guard status via
/api/health+ startup log. - Deduplicate MCP TOML section helpers into
core/mcp_toml.pyand add round-trip tests.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_shell_robustness.py | Adds regression tests for UTF-8 env forcing, git diagnostic filtering guard, and ghost-file sweep behavior. |
| tests/test_mcp_toml.py | Adds round-trip tests for the new shared MCP TOML helpers. |
| tests/test_mcp_host_guard.py | Adds tests for the new MCP Host-header allowlist middleware. |
| pyproject.toml | Bumps project version to 2.34.0. |
| oracle/oracle_server.py | Threads allowed_hosts config through to the MCP server startup. |
| oracle/mcp_oracle.py | Adds pure-ASGI Host-header allowlist middleware and wires it into the MCP Starlette app. |
| oracle-guide/discovery-api.md | Updates security docs to note MCP transport Host allowlist in v2.34.0. |
| core/web_security.py | Adds guard_summary() and logs a startup line confirming the localhost guard is active. |
| core/mcp_toml.py | Introduces shared parse/upsert/remove helpers for [mcp_servers.*] TOML sections. |
| cli/tools/shell.py | Forces UTF-8 for child processes, adds git-diagnostic filtering guard, and implements ghost-file self-sweep. |
| cli/server.py | Uses shared core.mcp_toml helpers and returns web_guard info in /api/health. |
| cli/hub_server.py | Uses shared core.mcp_toml helpers (removes duplicated TOML logic). |
| cli/c3.py | Bumps CLI version to 2.34.0. |
| CHANGELOG.md | Documents v2.34.0 changes (shell robustness, guard observability, MCP host allowlist, TOML dedup). |
|
|
||
| def test_unicode_output_does_not_crash(self): | ||
| # A child printing non-cp1252 chars (→) must not crash on Windows. | ||
| r = shell_mod._run_sync('python -c "print(chr(0x2192))"', ".", 30) |
| def test_handle_shell_sweeps_created_ghost(self): | ||
| with tempfile.TemporaryDirectory() as tmp: | ||
| svc = _Svc(tmp) | ||
| cmd = "python -c \"import pathlib; pathlib.Path('Lghost9').touch()\"" |
Comment on lines
+39
to
+40
| key, value = line.split("=", 1) | ||
| key = key.strip().strip('"') |
Comment on lines
+60
to
+62
| def toml_escape_str(value: str) -> str: | ||
| """Escape a string for a double-quoted TOML value (Windows ``\\`` → ``/``).""" | ||
| return value.replace("\\", "/") |
Comment on lines
+140
to
151
| def build_app(registry, version: str = "", require_auth: bool = True, path: str = "/mcp", | ||
| host: str = "127.0.0.1", allowed_hosts=None): | ||
| """Build the Starlette ASGI app for the MCP server (auth middleware attached).""" | ||
| mcp = build_mcp(registry, version) | ||
| app = mcp.http_app(path=path) | ||
| if require_auth: | ||
| app.add_middleware(_BearerAuthMiddleware) | ||
| # Host-header allowlist (defense-in-depth vs DNS rebinding). Added last so it | ||
| # is the outermost middleware and runs before the bearer check. | ||
| from core.web_security import allowed_hostnames | ||
| app.add_middleware(_HostGuardMiddleware, allowed=allowed_hostnames(host, allowed_hosts)) | ||
| return app |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements the improvements surfaced while exploring the tool. No behavioural change to the public tool contracts beyond the fixes below.