Skip to content

fix: detect AttachRolePolicy/PutRolePolicy/UpdateAssumeRolePolicy privesc without sts:AssumeRole#581

Merged
kmcquade merged 2 commits into
masterfrom
fix/580-privesc-without-assumerole
May 29, 2026
Merged

fix: detect AttachRolePolicy/PutRolePolicy/UpdateAssumeRolePolicy privesc without sts:AssumeRole#581
kmcquade merged 2 commits into
masterfrom
fix/580-privesc-without-assumerole

Conversation

@kmcquade
Copy link
Copy Markdown
Collaborator

Summary

Three methods in PRIVILEGE_ESCALATION_METHODS bundled sts:assumerole as a required action, producing false negatives: a policy granting iam:AttachRolePolicy (or iam:PutRolePolicy / iam:UpdateAssumeRolePolicy) on * without sts:AssumeRole was not flagged — even though it can attach AdministratorAccess to any role.

This relaxes the three entries to the IAM write alone. The existing + sts:AssumeRole cases still fire (the relaxed action set is a subset of them), so nothing previously detected is lost — only coverage is added. Aligns with DataDog/pathfinding.cloud iam-005/iam-009/iam-012 and peer tools (PMapper, Prowler).

Changes

  • cloudsplaining/shared/constants.py: drop sts:assumerole from AttachRolePolicy, PutRolePolicy, UpdateRolePolicyToAssumeIt.
  • New TDD test proving iam:AttachRolePolicy alone is flagged.
  • Update 3 existing assertions that expected the bundled action list.

Testing

  • just unit-tests — 94 passed
  • just type-check — clean
  • just test-js — 43 passing

Closes #580

…vesc without sts:AssumeRole

The three IAM role-policy escalation methods required sts:AssumeRole bundled
in, missing policies that grant the IAM write alone. Relax to the IAM action.

Closes #580
@kmcquade kmcquade merged commit 726b396 into master May 29, 2026
13 checks passed
@kmcquade kmcquade deleted the fix/580-privesc-without-assumerole branch May 29, 2026 15:04
kmcquade added a commit that referenced this pull request May 30, 2026
…new detections) (#584)

* feat: link privilege-escalation findings to pathfinding.cloud + refresh report

Each detected privilege-escalation method in the report now links to its pathfinding.cloud path page (e.g. CreateAccessKey -> /paths/iam-002) instead of the generic readthedocs glossary. Methods with no published path render as plain text.

- cloudsplaining/output/src/util/pathfinding-paths.json + pathfinding.js: method -> pathfinding URL map (mirrors PRIVILEGE_ESCALATION_METHODS; verified against repos/pathfinding.cloud).

- PrivilegeEscalationFormat.vue: render per-method pathfinding links.

- constants.py PRIVILEGE_ESCALATION_PATHFINDING_PATHS (canonical) + getFindingLinks in inline_policy.py/managed_policy_detail.py now emit pathfinding links in the data, so the data and report agree. Unmapped methods fall back to the glossary.

- Tests: mocha pathfinding-test.js + Python test_pathfinding_mapping.py (completeness + Python/JS parity + URL format).

- Regenerated example-iam-data.json, sampleData.js, dist bundle, and the published root index.html (now the comprehensive production report, not a dev build).

Covers the 20 existing Rhino-era paths. The 46 pathfinding.cloud paths cloudsplaining does not yet DETECT (apprunner, bedrock, ecs, sagemaker, codebuild, ssm, sts, newer iam/lambda/glue/cloudformation/ec2) are added in follow-on commits on this branch.

* feat: detect 37 additional pathfinding.cloud privilege-escalation paths

cloudsplaining previously detected only the ~22 Rhino-era privilege-escalation methods, missing 46 of pathfinding.cloud's 66 paths (entire services like apprunner, bedrock, ecs, sagemaker, codebuild). This adds detection for 37 of them to PRIVILEGE_ESCALATION_METHODS, each verified recognized by policy_sentry and mapped to its pathfinding.cloud writeup.

Added (low/medium false-positive risk, precise multi-action signatures): AppRunner/Bedrock/CodeBuild/ECS(x6)/Glue(x4)/SageMaker(x5)/Lambda/CloudFormation StackSet/EC2 PassRole + several new IAM principal-access chains (CreateAndRotateAccessKey, AttachUserPolicyThenCreateAccessKey, *ThenUpdateAssumeRolePolicy, etc.).

HELD (not added) - 7 high-FP single broad-action paths that would over-flag and contradict the #581 sts:assumerole fix: sts-001 (sts:AssumeRole alone), ssm-001/002 (StartSession/SendCommand), cloudformation-002 (UpdateStack), apprunner-002, codebuild-002/003. SKIPPED 2 redundant (iam-014/017 = existing AttachRolePolicy/PutRolePolicy).

- constants.py: +37 methods + matching PRIVILEGE_ESCALATION_PATHFINDING_PATHS entries (no duplicate keys; Python/JS parity + completeness tests enforce sync).

- test/scanning/test_privilege_escalation_methods.py: every method must self-detect from its own actions (also verifies policy_sentry recognition).

- Regenerated fixtures + report: privesc-high-priv-service-policy now flags 59 distinct methods (was 22); report adds 179 findings, drops 0; report links every detected method to pathfinding.cloud.

- docs/glossary/privilege-escalation.md: documents the 37 new paths.

- research/pathfinding-cloud/proposed-new-methods.json: provenance for all 46 (incl. held/skipped + FP rationale).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Privilege escalation false negative: AttachRolePolicy / PutRolePolicy / UpdateAssumeRolePolicy require sts:AssumeRole

1 participant