Snyk has a proof-of-concept or detailed explanation of how to exploit this vulnerability.
The probability is the direct output of the EPSS model, and conveys an overall sense of the threat of exploitation in the wild. The percentile measures the EPSS probability relative to all known EPSS scores. Note: This data is updated daily, relying on the latest available EPSS model version. Check out the EPSS documentation for more details.
In a few clicks we can analyze your entire application and see what components are vulnerable in your application, and suggest you quick fixes.
Test your applicationsUpgrade mlflow to version 3.17.0 or higher.
mlflow is a platform to streamline machine learning development, including tracking experiments, packaging code into reproducible runs, and sharing and deploying models.
Affected versions of this package are vulnerable to Insertion of Sensitive Information into Log File via mlflow.crewai.autolog in mlflow/crewai/autolog.py, where LLM credentials such as API keys are serialized into MLflow trace spans without sanitization. When a CrewAI LLM object is configured with an API key and autologging is enabled, the credential is recorded in plaintext across span attributes (including attributes.llm, attributes.function_calling_llm, attributes.agent_executor, and attributes.mlflow.spanInputs) and exported through the OTLP telemetry path, making it accessible to anyone with read access to the MLflow trace store or the OTLP receiver.
Note: This is only exploitable when mlflow.crewai.autolog() is enabled and a CrewAI LLM is configured with an API key.
Environment:
MLflow: 3.16.0
CrewAI: 1.15.18
Python: 3.12.3
opentelemetry-exporter-otlp-proto-http: 1.42.1
The following demonstrates the vulnerability without starting a Crew, making a network request, or requiring an MLflow server:
import importlib from crewai import LLM, Agentautolog = importlib.import_module("mlflow.crewai.autolog")
llm = LLM( model="gpt-4.1-mini", api_key="sk-proj-EXAMPLE1234567890", )
agent = Agent( role="r", goal="g", backstory="b", llm=llm, )
attrs = autolog._get_agent_attributes(agent)
assert "sk-proj-EXAMPLE1234567890" in attrs["llm"]
print(attrs["llm"])
The output contains the API key in plaintext, for example:
llm_type='openai' model='gpt-4.1-mini' ... api_key='sk-proj-EXAMPLE1234567890' ...
No provider request is required.
#
The issue can also be reproduced through MLflow's actual OTLP exporter.
Configure a local OTLP HTTP receiver and set:
export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://127.0.0.1:4318/v1/traces
export OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=http/protobuf
export CREWAI_DISABLE_TELEMETRY=true
Then run:
import mlflowfrom crewai import Agent, Crew, LLM, Task
mlflow.crewai.autolog()
llm = LLM( model="gpt-4.1-mini", api_key="sk-proj-EXAMPLE1234567890", )
agent = Agent( role="Support Responder", goal="Answer support questions", backstory="A support agent", llm=llm, )
task = Task( description="Answer the user's question", expected_output="A response", agent=agent, )
crew = Crew( agents=[agent], tasks=[task], )
crew.kickoff()
A local OTLP receiver can decode the ExportTraceServiceRequest sent by MLflow.
The provider request is expected to fail because the credential is intentionally fake. This does not affect the vulnerability: the sensitive value is added to the MLflow span when the instrumentation starts, before the provider call succeeds or fails.
In the tested environment, the fake API key appeared in the exported telemetry in 5 locations across 2 spans, including:
Support Responder attributes.llm attributes.function_calling_llm attributes.agent_executor attributes.mlflow.spanInputs
Task.execute_sync attributes.mlflow.spanInputs
The captured value is produced by MLflow's actual telemetry/export path rather than being manually inserted into a span.
All credentials used in the reproduction are locally generated fake values. No real API credential is required.
Note: The PoC states it was tested with MLflow 3.16.0, CrewAI 1.15.18, Python 3.12.3, and opentelemetry-exporter-otlp-proto-http 1.42.1.