azure-adf-copy-exfiltrate
ADF Copy activity configured with an external or cross-boundary sink (HTTP, public blob, SFTP) can move data outside the authorized boundary.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
node_type(?pipeline) ==
Workflow
?pipeline contains a Copy activity with sink.type targeting an external or cross-boundary storage (HttpSink, BlobSink referencing a non-private storage account, AzureDataLakeSinkV2 with public endpoint, SftpWriteSink, or similar external sink)
the factory MI (or the linked service credential for the sink) has confirmed write access to the sink
emit
| source type | Identity |
|---|---|
| target type | Data |
| source | <principal> |
| target | <data source (Data / ObjectStorage / DataLake node) read by the Copy activity> |
| permissions | Microsoft.DataFactory/factories/pipelines/createRun/action |
| conditions | iam_permission |
| state logic | ACTIVE when: (a) the pipeline Copy activity is configured with an external sink, (b) the factory MI or linked service credential has confirmed write access to the sink, and (c) the principal can trigger the pipeline (createRun/action or a Schedule trigger). CONDITIONAL(iam_permission) when sink write access is unconfirmed. BLOCKED if a deny assignment covers createRun/action or if the managed VNet + approved-only private endpoints prevent outbound traffic to the sink. |
Narrative
{principal.name} can trigger ADF pipeline {pipeline.name}, which contains a Copy activity that reads from {target.name} and writes to an external sink (HTTP / public blob / SFTP); triggering this pipeline exfiltrates the data source contents to outside the authorized boundary.
Raw rule rules/derived/azure/datafactory.yaml
id: azure-adf-copy-exfiltrate
emits: CanExfiltrate
description: ADF Copy activity configured with an external or cross-boundary sink (HTTP, public blob,
SFTP) can move data outside the authorized boundary.
match:
- - principal: null
- CanInvoke
- pipeline: null
- - pipeline: null
- ExecutesAs
- mi: null
where:
- node_type(?pipeline) == Workflow
- ?pipeline contains a Copy activity with sink.type targeting an external or cross-boundary storage (HttpSink,
BlobSink referencing a non-private storage account, AzureDataLakeSinkV2 with public endpoint, SftpWriteSink,
or similar external sink)
- the factory MI (or the linked service credential for the sink) has confirmed write access to the sink
emit:
source_type: Identity
target_type: Data
source: <principal>
target: <data source (Data / ObjectStorage / DataLake node) read by the Copy activity>
permissions:
- Microsoft.DataFactory/factories/pipelines/createRun/action
conditions:
- iam_permission
state_logic: 'ACTIVE when: (a) the pipeline Copy activity is configured with an external sink, (b) the
factory MI or linked service credential has confirmed write access to the sink, and (c) the principal
can trigger the pipeline (createRun/action or a Schedule trigger). CONDITIONAL(iam_permission) when
sink write access is unconfirmed. BLOCKED if a deny assignment covers createRun/action or if the managed
VNet + approved-only private endpoints prevent outbound traffic to the sink.'
confidence: 0.85
derived_from:
- '<CanInvoke edge: ?principal -> ?pipeline>'
- '<ExecutesAs edge: ?pipeline -> ?mi>'
- '<Copy activity sink configuration: external / cross-boundary sink>'
false_positive_note: "Exfiltration requires BOTH the Copy activity to be configured with a cross-boundary\
\ or external sink AND the factory MI (or linked service) to have confirmed write access to the sink.\
\ A Copy activity whose sink is a private storage account in the same subscription is NOT exfiltration\
\ \u2014 scope strictly to external or cross-boundary sinks. The principal who triggers the pipeline\
\ is the attacker-controlled identity; the data at risk is what the Copy source reads (determined\
\ by the source linked service). If the factory uses managed VNet with approved-only private endpoints,\
\ outbound traffic to arbitrary external sinks is BLOCKED (managed virtual network outbound rules\
\ restrict egress to approved services only)."
narrative: '{principal.name} can trigger ADF pipeline {pipeline.name}, which contains a Copy activity
that reads from {target.name} and writes to an external sink (HTTP / public blob / SFTP); triggering
this pipeline exfiltrates the data source contents to outside the authorized boundary.'