MLflow autologging writes CrewAI API keys into trace data
A GitHub advisory published on 27 October 2026 says MLflow's CrewAI integration copies LLM provider API keys into trace spans in plaintext.
By The Agentic Times ·

MLflow's automatic logging feature for CrewAI agents records LLM provider API keys in plaintext inside trace telemetry, according to a GitHub security advisory published on 27 October 2026. The flaw is tracked as CVE-2026-116691 under the advisory identifier GHSA-j7qq-vr8c-xvw3 and affects the mlflow package on PyPI. Any application that calls mlflow.crewai.autolog() with a CrewAI LLM object configured with an API key can send that key to the MLflow trace backend or to whatever OpenTelemetry destination is configured.
Autologging is meant to capture what an agent does without developers writing logging code themselves. The advisory says that convenience is the problem. When MLflow instruments a CrewAI Agent, it walks the agent's internal dictionary of fields and converts each one to a string. One of those fields is llm, the CrewAI LLM object. In CrewAI 1.15.18, the advisory states, the underlying model holds api_key as an ordinary field, so the object's string representation contains the credential. MLflow then stores that string as a span attribute.
The advisory describes a second, separate leak path. A function that builds the recorded inputs for a span expands any argument that has a __dict__ attribute. Because the Agent object is passed as an argument during CrewAI execution, the credential-bearing LLM object ends up inside the mlflow.spanInputs field as well. The researcher who filed the advisory notes that fixing only the agent attribute serialisation would leave this second path open.
The disclosure appears to be unintentional rather than by design. The advisory points out that MLflow's dedicated LLM attribute extraction already explicitly excludes api_key, so the LLM span itself does not expose the credential. The broader serialisation of the agent's fields simply bypasses that existing protection.
The advisory includes two proof-of-concept demonstrations. The first calls the internal attribute-extraction function directly with a fake key and asserts that the key appears in the returned string. It requires no MLflow server, no running Crew and no network request. The second runs a full Crew through MLflow's own OTLP exporter and decodes the exported trace data with a local receiver. In the tested environment the fake key appeared in five attribute locations across two spans, including the llm, function_calling_llm and agent_executor attributes on the agent span, and the spanInputs attribute on both the agent span and a Task.execute_sync span.
The advisory notes that the provider request in the end-to-end test is expected to fail because the credential is fake, but says this does not change the outcome. The sensitive value is attached to the span when instrumentation starts, before the provider call succeeds or fails. All credentials used in the reproduction were locally generated fake values.
The behaviour was verified on MLflow 3.16.0 with CrewAI 1.15.18 and Python 3.12.3, using version 1.42.1 of the OTLP HTTP exporter. The advisory classifies the issue as sensitive information disclosure under CWE-532, insertion of sensitive information into a log file.
As a remedy, the advisory recommends that MLflow stop recursively serialising arbitrary object dictionaries. It suggests agent telemetry should use an explicit allowlist of non-sensitive scalar fields, and that credential-bearing objects such as llm, function_calling_llm, agent_executor and crew be reduced to safe metadata or left out entirely. It also says the inputs-construction path should either stop expanding arbitrary objects or pass values through the same sanitisation.
Sources
- github.comhttps://github.com/advisories/GHSA-j7qq-vr8c-xvw3
