Pipelines of Privilege: Attack Paths from DevOps to MLOps Infrastructure

4.9.26
WRITTEN BY
Brett Hawkins
Pipelines of Privilege: Attack Paths from DevOps to MLOps Infrastructure

As DevOps automation extends into machine learning, the attack surface expands in ways many organizations haven’t yet noticed. Today’s CI/CD and Machine Learning Operations (MLOps) ecosystem are built on platforms like GitHub and Azure DevOps, which are deeply interconnected and packed with credentials, automation logic, and deployment secrets that can be exploited as pivot points. Once breached, these CI/CD pipelines offer attackers a direct path into high-value ML environments such as Azure ML and Amazon SageMaker.

This research showcases DevOps-to-MLOps attack chains that lead to remote code execution in ML training compute. Each attack scenario highlights the details of the attack path and exposes why standard IAM, segmentation, and logging controls often fail to detect or prevent them. On the defensive side, we’ll explore practical countermeasures for locking down service account scopes, isolating build and training clusters, and enforcing artifact trust boundaries. You will receive guidance on how to detect, contain, and harden your environment against these emerging DevOps-to-MLOps attack paths.

Summary of Key Points

  • Five key trust boundaries are highlighted for the abuse of integrations between DevOps and MLOps platforms.
  • Four attack paths are detailed in this research for pivoting from DevOps repositories to ML training environments.
  • A prioritized list of defensive guidance is provided to help organizations reduce risk, covering practical countermeasures like locking down service account scopes and isolating build and training environments.
  • A new OpenGraph collector named Dop2Mop was created to help in identifying and mapping potential attack paths from DevOps to MLOps infrastructure:
  • The Armadin BloodHound MCP server was updated to support the analysis of data collected from Dop2Mop:

Background

Prior Work

Below are references to my prior public security research related to DevOps and MLOps security. This research focuses on blending these two security research areas to show how an attacker can pivot from DevOps environments into MLOps infrastructure.

DevOps Security Research

Controlling the Source: Abusing Source Code Management Systems

Hiding in the Clouds: Abusing Azure DevOps Services to Bypass Microsoft Sentinel Analytic Rules

MLOps Security Research

Disrupting the Model: Abusing MLOps Platforms to Compromise ML Models and Enterprise Data Lakes

Becoming the Trainer: Attacking ML Training Infrastructure

MLOps Overview

MLOps is the practice of deploying and maintaining ML models in a secure, efficient, and reliable way. The goal of MLOps is to provide a consistent and automated process to be able to rapidly get an ML model into production for use by ML technologies. MLOps exists at the intersection of machine learning, DevOps, and data engineering.

MLOps Diagram

Attack Surface Analysis

Integrations between DevOps and MLOps

Modern machine learning pipelines rarely exist in isolation. Instead, MLOps is deeply intertwined with DevOps, borrowing the same principles of automation, version control, continuous integration, and continuous delivery to accelerate model development and deployment. Source code repositories, CI/CD platforms, and infrastructure-as-code pipelines are now responsible not only for application builds, but also for orchestrating data preprocessing jobs, launching model training, registering artifacts, and promoting models into production environments.

This tight integration means that DevOps systems often act as the control plane for MLOps. Platforms like GitHub, GitLab, Azure DevOps, and AWS CodeBuild routinely trigger ML workflows based on code commits, scheduled jobs, or pipeline events. These systems authenticate into ML platforms such as Azure Machine Learning (Azure ML) and Amazon SageMaker (SageMaker) using non-human identities (NHIs), service principals, automation roles, or API tokens to submit training jobs, access datasets, manage compute resources, and deploy models at scale.

DevOps and MLOps Integration

While this convergence enables rapid experimentation and repeatability, it also expands the attack surface. A compromise in a DevOps environment can directly translate into control over ML infrastructure, and vice versa. Automation credentials frequently traverse both domains, bridging traditional software delivery pipelines with high-privilege ML training compute. Understanding how DevOps and MLOps are connected is therefore critical not just for reliability and scale, but for securing the entire ML lifecycle against identity-driven attacks.

Attack Surface Diagram

DevOps and MLOps Trust Boundaries

There are implicit trusts that exist in the DevOps-to-MLOps pipeline where attackers can cross security boundaries without triggering alarms.

Trust Boundary #1: Code Repository to CI/CD Pipeline

This represents the automatic triggering of CI/CD pipelines when code is committed to a code branch. The pipeline implicitly trusts that code has been properly reviewed and approved, automatically executing without additional validation. If an attacker compromises a developer account or bypasses branch protection, they can commit malicious code that the pipeline will automatically execute with access to secrets, cloud credentials, and deployment permissions.

Trust Boundary 1 Diagram
Trust Boundary #1 Diagram

Trust Boundary #2: Service Account Authentication

The second trust boundary represents the implicit trust ML platforms place in the service account identities used by CI/CD pipelines. When pipelines authenticate using service connections (NHI), the ML platform assumes these credentials represent legitimate automation and grants access to submit and execute ML jobs without additional scrutiny. If the CI/CD pipeline is compromised, attackers can steal or abuse these service account credentials to submit malicious ML training jobs that appear legitimate to the platform.

Trust Boundary 2 Diagram
Trust Boundary #2 Diagram

Trust Boundary #3: Container Artifact Trust

The third trust boundary represents the implicit trust placed in container images from internal artifact registries. When ML orchestration systems provision training infrastructure, they pull and execute container artifacts (Dockerfiles and environment definitions) without validation, assuming images built by the internal pipeline are safe. If the build pipeline is compromised, attackers can inject malicious code into Dockerfiles, resulting in poisoned containers that execute with full privileges in the training environment.

Trust Boundary 3 Diagram
Trust Boundary #3 Diagram

Trust Boundary #4: Job Definition Execution

Trust boundary #4 represents the implicit trust ML platforms place in job definition contents submitted via authenticated service accounts. When orchestration systems execute job definitions (e.g., job.yml/pipeline.yml files), they do not validate the specifications for malicious parameters such as unauthorized data access, excessive compute requests, or data exfiltration paths. Attackers who compromise service account credentials can submit job definitions that specify malicious training scripts, access sensitive datasets, or exfiltrate data through model artifacts.

Trust Boundary 4 Diagram
Trust Boundary #4 Diagram

Trust Boundary #5: Code Deserialization

The last trust boundary shows the implicit trust that training code gives to serialized datasets loaded from internal storage. When training jobs deserialize data using unsafe formats like pickle or joblib, malicious code embedded in poisoned datasets can execute automatically through methods like __reduce__(), without any explicit invocation by the training script. If data pipelines are compromised or datasets are poisoned through supply chain attacks, attackers can achieve remote code execution in the training environment with full access to credentials, training data, and model artifacts.

Trust Boundary 5 Diagram
Trust Boundary #5 Diagram

Attack Scenarios

We will explore the following attack scenarios to show lateral movement to MLOps platforms via various DevOps components that are integrated within an automated ML training pipeline.

Table of Attack Scenarios

Attack Scenario #1: Lateral Movement from Azure DevOps to Azure ML Cloud Compute

Below is a high-level diagram showing the Lateral Movement from an Azure DevOps to Azure ML Cloud Compute attack scenario.

Attack Scenario 1 Diagram

The example Azure DevOps Pipeline configuration shown below is configured to create an Azure ML training job within Azure ML compute, based upon the configuration set within the Azure ML job definition files (environment.yml and job.yml). In this attack scenario, an attacker has compromised a personal access token (PAT) for Azure DevOps and gained access to the repository containing this ML training project.

A screenshot of a computer programAI-generated content may be incorrect.
Azure Pipeline config file

The attacker can then review the pipeline configuration, identifying the Azure ML job definition file being used. The following figure shows a job file that runs an ML training experiment within Azure ML by executing the train.py script file.

A screenshot of a computerAI-generated content may be incorrect.
Azure ML config file - original

The attacker can then modify the “command” variable to execute an arbitrary command and commit the updated code to the Azure DevOps repository. In this example the attacker modifies the variable to be a one-liner reverse shell.

A screenshot of a computerAI-generated content may be incorrect.
Azure ML config file - modified

The Azure DevOps pipeline picks up this change and starts running the automated ML workflow, which includes creating an Azure ML compute instance within a compute cluster and running the training job within that associated compute instance. As you can see, the attacker’s reverse shell code executes within the Azure ML compute instance and gives them privileged access to the container running within that Azure ML compute.

Obtaining reverse shell within Azure ML training compute

Attack Scenario #2: Pipeline Artifact Poisoning to MLOps Execution

Below is a high-level diagram showing the Pipeline Artifact Poisoning to MLOps Execution attack scenario.

Attack Scenario 2 Diagram

Instead of modifying pipeline code or job definitions, an attacker can poison pipeline-produced artifacts that are implicitly trusted and later consumed by an MLOps platform, resulting in code execution during model training or evaluation. In this scenario , we have a pipeline that builds and publishes artifacts such as Docker images.

GitHub workflow that builds Docker image

These trusted artifacts are then automatically promoted to an internal registry, in this case Amazon ECR.

Listing private ECR registry repositories

Through the access provided by stolen credentials, the attacker poisons the Docker image that is being used for training as shown in the figure below.

Running workflow to poison Docker image

When the ML training is performed using the attacker’s custom (and poisoned) Docker image, it will run the attacker’s malicious code and give us a reverse shell in the ML training environment.

Getting reverse shell in Docker container

Artifact integrity is rarely enforced between DevOps and MLOps. ML platforms implicitly trust internal registries and it is normal for training jobs to routinely pull images at runtime.

Attack Scenario #3: Abuse of DevOps OIDC/Federated Identity to Assume ML Execution Roles

Below is a high-level diagram showing the Abuse of DevOps OIDC/Federated Identity to Assume ML Execution Roles attack scenario.

Attack Scenario 3 Diagram

In many DevOps-to-MLOps workflows, pipelines authenticate using federated identity, managed identity, or execution roles rather than long-living secrets. In these cases, attackers do not need to steal credentials from a DevOps platform. Once pipeline logic or execution is compromised, the pipeline itself can be used to submit ML jobs, access datasets, or provision training compute under its NHI. Because these actions are performed using approved automation identities, they appear legitimate within audit logs and are difficult to distinguish from expected pipeline behavior. Due to how OpenID Connect (OIDC) works, there are no credentials to steal or rotate, and it appears as legitimate automation in the logs. Therefore, the trust boundary is the source code repository itself. From a detection standpoint, this means focusing on pipeline behavior changes and analyzing git commit history correlation.

In this example, we have a GitHub Actions workflow that is configured to authenticate to AWS using OIDC federation in order to submit SageMaker training jobs. The workflow does not store any AWS credentials. Instead, it exchanges an OIDC token for an IAM role that has permission to create SageMaker training jobs and access specific S3 buckets.

Snippet of OIDC authentication

An attacker who gains the ability to modify the workflow file (typically within .github\workflows) or trigger the workflow in an unintended context does not need to recover any secrets. By simply reusing the existing job submission logic, the attacker can submit arbitrary SageMaker training jobs that execute attacker-controlled code, inherit the SageMaker execution role, and access the same datasets and resources as legitimate training jobs.

In this example, the attacker’s malicious workflow assumes the pipeline identity and lists all training jobs that it has access to.

Verifying access with compromised identity

After listing training jobs that the attacker’s workflow has access to, the workflow executes the malicious code that attacker added within a Python script to obtain a reverse shell on the SageMaker training compute instance using the OIDC identity. 

Receiving reverse shell in SageMaker training compute

Another example of the impact this attack scenario poses would be the ability to steal datasets for models the OIDC identity has access to. In this case, the attacker’s  malicious code created a recon_data.json file that included what S3 buckets it had access to, which is typically where model artifacts and datasets are stored within the AWS SageMaker ecosystem.

JSON file with recon data

From an AWS logging perspective, all activity is performed by the expected IAM role via a valid federated login, making the behavior indistinguishable from normal pipeline-driven automation.

Attack Scenario #4: Pipeline-Driven Dataset or Feature Store Poisoning

Below is a high-level diagram showing the Pipeline-Driven Dataset or Feature Store Poisoning attack scenario.

Attack Scenario 4 Diagram

An attacker can abuse DevOps-controlled data preprocessing pipelines to poison datasets or feature stores that are later consumed by ML training jobs, resulting in malicious code execution or model compromise. In this example, a DevOps pipeline is responsible for data preprocessing, feature engineering, and writing datasets to cloud storage or a feature store.

This scenario includes an attacker gaining access to the pipeline configuration or preprocessing code and then poisoning a Pickle-based dataset in a CI preprocessing pipeline to trigger execution during the ML training process. This is what the normal preprocessing workflow looks like in this example. You can see it saves the dataset in the pickle format to an S3 bucket.

Data preprocessing workflow

When the normal ML training workflow is kicked off, it loads the Pickle dataset for training.

Running training workflow

In this scenario an attacker adds a malicious GitHub workflow to poison the dataset that is located within the S3 bucket. This workflow will embed malicious scripts in the feature data. Below is a snippet of the output of the malicious dataset poisoning workflow executing.

Running poison dataset workflow

When the normal ML training workflow runs, the downstream ML training job loads the dataset and triggers the execution. In this case, the poisoned dataset executes the attacker’s reverse shell code during the ML training process.

Getting reverse shell

Data is rarely treated as an execution surface. Additionally, ML training code often deserializes data without validation and feature stores are implicitly trusted once they are populated.

Identifying DevOps-to-MLOps Attack Paths with Dop2Mop

We created a proof-of-concept OpenGraph collector named Dop2Mop in support of this research to help identify potential attack paths relating to DevOps-to-MLOps attack chains. There will be several example Cypher queries highlighted below related to identifying trust boundaries and attack paths related to this research. For full details on Dop2Mop, check the documentation in the GitHub repository.

Identifying Trust Boundaries using Dop2Mop

Trust Boundary #1: Code Repository to CI/CD Pipeline

MATCH (repo)-[:TriggersPipeline]->(pipeline)
RETURN repo, pipeline
Cypher Query Results - Trust Boundary #1

Trust Boundary #2: Service Account Authentication

MATCH (sc:ADOServiceConnection)-[:HasAccessTo]->(target)
RETURN sc, target
Cypher Query Results - Trust Boundary #2

Trust Boundary #3: Container Artifact Trust

MATCH (attacker)-[:CanPoisonImage]->(image:ContainerImage)
MATCH (job)-[:PullsImage]->(image)
RETURN attacker, image, job
Cypher Query Results - Trust Boundary #3

Trust Boundary #4: Job Definition Execution

MATCH (entity)-[:CanModifyJob]->(job)
RETURN entity, job
Cypher Query Results - Trust Boundary #4

Trust Boundary #5: Code Deserialization

MATCH (attacker)-[:CanPoisonDataset]->(dataset:Dataset)
MATCH (job)-[:LoadsDataset]->(dataset)
RETURN attacker, dataset, job
Cypher Query Results - Trust Boundary #5

Identifying Attack Paths using Dop2Mop

Attack Scenario #1: Azure DevOps to Azure ML Lateral Movement

This scenario shows the ability of an attacker to compromise an Azure DevOps repository named MLTRAINING, and then modify a pipeline YAML to inject malicious code. After this pipeline YAML is modified, it would execute the MLTRAINING Azure DevOps pipeline to submit jobs to an Azure ML compute cluster named CPU-CLUSTER within the TEST-WORKSPACE Azure ML workspace.

MATCH p=(repo)-[:TriggersPipeline]->(pipeline)-[:SubmitsJob]->(workspace)-[:CodeExecution]->(compute)
RETURN p
Cypher Query Results - Attack Scenario #1

Attack Scenario #2: Pipeline Artifact Poisoning to MLOps Execution

This scenario shows the ability for an attacker to compromise a GitHub repository containing GitHub Action Workflows named BUILD-TRAINING-IMAGE and DATA-PREPROCESSING. Both of these GitHub Action Workflows are responsible for building a Docker image named TRAINING-BASE:LATEST that is used as part of SageMaker training jobs named FRAUD-DETECTION-JOB and SENTIMENT-TRAINING-JOB. Therefore, once the attacker poisons the container image via a malicious workflow, that malicious container image will be used as part of the SageMaker training job and executed within the SageMaker ML training environment.

MATCH p=(workflow)-[:CanPoisonImage]->(image)<-[:PullsImage]-(job)
RETURN p
Cypher Query Results - Attack Scenario #2

Attack Scenario #3: Abuse of DevOps OIDC/Federated Identity to Assume ML Execution Roles

The third scenario shows the possibility for an attacker to compromise a GitHub workflow named DEPLOY-MODEL that uses OIDC federation to authenticate as the GITHUBACTIONSROLE-SAGEMAKER assumed IAM role to submit SageMaker training jobs named SENTIMENT-TRAINING-JOB and FRAUD-DETECTION-JOB. Therefore, once the attacker would compromise this GitHub workflow to submit malicious code to the training jobs, the attacker would gain code execution within the SageMaker ML training environment.

MATCH p=(workflow)-[:OIDCTrust]->(oidc)-[:CanAssumeRole]->(role)-[:SubmitsJob]->(job)
RETURN p
Cypher Query Results - Attack Scenario #3

Attack Scenario #4: Pipeline-Driven Dataset or Feature Store Poisoning

This last scenario shows the ability of an attacker to compromise a data preprocessing workflow named DATA-PREPROCESSING and poison a pickle dataset named TRAINING_DATA.PKL. When the SENTIMENT-TRAINING-JOB SageMaker training job loads and deserializes the dataset, the malicious code would execute in the SageMaker ML training environment.

MATCH p=(workflow)-[:CanPoisonDataset]->(dataset)<-[:LoadsDataset]-(job) 
RETURN p
Cypher Query Results - Attack Scenario #4

Analyze DevOps-to-MLOps Attack Paths with Armadin BloodHound MCP Server

Another method to analyze potential DevOps-to-MLOps attack paths is by using the Armadin BloodHound MCP server. As part of this research, we have updated our MCP server to support data collected with Dop2Mop. For example, you can use the MCP server’s web interface to perform ad-hoc natural language queries as shown in the figure below.

Using Armadin BloodHound MCP server web interface

Another option when using the Armadin BloodHound MCP server is to use the Gemini CLI extension to have a multi-turn conversation when attempting to discover DevOps-to-MLOps attack paths.

Snippet of output of Gemini CLI extension

This helps simplify the data analysis of the data collected with Dop2Mop by including an LLM as an analysis assistant.

Defensive Considerations

DevOps and MLOps are no longer separate security domains. NHI’s routinely can bridge both, bypassing traditional trust boundaries. Defenders who treat CI/CD pipelines and ML platforms as isolated systems risk missing attack paths that take advantage of their integration. By locking down service account scopes, isolating build and training environments, enforcing artifact trust boundaries, and shifting detection toward pipeline and job behavior, organizations can reduce the risk posed by these emerging DevOps-to-MLOps attack techniques. Here is a prioritized and summarized list of guidance with public resources for each recommendation.

Immediate Guidance

Scan CI/CD logs for exposed credentials

Resources:

Enable GitHub/GitLab secret scanning

Resources:

Review service principal/IAM role permissions (least privilege)

Resources:

Enable audit logging on all platforms

Resources:

Short-Term Guidance

Implement pipeline change approval workflows

Resources:

Harden CI/CD identity, integrity, and execution controls

Resources:

Migrate long-lived secrets to OIDC/federated identity

Resources:

Isolate CI/CD build agents on separate network segments

Resources:

Medium-Term Guidance

Artifact signing and verification

Resources:

Training job sandboxing (metadata blocking, egress restrictions)

Resources:

Comprehensive behavioral baselining for pipelines

Resources:

Automated artifact scanning

Resources:

Long-Term Guidance

Zero-trust ML training architecture

Resources:

Hardware-based training job isolation

Resources:

ML supply chain security framework

Resources:

Threat hunting program (DevOps and MLOps)

Resources:

Conclusion

The attack paths and trust boundaries highlighted in this research show how DevOps pipelines have quietly become high-privilege control planes for modern MLOps environments. As CI/CD systems increasingly orchestrate ML training and deployment, the trust placed in automation identities, pipeline logic, and job definitions creates direct and often hidden paths into sensitive ML compute. Once an attacker can influence pipeline-controlled artifacts, they effectively inherit the privileges of the ML platform itself without triggering traditional IAM, network, or behavioral alerts. Defending against these attacks requires treating pipelines and non-human identities as first-class security boundaries, breaking implicit trust between build and training systems, and shifting detection upstream toward pipeline integrity and anomalous job behavior. As ML continues to operationalize at scale, understanding and dismantling these pipelines of privilege will be critical to securing the ML lifecycle.

Continue reading
The End of the Known Adversary:  Why Security Strategies Must Change
Blog
6.2.26
The End of the Known Adversary: Why Security Strategies Must Change
Dark Reading - 20 Leaders Who Built the CISO Era: 2 Decades of Change
News
5.19.26
Dark Reading - 20 Leaders Who Built the CISO Era: 2 Decades of Change
Armadin Discovers Two More Zero Days: Passback Perfection CVE-2026-28297 and CVE-2026-28298 Plus Credential Relaying for Full Domain Compromise
Blog
5.13.26
Armadin Discovers Two More Zero Days: Passback Perfection CVE-2026-28297 and CVE-2026-28298 Plus Credential Relaying for Full Domain Compromise