Hackers used Qubole's IAM credentials to steal secrets and customer data via forgotten cross-account roles in AWS. How to check accounts and protect yourself.
On November 9, 2026, a team of Wiz researchers (together with Sentra and Mandiant, a Google Cloud unit) published a report on a campaign demonstrating a dangerous class of cloud-infrastructure attacks: the attacker didn't break into companies directly — he entered through "doors" those companies had left open for a third-party vendor.
What happened
Between October 14 and 26, 2026, an unknown attacker used IAM credentials (access keys) from an AWS account linked to the Qubole platform to gain access to the cloud environments of several of its customers. Qubole is a cloud data-processing platform (data lake) owned by Idera. Inside customer AWS accounts it works through cross-account IAM roles.
Having obtained those credentials, the attacker called the sts:AssumeRole API and "tried on" roles that customers had once created to trust the Qubole account. Once inside others' AWS environments, he enumerated resources, collected configurations and secrets, read data from S3 buckets, and checked additional credentials found along the way.
The key point: most of the roles the attacker "tried on" were inactive. The platform had long stopped being used, but the roles themselves were never deleted, and they still trusted the Qubole account. It was these "forgotten doors" the attacker opened.
How Qubole's cross-account access works
For a third-party SaaS platform to work in your AWS account, you typically create an IAM role with a trust policy that lets the vendor's account "assume" that role. A typical policy looks like this:
{
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::<vendor-account-id>:root" },
"Action": "sts:AssumeRole",
"Condition": { "StringEquals": { "sts:ExternalId": "<external-id>" } }
}
An AssumeRole request is accepted if it comes from a trusted account and carries the correct External ID. And here lies a common misconception: many treat External ID as a "password." In fact, per AWS's official documentation, External ID is not a secret. It's just an identifier that helps avoid role confusion (the "confused deputy" attack), but anyone with access to the role can simply see it.
External ID was invented for a different problem. Imagine the same trust role is used by two different vendors or two services. If one is compromised, the attacker could "assume" the role in the other context. External ID simply distinguishes who owns a given request — but it doesn't encrypt access and doesn't replace real authentication. In this attack it played exactly as much of a role as it can: an attacker with role access freely read the needed identifier.
In Qubole's case, Wiz researchers confirmed: every AssumeRole request from the attacker carried a valid External ID and was accepted. The attacker didn't even need to bypass the mechanism — he simply had the right identifier.
Attack timeline
Wiz traced activity back to October 14. The first AssumeRole request came from an IP belonging to the Mullvad VPN service (45.83.220.211). Calls came from AWS account 805246085872 — the one Qubole uses to work with customer roles — and used the IAM user AIDA3W7DIFLYOLTK63SFS. Tellingly: across all investigated environments, Wiz saw no activity from this user other than the attacker's actions.
From October 15, most traffic came from an OVH VPS server (57.129.54.120). On October 18 the attacker began using a second IAM user of the same account — AIDAJYRRH5Y3A7AAJM2HW, which in parallel also carries legitimate Qubole platform traffic. That same day a second Mullvad address (185.209.199.73) quickly "tried on" roles across several victim environments.
Separately, Wiz recorded a second wave of activity from October 8 to 11: there the attacker used not a role but long-lived AWS access keys that customers had once created for Qubole integration. Over a single hour on October 8, he tested all those keys, and in a small number of cases reached environment compromise. The researchers couldn't link the two waves.
What the attacker stole
The sequence was the same across all environments: assume role → call ListBuckets to see what the role can access → ListObjects and HeadObject to enumerate and inspect contents → GetObject to download files. The attacker acted opportunistically: not looking for specific data but reading everything each role could reach, sometimes dumping entire S3 buckets in one session.
Besides data, the attacker hunted credentials:
- pulled secrets from AWS Secrets Manager — including vendor tokens and ExternalIds;
- read decrypted parameters from SSM Parameter Store (monitoring and scanning agent keys);
- collected Lambda function environment variables;
- scraped EC2 instance user data — startup scripts often holding tokens and passwords.
Found credentials were run through the open-source secret scanner TruffleHog, checking victims' own AWS keys, Microsoft Entra ID client secrets, and Okta credentials. The tool called GetCallerIdentity — a request requiring no permissions that simply confirms whether a key works.
Researchers also found a Linux boot image sso_agent.iso on the attacker's server. Per Wiz's hypothesis, it was created to boot remotely on victim machines: after launch, the image sends system and disk information to the attacker's server and awaits commands on port 23458.
How researchers traced the attack
Sentra first noticed the suspicious activity — on several of its customers' environments. The chain of evidence came together because cloud services leave traces even where you don't expect them. The key indicator was encryption logs: whenever an encrypted file is downloaded, the cloud must decrypt it, and each such unlock is recorded with the file name. Matching these records with the attacker's sessions, researchers could pinpoint exactly which files leaked. Files with default encryption leave no such trace, so the real volumes are likely larger.
The second trace was the secrets themselves: every read password or key left its own record, giving a precise list of what to rotate. And through the lens of external trust identities, Sentra narrowed the suspects to one vendor: Qubole was the only external principal with access to most of the source S3 buckets.
Forgotten integrations — the main vulnerability
Technically this attack belongs to the class MITRE ATT&CK describes as T1199 "Trusted Relationship". The essence is simple: by breaching a vendor, the attacker inherits all the access that vendor's customers granted it.
Wiz puts it even more harshly: trusted SaaS-provider principals are "effectively credentials into every customer's environment." One compromised vendor account becomes a key to dozens of organizations.
The most dangerous part is precisely the "forgotten" integrations. Many organizations left trust policies active even after they stopped using Qubole. The role isn't needed by the business, nobody monitors it, but it still lets a foreign account assume it — and these are exactly the roles the attacker used most.
How to check if you were affected
Wiz advises reviewing CloudTrail logs starting October 1 in every AWS account with a Qubole role. Attack signs:
- Account:
AssumeRolerequests whereuserIdentity.accountIdequals805246085872andsourceIPAddressis a non-AWS address. Per Wiz's observations, legitimate Qubole traffic comes only from AWS infrastructure. - IAM principal:
AIDA3W7DIFLYOLTK63SFS— any activity from this user must be investigated (only the attacker used it). - IAM principal:
AIDAJYRRH5Y3A7AAJM2HW— filter for non-AWS source IPs, since legitimate Qubole traffic also flows through it. - IP addresses:
57.129.54.120and2001:41d0:70d:7800::(OVH);45.83.220.211,185.209.199.73,89.37.63.175(Mullvad VPN). Note: Mullvad addresses are shared by many VPN users, so a match alone isn't proof. - Session name: role sessions starting with
quiam-(e.g.,quiam-enum). - User agent: TruffleHog in
GetCallerIdentitycalls from the above IPs. Look for the same user agent in your identity provider's login logs.
If you find traces of compromise, separately check whether your credentials already appear in public leaks — for example, via the free cyberpeople.tech breach checker.
How to protect yourself
Even if you never used Qubole, these rules apply to any third-party SaaS integration in your AWS account:
- Rotate everything the role could access. Change secrets, Parameter Store parameters, and Lambda environment variables. Separately revoke active role sessions: rotating credentials doesn't end already-issued sessions.
- Delete unnecessary roles. If an integration is no longer used — remove the role or drop the vendor account from the trust policy.
- Narrow the principal. Instead of a broad
:root, specify the vendor's specific IAM principal in the trust policy if supported. - Add a request-source condition. Use
aws:SourceIporaws:SourceVpceto restrictAssumeRoleto the vendor's documented network ranges. Per Wiz, in this attack "a source-IP condition alone would have sufficed to block every role we observed." - Enable S3 data events. Management events in CloudTrail record the role assumption and bucket listing, but not object reads. Only CloudTrail data events or S3 server access logs will show which files were actually downloaded.
The general advice: regularly audit external trust relationships and apply least privilege — a role should get access to exactly the resources the vendor needs, and not a byte more.
Conclusion
The attack on Qubole customers is a vivid example that the cloud-services supply chain has long become an independent vector, no less dangerous than direct perimeter breach. The weak point here isn't a code vulnerability but the trust organizations grant third-party vendors — and forget as soon as the service is no longer needed.
While vendors publish no official statements (neither Qubole nor Idera had responded at the time of Wiz's report, and the source of the Qubole credential compromise is undisclosed), the main conclusion for security teams is one: audit all third-party integrations in your AWS account right now. Every forgotten role with a trust policy is a potentially open door that someone else will one day use.
It's worth grasping the scale: if you have even a few SaaS vendors integrated with the cloud, your real attack surface is not just your own systems but the security posture of each of those vendors. Check trust policies, remove extra roles, narrow principals, and add request-source conditions. That's cheaper and faster than investigating a data leak after the fact.