gcp-composer-update-env-inject-packages

composer.environments.update with softwareConfig.pypiPackages injects an attacker-controlled Python package installed on all workers and the scheduler, executing code as the environment SA at import time.

derived gcp emits CanModifyConfiguration

match (effective permission)

{ "action": "composer.environments.update", "resource_type": "google.composer.Environment" }

where

update targets config.softwareConfig.pypiPackages OR config.softwareConfig.envVariables OR config.softwareConfig.airflowConfigOverrides no SA swap in this update path (separate rule gcp-composer-update-env-attach-sa covers SA swap)

emit

source typeIdentity
target typeAnalyticsService
source<principal>
target<Composer Environment node>
permissionscomposer.environments.update
state logicACTIVE when composer.environments.update is confirmed in the effective grant at project or environment scope. The package installation requires an environment update cycle (minutes) and a worker restart — emit as ACTIVE for the code-injection capability with a note that execution is delayed by the update propagation time. The downstream CanExecuteAs (from can-execute-as execute-as-via-code-modify: CanModifyConfiguration is treated as equivalent to CanModifyCode when it achieves code injection) is ACTIVE once the update propagates. BLOCKED if an IAM deny policy applies to composer.environments.update.

Narrative

{principal.name} can update Composer environment {env.name} (composer.environments.update) to add an attacker-controlled Python package to softwareConfig.pypiPackages; the package is installed on all worker pods and the scheduler and executes at Python import time as the environment SA {sa.name}. No actAs permission is required for this path (unlike SA-swap updates).

Raw rule rules/derived/gcp/composer.yaml

id: gcp-composer-update-env-inject-packages
emits: CanModifyConfiguration
description: composer.environments.update with softwareConfig.pypiPackages injects an attacker-controlled
  Python package installed on all workers and the scheduler, executing code as the environment SA at import
  time.
match_effective_permission:
  action: composer.environments.update
  resource_type: google.composer.Environment
where:
- update targets config.softwareConfig.pypiPackages OR config.softwareConfig.envVariables OR config.softwareConfig.airflowConfigOverrides
- no SA swap in this update path (separate rule gcp-composer-update-env-attach-sa covers SA swap)
emit:
  source_type: Identity
  target_type: AnalyticsService
  source: <principal>
  target: <Composer Environment node>
  permissions:
  - composer.environments.update
  conditions: []
  state_logic: "ACTIVE when composer.environments.update is confirmed in the effective grant at project\
    \ or environment scope. The package installation requires an environment update cycle (minutes) and\
    \ a worker restart \u2014 emit as ACTIVE for the code-injection capability with a note that execution\
    \ is delayed by the update propagation time. The downstream CanExecuteAs (from can-execute-as execute-as-via-code-modify:\
    \ CanModifyConfiguration is treated as equivalent to CanModifyCode when it achieves code injection)\
    \ is ACTIVE once the update propagates. BLOCKED if an IAM deny policy applies to composer.environments.update."
  confidence: 0.9
  derived_from:
  - <composer.environments.update effective permission>
  false_positive_note: "This requires specifying an attacker-controlled PyPI package (e.g., a typosquat\
    \ or a private package the attacker controls). Injecting a package that performs a no-op is not code\
    \ execution \u2014 the package must contain malicious import-time code. The update takes minutes and\
    \ workers are restarted; not an instant execution like the dags/ write path. CanModifyConfiguration\
    \ is ACTIVE for the configuration capability, but the code-execution consequence (downstream CanExecuteAs)\
    \ is CONDITIONAL(external_resource) since the attacker must also control the external PyPI package\
    \ or have registered a typosquat. Also covers envVariables injection (e.g., overriding AIRFLOW__CORE__EXECUTOR\
    \ or pointing PYTHONPATH at an attacker-controlled source) and airflowConfigOverrides (can alter scheduler\
    \ behavior). Cite can-execute-as execute-as-via-code-modify for the CanExecuteAs collapse (treating\
    \ this CanModifyConfiguration as equivalent in effect)."
  narrative: '{principal.name} can update Composer environment {env.name} (composer.environments.update)
    to add an attacker-controlled Python package to softwareConfig.pypiPackages; the package is installed
    on all worker pods and the scheduler and executes at Python import time as the environment SA {sa.name}.
    No actAs permission is required for this path (unlike SA-swap updates).'
move · open · esc close