From 6c307385b0fdcc135b91acdba8771cb793e10070 Mon Sep 17 00:00:00 2001 From: "Andoni A." <14891798+andoniaf@users.noreply.github.com> Date: Mon, 12 Jan 2026 14:47:12 +0100 Subject: [PATCH] fix(attack-paths): preserve aws variable in ECS query WITH clause Add aws to intermediate WITH clause to fix 'Variable aws not defined' error when deduplicating principals before matching target roles. --- api/src/backend/api/attack_paths/query_definitions.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/api/src/backend/api/attack_paths/query_definitions.py b/api/src/backend/api/attack_paths/query_definitions.py index e9193c6f08..0fc3d66689 100644 --- a/api/src/backend/api/attack_paths/query_definitions.py +++ b/api/src/backend/api/attack_paths/query_definitions.py @@ -742,7 +742,7 @@ _QUERY_DEFINITIONS: dict[str, list[AttackPathsQueryDefinition]] = { // Principal can assume roles (up to 2 hops for flexibility) OPTIONAL MATCH path_assume = (principal)-[:STS_ASSUMEROLE_ALLOW*0..2]->(acting_as:AWSRole) - WITH escalation_outcome, principal, path_principal, path_assume, + WITH escalation_outcome, aws, principal, path_principal, path_assume, CASE WHEN path_assume IS NULL THEN principal ELSE acting_as END AS effective_principal // Find iam:PassRole permission @@ -760,6 +760,9 @@ _QUERY_DEFINITIONS: dict[str, list[AttackPathsQueryDefinition]] = { any(action IN ecs_stmt.action WHERE toLower(action) = 'ecs:createservice' OR toLower(action) = 'ecs:runtask' OR action = '*' OR toLower(action) = 'ecs:*') ) + // Deduplicate principals FIRST (before matching target roles) + WITH DISTINCT escalation_outcome, aws, principal, effective_principal + // Find target roles with elevated permissions that could be passed MATCH (aws)--(target_role:AWSRole)--(target_policy:AWSPolicy)--(target_stmt:AWSPolicyStatement) WHERE target_stmt.effect = 'Allow' @@ -768,14 +771,11 @@ _QUERY_DEFINITIONS: dict[str, list[AttackPathsQueryDefinition]] = { OR any(action IN target_stmt.action WHERE toLower(action) = 'iam:*') ) - // Collect all target roles per principal (merge into one node) + // Collect all target roles per principal WITH escalation_outcome, aws, principal, effective_principal, collect(DISTINCT target_role) AS target_roles, count(DISTINCT target_role) AS target_count - // Deduplicate to one node per principal - WITH DISTINCT escalation_outcome, aws, principal, effective_principal, target_roles, target_count - // Create single virtual ECS task node per principal CALL apoc.create.vNode(['ECSTask'], { name: 'New Task Definition',