Keypoints
- Cloud Composer runs on Apache Airflow and is tightly integrated with Google Cloud services, using a dedicated Cloud Storage bucket per environment.
- Write access to the environment’s Cloud Storage bucket, specifically the “dags” folder, allows attackers to upload DAGs that Airflow will run automatically.
- The default Cloud Composer configuration uses the Default Compute Engine Service Account, which by default has Editor permissions on the entire project.
- An attacker can gain command execution and retrieve service account tokens by uploading a crafted Python DAG without needing access to the Airflow UI.
- NetSPI reported the behavior to Google VRP; Google determined it to be Intended Behavior and updated documentation to emphasize customer responsibility for bucket IAM.
- Prevention recommendations include applying least privilege to bucket access and avoiding use of the Default Compute Engine Service Account for Composer.
MITRE Techniques
- [T1068] Privilege Escalation – Attacker uploads DAGs to gain elevated execution within Composer, enabling access to attached service account. [‘An attacker that has write access to the Cloud Composer environment’s dedicated bucket … can gain command execution in the Composer environment.’]
- [T1071] Application Layer Protocol – Malicious DAGs send tokens or data out to an externally available listener to maintain control/communication. [‘The DAG file will query the metadata service for a Service Account token and send that to the externally available webserver.’]
- [T1041] Exfiltration Over C2 Channel – The DAG posts the retrieved service account token to an external server, exfiltrating credentials. [‘Monitor the listening webserver for a POST request with the Service Account access token.’]
- [T1134] Access Token Manipulation – The DAG queries the metadata service for a service account token and transfers it outbound for use. [‘the BashOperator has been used to query the metadata service for a token which is then sent outbound to a listening web server’]
Indicators of Compromise
- [URL/Endpoint] Metadata and exfil endpoints – http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token (metadata token endpoint), https://[REDACTED]/test (example external listener)
- [File/DAG] Malicious DAG artifacts – example DAG shown with id ‘netspi_dag_test’ and an uploaded Python DAG file that executes bash commands
- [Bucket/Folder] Cloud Storage targets – ‘dags’ folder in the Composer environment’s bucket (auto-synced to Airflow)
- [Project] Example project context – ‘cc-demo’ used in the proof-of-concept setup
- [Log sources] Detection artifacts – gcs-syncd, airflow-scheduler, and airflow-worker logs referenced for detecting new DAG uploads
Cloud Composer environments store Airflow DAGs in a dedicated Cloud Storage bucket and automatically sync the bucket’s “dags” folder into the Airflow runtime. If an identity has write access to that folder, an attacker can simply upload a crafted Python DAG that the scheduler will pick up and run, allowing command execution in the environment without any UI access. The proof-of-concept demonstrates using a BashOperator to query the metadata service for the default service account token and POST it to an externally reachable server.
The root of the risk is default configuration: Composer commonly runs with the Default Compute Engine Service Account, which often has Editor permissions across the project. Combined with customer-managed bucket IAM, this creates a powerful escalation path when write access to the bucket is granted too broadly. Google reviewed the report and labeled this workflow as Intended Behavior, updating documentation to clarify customer responsibilities for bucket permissions.
To mitigate, apply least privilege to both the service account used by Composer and any identities with access to the environment’s Cloud Storage bucket. Avoid assigning the Default Compute Engine Service Account to Composer; restrict or remove write permissions on the “dags” folder for non-essential identities; and monitor gcs-syncd and Airflow logs for unexpected new Python files or DAG sync events to detect potential malicious uploads early.