Skip to content

[security-audit-agent] Security Audit: Lambda IAM Privilege Escalation Path, Config Dir Permissions, Unpinned Image#61

Closed
rosa-regional-platform-ci wants to merge 1 commit into
openshift-online:mainfrom
rosa-regional-platform-ci:security-audit-agent/2026-05-15
Closed

[security-audit-agent] Security Audit: Lambda IAM Privilege Escalation Path, Config Dir Permissions, Unpinned Image#61
rosa-regional-platform-ci wants to merge 1 commit into
openshift-online:mainfrom
rosa-regional-platform-ci:security-audit-agent/2026-05-15

Conversation

@rosa-regional-platform-ci

Copy link
Copy Markdown

Security Audit — rosa-regional-platform-cli

Audit Date: 2026-05-15 | Auditor: security-audit-agent (automated)

This PR documents security findings from an automated security audit. No fixes are included — the goal is to surface issues for maintainer triage.


🔴 HIGH — Finding 1: Lambda IAM Role Has Unrestricted Resource Scope for IAM Operations — Privilege Escalation Path

Affected file: internal/cloudformation/templates/lambda-bootstrap.yaml:88-107

- Sid: IAMResourceManagement
  Effect: Allow
  Action:
    - iam:CreateRole
    - iam:AttachRolePolicy
    - iam:PutRolePolicy
    - iam:DeleteRolePolicy
    # ... more IAM actions
  Resource: '*'   # <-- unrestricted

Risk: The Lambda execution role can create any IAM role and attach any policy (AWS-managed or customer-managed) to it, scoped to all IAM resources (Resource: *). There is no IAM permission boundary enforced on created roles. This is a privilege escalation path:

  1. Compromised Lambda code creates a new IAM role.
  2. Attaches AdministratorAccess to it (this action is allowed — AttachRolePolicy on Resource: *).
  3. Assumes the new role (if sts:AssumeRole trust policy allows the Lambda's execution role principal).
  4. Achieves full account admin access.

Attack Vectors:

  • Compromised container image: If the Lambda's container image uses a mutable tag (see Finding 4), a supply chain attack gives an attacker a Lambda execution environment with these IAM permissions.
  • CloudFormation parameter injection: If the Lambda constructs role names or policy documents from CloudFormation event parameters without sanitization, malicious parameter values could trigger unexpected IAM operations.
  • Lambda event source manipulation: If Lambda is invoked from an event source that can be manipulated (API Gateway, SQS), forged events could trigger unauthorized IAM operations.

What to Mitigate:

  1. Enforce IAM Permission Boundaries: Require that all roles created by the Lambda have a permission boundary attached:
    Condition:
      StringEquals:
        iam:PermissionsBoundary: arn:aws:iam::${AccountId}:policy/rosa-cluster-role-boundary
  2. Restrict Resource scope: Limit to arn:aws:iam::${AccountId}:role/rosa-* and arn:aws:iam::${AccountId}:instance-profile/rosa-*.
  3. Restrict AttachRolePolicy: Add condition iam:PolicyARN: arn:aws:iam::aws:policy/service-role/ROSA* to prevent attaching arbitrary managed policies.

🔴 HIGH — Finding 2: Lambda IAM Role Can Pass Any Role to CloudFormation and Has Unrestricted EC2/Route53 Scope

Affected file: internal/cloudformation/templates/lambda-bootstrap.yaml:50-52, 94-96, 135-137

- Sid: PassRoleForCloudFormation
  Action: iam:PassRole
  Resource: '*'    # can pass ANY role in the account to CloudFormation
  Condition:
    StringEquals:
      iam:PassedToService: cloudformation.amazonaws.com

- Sid: VPCResourceManagement
  # All EC2 VPC operations...
  Resource: '*'    # affects ALL EC2 resources in the account

- Sid: Route53ResourceManagement
  # CreateHostedZone, DeleteHostedZone, AssociateVPCWithHostedZone...
  Resource: '*'    # affects ALL Route53 hosted zones

Risk:

PassRole Resource: *: The Lambda can pass any IAM role in the account to CloudFormation stacks it deploys. If an existing over-privileged or admin role exists, a malicious CloudFormation template triggered by the Lambda can operate with that role's permissions.

VPCResourceManagement Resource: *: The Lambda can modify security groups, route tables, and VPC configurations for all VPCs in the account — not just ROSA cluster VPCs. A compromised Lambda could open security groups for unrelated production workloads.

Route53ResourceManagement Resource: *: The Lambda can associate any VPC with any hosted zone and create/delete hosted zones across the account, potentially disrupting DNS for non-ROSA services.

What to Mitigate:

  • Restrict iam:PassRole Resource to arn:aws:iam::${AccountId}:role/rosa-*.
  • Restrict EC2 operations using resource tag conditions: ec2:ResourceTag/ManagedBy: rosactl.
  • Restrict Route53 operations to resource ARN patterns for ROSA-managed zones.

🟡 MEDIUM — Finding 3: CLI Config Directory Created with World-Readable Permissions (0755)

Affected file: internal/config/config.go:44

func ensureConfigDir() error {
    // ...
    if err := os.MkdirAll(configDirPath, 0755); err != nil {

Risk: The ~/.rosactl/ directory is created with 0755 (world-readable, world-executable). While the config file itself is written with 0600 (correct), the directory being 0755 means:

  • Any user on a multi-user system can list the directory contents, revealing the existence of config.json and any other files stored there.
  • On some shared filesystem configurations, world-readable directories can expose metadata about user activity.

The config stores the platform API URL (platform_api_url), which could reveal internal API endpoint addresses to other users on shared systems (CI runners, jump hosts, developer VMs).

What to Mitigate: Change 0755 to 0700 in ensureConfigDir(). This matches the security posture of ~/.aws/ (the AWS CLI config directory).


🟡 MEDIUM — Finding 4: Lambda Container Image URI Example Uses :latest — No Digest Enforcement

Affected file: internal/cloudformation/templates/lambda-bootstrap.yaml:2-8

Parameters:
  ContainerImageURI:
    Type: String
    Description: 'ECR container image URI (e.g., 123456789012.dkr.ecr.us-east-1.amazonaws.com/rosa-regional-platform-cli:latest)'

Risk: The description explicitly gives :latest as an example, and there is no AllowedPattern constraint requiring a digest-pinned URI. Operators following the example deploy with a mutable tag. Combined with the Lambda's IAM privilege escalation path (Finding 1), a supply chain attack on the container image leads to full account admin access.

What to Mitigate:

  • Add AllowedPattern: ^.*@sha256:[a-f0-9]{64}$ to require digest-pinned images.
  • Update the description to explicitly warn against mutable tags.

Triage Guide

Finding Severity Effort Priority
Lambda IAM privilege escalation (IAM wildcard) HIGH Medium Immediate
Lambda unrestricted PassRole + EC2/R53 HIGH Medium Short-term
Config dir world-readable (0755) MEDIUM Low Short-term
Lambda image URI lacks digest enforcement MEDIUM Low Short-term

@openshift-ci

openshift-ci Bot commented May 15, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: rosa-regional-platform-ci
Once this PR has been reviewed and has the lgtm label, please assign jmelis for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@coderabbitai

coderabbitai Bot commented May 15, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are limited based on label configuration.

🚫 Review skipped — only excluded labels are configured. (1)
  • do-not-merge/work-in-progress

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Enterprise

Run ID: 3a3c2b74-e9c1-4d93-962a-db3d936bb8e0

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@openshift-ci

openshift-ci Bot commented May 15, 2026

Copy link
Copy Markdown

Hi @rosa-regional-platform-ci. Thanks for your PR.

I'm waiting for a openshift-online member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work.

Tip

We noticed you've done this a few times! Consider joining the org to skip this step and gain /lgtm and other bot rights. We recommend asking approvers on your previous PRs to sponsor you.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@openshift-ci openshift-ci Bot added the needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. label May 15, 2026
@rosa-regional-platform-ci

Copy link
Copy Markdown
Author

Superseded by #75 (2026-06-15 consolidated audit).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants