“Confused Deputy” in third-party SaaS integrations: when the problem isn’t your account, but the intermediary

“Confused Deputy” usually doesn’t start with a sophisticated exploit, but with a “trusted” integration that already has keys to get in. You connect a SaaS (monitoring, CI/CD, billing) and grant it a cross-account role or an OIDC federation to do work on your behalf. If that third party doesn’t separate its customers well (tenant isolation) or doesn’t correctly validate the “who requests what,” your account can end up executing actions originating from another organization.

In an enterprise, this usually shows up as “it’s not our fault”: there are no internally compromised credentials, no MFA bypassed, no IAM user with excessive permissions. And yet, there is new infrastructure, unexpected changes, or altered billing. The piece that fails is in the middle: the deputy (the SaaS) is confused and acts for the wrong actor using your permissions.

What went wrong in practice: the CI/CD role that deployed to the wrong account

Realistic scenario: you integrate a third-party CI/CD tool and create a role in your cloud account with deployment permissions (create/update stacks, register images, manage artifact buckets). The tool assumes that role to run pipelines. Everything works… until a developer from another company (another customer of the same SaaS) runs a pipeline and, due to misconfiguration or insufficient validation by the SaaS, that pipeline ends up assuming your role.

The effect is not always an obvious “hack.” It can be a deployment with similar names (same repo template, same stack name), resources in regions you don’t use, or a bucket with artifacts that don’t belong to your SDLC. In the best case, it’s detected by operational noise. In the worst, changes with impact are executed: network routes, IAM policies, secret rotation, or deployments that overwrite environments.

The important part: the attacker doesn’t need your credentials. They just need to be able to convince the SaaS (the deputy) to execute an action in your account. If the SaaS doesn’t “bind” the request to your customer identity, your trust policy becomes an overly generic door.

The root cause: overly broad trust and lack of customer→role “binding”

The pattern repeats: the cross-account role trusts the SaaS provider’s account, and the provider operates for multiple customers within that same account (or a limited set of accounts). If your trust policy only says “I trust the provider account X,” you have delegated customer separation to its internal control. If its control fails, your isolation fails.

In AWS, the typical “binding” is done with ExternalId (and, depending on the case, additional conditions such as aws:PrincipalArn or session restrictions). In OIDC federation (very common in modern CI/CD), the binding is done by validating issuer (iss), audience (aud) and claims that identify the repository/organization/environment. If the provider or your configuration does not pin down those elements, the identity arriving in the cloud is “valid” but not “yours.”

A sign of insecure design in SaaS integrations is when documentation suggests something equivalent to “create a role and trust our account” without strong conditions, or when the customer identifier doesn’t appear anywhere in the role-assumption flow. In corporate environments, that translates into a risk that’s hard to explain… until it happens.

Early signals and how to confirm it without speculating

“Confused Deputy” usually leaves operational traces that look like human errors: resources created by an expected principal (the integration role) but at odd times, in unusual regions, or with names that don’t match your standards. The dangerous part is to quickly attribute it to “someone made a mistake” and not look at the real origin of the request.

In AWS, confirmation relies on CloudTrail: identify AssumeRole events to the provider role, review the userIdentity, the principalId, the sourceIPAddress and the sessionContext. If you see role sessions that can’t be correlated with a pipeline, ticket, or change window, treat it as an incident until proven otherwise. In OIDC integrations, review the claims used for the session and whether the aud corresponds to the correct resource.

  • Assumption events without operational correlation: sessions for the “CI/CD” role appear but there is no associated pipeline execution or planned deployment.

In practice, this forces better traceability: the role should assume sessions with names or tags that allow mapping to a specific job/run. If the provider doesn’t support it, it’s a real limitation that increases the investigation cost.

  • “Foreign” resource patterns: stacks with different naming, buckets with standard policies from another organization, or artifacts with paths that don’t exist in your repositories.

This usually indicates that the action was “valid” for someone, but not for you. It doesn’t prove confused deputy by itself, but it is a clear trigger to review the trust policy and the federation conditions.

How to do it in practice: concrete guardrails (AWS ExternalId and OIDC with iss/aud)

Effective mitigation consists of reducing “blind” trust in the provider and requiring cryptographic proofs or identifiers that only correspond to your customer onboarding. In AWS, the classic control is ExternalId: the SaaS must present a unique value assigned to your tenant when calling STS. Without that value, the assumption must fail.

Example trust policy in AWS for a cross-account role, conditioned by ExternalId (adjust ACCOUNT_ID_SAAS and the real external id):

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::ACCOUNT_ID_SAAS:root" },
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "YOUR-UNIQUE-EXTERNAL-ID"
}
}
}
]
}

Validation: explicitly test that AssumeRole fails without ExternalId and only works with the correct value. Also, periodically review in CloudTrail that AssumeRole events include that expected ExternalId (and that there are no alternative paths to assume the role).

For modern CI/CD with OIDC (for example, GitHub Actions federating against Azure/GCP or AWS), the practical equivalent is to validate issuer and audience and restrict by repository/organization/environment claims. In operational terms: configure the IdP/OIDC provider to accept only the legitimate iss, require a specific aud for your app/resources, and filter by token attributes (for example, repo and branch) so that an identity from another repo/org cannot exchange its token for permissions in your tenant.

  • Pin audiences: the token must be issued for your resource (audience) and not “anything valid.”

This prevents the typical failure where any “well-formed” OIDC token from the platform is accepted to assume permissions. In internal reviews, this is one of the most common findings when integrating quickly and leaving the default condition.

  • Restrict by operational identity: the token must represent exactly the expected repo/organization (and, if applicable, the environment), not just “a workflow.”

In enterprise environments, this greatly reduces the blast radius: even if someone obtains a valid token in their own context, they won’t be able to pass it off as your context. And when a SaaS configuration error happens, the control will fail closed.

Useful add-ons (when they provide real value and don’t break operations) are conditions by the provider’s egress IP or by session tags. The key is not to rely on a single control: ExternalId/OIDC claims for identity, and context restrictions to reduce abuse.

Operations and cleanup: integrations that stay forever (and how to revoke them without stopping the business)

“Confused Deputy” gets worse over time for two reasons: proliferation of integrations and loss of context. Roles created for a proof of concept remain in production; provider accounts get renewed; teams change; and nobody remembers which SaaS needs which permissions. That is the perfect ground for Shadow IT with privileges.

A practice that works in corporate environments is to treat SaaS integrations as assets with a life cycle. It’s not enough to “create the role” once. You have to audit, rotate, reduce permissions, and revoke when it isn’t used. And when it’s revoked, you have to confirm that there are no alternative paths (other roles, other IdPs, old keys) that keep access alive.

  • Annual audit of SaaS integrations: inventory each third-party role/identity, its internal owner, its justification, and its last observed real use.

The point is not to make an excel to comply: it is to cross “last use” (telemetry) with “need” (business process). Many integrations survive out of fear of breaking something, but when evidence of use is requested, it doesn’t exist.

  • Safe revocation: disable first in stages (for example, reduce permissions or limit conditions) and monitor failures before deleting the role/credential.

This avoids silent outages of critical processes. At the same time, it forces the consuming team to explicitly declare the dependency. If nobody complains when you restrict it, it was accumulated debt with privileges.

Recommendations for corporate environments

“Confused Deputy” in third-party SaaS integrations appears when you delegate customer separation to a provider, but your cloud accepts requests only because they “come from the provider account.” Day to day, it shows up as changes made by an expected role, but without correlation to your operations.

In practice, defense comes down to tying each integration to your customer identity: ExternalId in AWS cross-account roles and, in OIDC flows, validate iss and aud and restrict by claims that identify your repo/organization/environment. Complement with contextual conditions (IP, tags) when they are sustainable and verifiable.

Finally, the control that most reduces risk in the medium term is operational: periodic auditing of integrations and cleanup of third-party roles/identities that are no longer used. In corporate environments, what isn’t reviewed becomes permanent, and what is permanent ends up being the entry point.


Interested in Cloud Security?

Technical analysis, hands-on labs and real-world cloud security insights.

Privacy policy