You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A generated transport token was written to logs/server.log in cleartext (CWE-532).
Starting --transport sse or --transport streamable-http without pinning $DAVINCI_MCP_TOKEN logged the fresh token verbatim. The transport logger
has no handler of its own, so the record propagated to the root logger,
which src/server.py points at logs/server.log — opened with the default
file mode (0644 under the usual umask), appended to forever, and never
cleared. That copy was strictly less protected and strictly more durable
than the one the code deliberately locks down: the 0600 state file under
the per-user private directory, deleted in run_networked's finally. The
token is the transport's only access control, and the control panel's
sibling token was already kept out of argv and logs against exactly this
local-user threat. The log line now names the state file's path instead of
the value, and a generated token is echoed only to an interactive stderr
(a redirected stderr is another file). The state file remains the
hand-back channel the control panel already reads. Reported privately by an
external security researcher, with a reproduction against the real run_networked and the server's real root-logger configuration.
Documentation
SECURITY.md now states the rule outright: the pidfile and the transport
state file are the only on-disk copies of either token, and neither is
written to logs/server.log. The mcp_transport module docstring no longer
says the token is "logged at startup".
Validation
A regression test runs the real run_networked (uvicorn stubbed) with a
root FileHandler configured the way src/server.py configures it, and
asserts the token is absent from the file, the state-file path is present,
a redirected stderr never carries it, an interactive stderr carries it
exactly once, and a pinned token is echoed nowhere. Against the previous
code the test fails with the token found in the log — the reporter's
finding, reproduced.