azure-adf-pipeline-write-modifycode
Overwrite an ADF pipeline definition to inject arbitrary activities (Web, Custom, Copy) that run as the factory MI.
match (effective permission)
{
"action": "Microsoft.DataFactory/factories/pipelines/write",
"scope_type": "resource|resourceGroup|subscription"
}
emit
| source type | Identity |
|---|---|
| target type | Workflow |
| source | <principal> |
| target | <ADF pipeline (Workflow node)> |
| permissions | Microsoft.DataFactory/factories/pipelines/write |
| conditions | trigger_exists |
| state logic | ACTIVE when the definition is modified AND a trigger path exists (a Schedule trigger is Enabled, a Storage Events trigger is bound to an active blob event, or the principal also holds pipelines/createRun/action to start a run directly). CONDITIONAL(trigger_exists) when no confirmed trigger or invoke path exists. BLOCKED if a deny assignment covers pipelines/write at the scope. Note: if the factory uses Git integration (repoConfiguration set), the ARM pipelines/write reflects the PUBLISHED version; modifying via ARM still overwrites the published definition. Parallel path via Git repo is a separate cicd-chains entry. |
Narrative
{principal.name} can overwrite the pipeline definition of {target.name} (Microsoft.DataFactory/factories/pipelines/write), injecting Web, Custom, or Copy activities that run as the factory's managed identity on the next trigger or run invocation.
Raw rule rules/derived/azure/datafactory.yaml
id: azure-adf-pipeline-write-modifycode
emits: CanModifyCode
description: Overwrite an ADF pipeline definition to inject arbitrary activities (Web, Custom, Copy) that
run as the factory MI.
match_effective_permission:
action: Microsoft.DataFactory/factories/pipelines/write
scope_type: resource|resourceGroup|subscription
emit:
source_type: Identity
target_type: Workflow
source: <principal>
target: <ADF pipeline (Workflow node)>
permissions:
- Microsoft.DataFactory/factories/pipelines/write
conditions:
- trigger_exists
state_logic: 'ACTIVE when the definition is modified AND a trigger path exists (a Schedule trigger is
Enabled, a Storage Events trigger is bound to an active blob event, or the principal also holds pipelines/createRun/action
to start a run directly). CONDITIONAL(trigger_exists) when no confirmed trigger or invoke path exists.
BLOCKED if a deny assignment covers pipelines/write at the scope. Note: if the factory uses Git integration
(repoConfiguration set), the ARM pipelines/write reflects the PUBLISHED version; modifying via ARM
still overwrites the published definition. Parallel path via Git repo is a separate cicd-chains entry.'
confidence: 0.97
derived_from:
- 'effective permission: Microsoft.DataFactory/factories/pipelines/write'
false_positive_note: "pipelines/write is granted to Data Factory Contributor, Contributor, and Owner.\
\ The Data Factory Operator role (if used via ARM custom role for trigger management only) does NOT\
\ include pipelines/write; do not derive CanModifyCode from a trigger-only role. Realized on next\
\ trigger event or direct createRun \u2014 without either, emit CONDITIONAL(trigger_exists) not ACTIVE.\
\ The managed identity must exist for CanExecuteAs to fire via can-execute-as; if the factory has\
\ no MI, this yields only linked-service credential access, not ARM token access."
narrative: '{principal.name} can overwrite the pipeline definition of {target.name} (Microsoft.DataFactory/factories/pipelines/write),
injecting Web, Custom, or Copy activities that run as the factory''s managed identity on the next
trigger or run invocation.'