Authentication and security¶
gvm-mcp invents no authentication of its own. It forwards a caller’s gvmd
identity to the rust-gvm-api gateway, and gvmd is the sole authority for
authorization and auditing. What the server keeps is a short-lived gateway
session per identity, described below; it never stores passwords beyond the
configured fallback.
Identity resolution¶
The Authorization value for each gateway request is resolved per call:
The inbound MCP request’s
Authorizationheader, when present. Every streamable-HTTP caller can therefore authenticate as themselves, withBasicgvmd credentials or a gateway session token. The header is forwarded verbatim.Otherwise a
Basicheader built fromGVM_USERNAME/GVM_PASSWORD(orGVM_PASSWORD_FILE). This fallback identity serves stdio clients and HTTP callers that send no credentials.
When neither is available the request goes out unauthenticated and the
gateway answers 401, which surfaces as a legible tool error.
Gateway sessions¶
In the default session mode a Basic identity (the fallback or a forwarded
Basic header) is logged into the gateway once with POST /api/v1/session,
and its requests then carry the returned bearer token:
The pool is keyed by a SHA-256 digest of the
Authorizationvalue, so a forwarded password is never retained; a token is only ever used for the identity whose credential created it.Tokens are kept as secrets in memory, never logged, and closed at the gateway after 60 seconds without use, when the server shuts down (also on
SIGTERM), or when an identity is evicted from the bounded pool (64 identities, least recently used first). A conversation therefore costs one login per burst of activity, and an idle server holds no session.A session whose gvmd connection the gateway lost (gvmd restarted, or the connected gvmd dropped the connection on a command it does not support) is closed as soon as a call fails with it; reads are retried on a fresh session right away, writes report the error once and the next call logs in again.
A session is treated as expired shortly before the gateway’s idle timeout (5 minutes by default) and replaced after one hour at the latest. If the gateway rejects a token, the session is re-created once and the call retried; a second rejection is reported as the credential error it is.
If the gateway refuses to create a session (its session or rate limits, or an older gateway without the endpoint), calls fall back to request-scoped
Basicauthentication for a short while.
Forwarded bearer tokens are passed through unchanged. per-request mode
(GVM_GATEWAY_AUTH_MODE=per-request) sends the Basic header on every call
instead; the gateway then opens and closes a gvmd session around each one.
The fallback identity is optional. Omit GVM_USERNAME / GVM_PASSWORD to
require every HTTP caller to authenticate as themselves, or keep them for
stdio and set MCP_REQUIRE_CALLER_AUTH=true so that HTTP callers can never
borrow them.
Report export sessions¶
Asynchronous report exports are the one exception to “no session”. The
gateway binds an export job to the session that created it and cancels the
job when that session ends; request-scoped Basic sessions end with the
request.
openvas_export_report therefore opens one gateway session with the caller’s
own credentials, runs the job on it, serves openvas_get_job and
openvas_download_job_result through it, and deletes it as soon as the
artifact is downloaded, the job is cancelled or the job reaches a terminal
state. The session is usable only by the identity that created the job.
Callers that forward their own gateway bearer token are passed through
unchanged. Keep polling at least every few minutes: the gateway closes idle
sessions and cancels their jobs.
Transport to the gateway¶
The connection to the gateway normally crosses a network. Use https:// and,
for a private CA, GVM_GATEWAY_CA_CERT; the client requires TLS 1.2 or newer
and never follows redirects. A plain http:// gateway URL is refused unless
its host is loopback or GVM_ALLOW_INSECURE_GATEWAY=true acknowledges that the
network is isolated (for example a Docker network); the server then logs a
warning at start-up.
Hardening for HTTP deployments¶
--require-caller-auth(MCP_REQUIRE_CALLER_AUTH=true) refuses HTTP tool calls that carry noAuthorizationheader instead of serving them with the fallback identity. The server logs a warning at startup when fallback credentials are configured, the flag is off and the bind address is not loopback.--allowed-hosts(MCP_ALLOWED_HOSTS) is a DNS-rebinding guard, not authentication. For a public deployment, terminate TLS and authenticate at a reverse proxy in front of the server.The Docker image binds
0.0.0.0:8000and disables the Host check for container networks. When you passGVM_USERNAME/GVM_PASSWORDto it, also passMCP_REQUIRE_CALLER_AUTH=trueor keep the port on a private network.The gateway client never follows redirects, rejects credentials embedded in
GVM_GATEWAY_URL, never writes credentials to its logs and caps downloaded artifacts (report exports, agent support bundles) at 3 MB.
Secrets¶
Prefer GVM_PASSWORD_FILE (a mounted secret file) over GVM_PASSWORD in
production; it takes precedence when both are set. Passwords and forwarded
tokens never appear in logs or in MCP responses.
Vulnerabilities in this project are reported privately as described in SECURITY.md.