An attack path is only as good as its last hop. “An internet-facing service can reach a storage bucket” is interesting; “an internet-facing service can reach the bucket that holds 40,000 card numbers” is an incident waiting to happen. Getting from the first sentence to the second needs two things most organizations only have for one cloud, if at all: what each identity can really do, and what each data store really holds.

In short

  • Identity analysis now covers AWS, Azure and Google Cloud, folding every role assignment and policy into the effective permissions of each user, role, service principal and service account.
  • It finds the escalation routes, not just the admins: identities that can assign themselves more, act as other identities, mint tokens or rewrite their own permissions.
  • Data-store discovery and opt-in sampling decide where paths end. Bounded sampling of object stores, with checksum-validated detectors, marks stores sensitive.
  • Counts, never values. InsightFortify records how many card numbers or national IDs it saw, never the matches themselves.
  • Paths are computed per cloud and never cross clouds: an Azure identity is never assumed to reach a Google bucket.

The situation

In this illustrative case, a company runs its customer portal on Azure App Service, its analytics on Google Cloud and its payments platform on AWS. Each cloud team reviews its own permissions once a year. Nobody owns the question “which internet-facing workload, in any cloud, can reach regulated data?” The data protection officer has a spreadsheet of where personal data is supposed to live, last updated before two migrations.

Industry
data

Industry breach reports consistently list stolen or misused credentials among the most common ways attackers get in, and cloud-provider research has repeatedly found that most permissions granted to cloud identities are never used.

Sources: Verizon Data Breach Investigations Report (2024 and 2025 editions); Microsoft, State of Cloud Permissions Risks (2023). Figures vary by edition and method.

TODAY Three consoles, one spreadsheet

Permissions reviewed per cloud, per team, once a year. Sensitive data located by asking people. Attack paths drawn on a whiteboard after an incident.

WITH CIEM + DSPM One identity model, data evidence, computed paths

Effective permissions and escalation routes for every identity in all three clouds, data stores classified by sampling, and paths recomputed after every scan.

Identities: what they can really do

CloudWhere permissions come fromWhat counts as administratorEscalation routes found
AWSAttached and inline policies, groups, trust policiesFull control of the accountPassRole with compute, policy edits, credential creation and similar
AzureRole assignments and role definitions (built-in and custom, notActions carved out), groups folded into membersOwner, or Contributor plus User Access Administrator, at subscription scope or aboveAssigning roles, editing custom roles, VM run-command with a managed identity, attaching identities, Key Vault access policies, App Service code, Automation, deployment scripts, risky Graph app permissions
Google CloudIAM policies at project, folder, organization and resource levelOwnerToken minting, key creation, signing, setIamPolicy, custom-role edits, actAs with compute, Functions or Cloud Run, Cloud Build, Deployment Manager, instance metadata

Each identity also gets a blast radius — the inventoried resources its permissions reach — and, where usage data is available (AWS access advisor, the Azure Activity Log, the GCP IAM recommender), a least-privilege starting point built from what it actually did. A principal with several escalation routes gets one finding listing them all, rather than one alert per route.

An identity in InsightFortify: its blast radius, escalation routes and a least-privilege policy suggestion
An identity. What it can reach, how it could escalate, who can assume it, and a least-privilege starting point.

Data: what the stores actually hold

The cloud inventory already lists every data store — S3, RDS, DynamoDB, Redshift and Secrets Manager on AWS; Storage, SQL, Cosmos DB, Synapse and Key Vault on Azure; Cloud Storage, BigQuery, Cloud SQL, Spanner and Secret Manager on Google Cloud. Discovery tags them as data stores. What it cannot tell you is what is inside.

Sampling answers that, and it is designed around a data protection officer’s concerns:

  • Opt-in per account. Off until a security lead turns it on.
  • Bounded. At most N objects and M kilobytes of text per object, read through the account’s own identity.
  • Validated detectors. Card numbers need a valid issuer prefix and Luhn checksum, IBANs the mod-97 check, Aadhaar numbers the Verhoeff check; emails and phone numbers need several hits; secrets cover cloud keys, private keys and common tokens.
  • Counts only. The result is “3 card numbers, 40 email addresses”. No matched value is ever stored or displayed; uploaded results with unknown detectors or non-numeric counts are discarded.
  • Air-gapped accounts can run the sampling script where the data is and upload only the counts.
sequenceDiagram participant Lead as Security lead participant IF as InsightFortify participant W as Worker participant S as Object store Lead->>IF: enable sampling for acme-gcp, 50 objects, 64 KB each IF->>W: after the next cloud scan W->>S: read a bounded sample with the account identity S-->>W: text objects W->>W: run detectors with checksums W-->>IF: counts only - credit_card 3, email 40 IF->>IF: mark store sensitive, data class PCI IF->>IF: raise finding if the store is public IF->>IF: rescore findings and recompute attack paths

Sampling never stores a matched value. The store is marked sensitive and the paths that reach it are re-evaluated.

The Data page in InsightFortify: data stores across AWS, Azure and Google Cloud with exposure, sensitivity and what sampling found
Data stores across three clouds. Sampling found card numbers and email addresses in one public bucket; counts only.

Where identity and data meet: the attack path

flowchart LR A["Internet"] --> B["Cloud Run service api
accepts unauthenticated traffic"] B --> C["Runs as
api-runner service account"] C --> D["Can read
acme-customer-exports"] C --> E["Can read
acme-public-assets"] E --> F["Sampling found
card numbers and emails"] style B fill:#fee2e2,stroke:#ef4444 style F fill:#fee2e2,stroke:#ef4444

From our demo Google Cloud account: a public workload, its service account, and the stores it can read, one of them now known to hold card data.

Attack paths in InsightFortify across AWS, Google Cloud and Azure, each ending at sensitive data
Three paths, three clouds. Each is computed within its own cloud and ends at stores marked sensitive.

Sampling only ever marks a store sensitive, never unmarks it, so a person’s judgement is not overridden by a sample that happened to miss. Two findings come straight from the data: sensitive data in a public store (critical), and credentials stored in a data store (high).

A first month with cross-cloud identity and dataIllustrative sequence
1
Connect each cloud read-onlyCloud teams

AWS role, Azure service principal (Reader), GCP service account (Viewer, Security Reviewer); or upload exports.

2
Review administrators and escalation routesAppSec lead

Start with identities that are both internet-reachable and can escalate.

3
Mark known sensitive storesData owners

Manual marks first: they are authoritative and never undone by sampling.

4
Enable sampling on one accountSecurity lead with DPO

Agree object and size limits first; counts only are stored.

5
Work the attack pathsCloud and app teams

Fix any one hop: the vulnerability, the exposure, the permission or the data location.

Limits, stated plainly

The Azure and Google Cloud collectors are built to the public API references and tested against mocked responses; they have not yet been run against a customer tenant. Azure deny assignments and GCP IAM conditions are not applied, so effective permissions can be over-reported; GCP folder and organization bindings are applied to every resource in the account. Sampling covers object stores only; databases are discovered, and their classification can be uploaded. Detectors are patterns with checksums, not a trained classifier.

Escalation routes, explained

The most dangerous identities are often not the administrators everyone already watches. They are the ones that can make themselves administrators. A few illustrative routes, one per cloud:

CloudRouteWhy it matters
AWSiam:PassRole plus permission to start computeLaunch a workload that runs as a more powerful role and act through it
AzurePermission to write role assignments at subscription scopeGrant itself Owner; Contributor alone does not include this
Google Cloudiam.serviceAccounts.actAs with permission to deploy to Cloud RunRun code as a service account with broader access than its own

Each route is raised once per identity, listing every route it has, with the actions involved. The fix is usually narrow: remove one permission, or scope it to specific resources, rather than rebuilding the role.

Working with the data protection officer

Data sampling touches personal data, so it needs agreement before it is switched on. The conversation is easier when the design answers the usual questions up front:

  • What is read? A bounded sample: a fixed number of objects per store and a fixed number of kilobytes of text per object. Binary files are skipped.
  • What is kept? Counts per detector and the number of objects and bytes read. No matched value is stored, logged or shown.
  • Who decides? Sampling is off by default and switched on per cloud account by a security lead.
  • Can it run without giving InsightFortify access? Yes: the sampling script runs where the data is, and only the counts are uploaded.
MetricWhat good looks like
Identities that are both internet-reachable and can escalateFalling to zero
Unused identities older than 90 daysRemoved or disabled
Public data stores with sensitive dataZero
Attack paths ending at sensitive dataEach one owned and closing within its SLA

Why per-cloud boundaries matter

It is tempting to draw one big graph across every cloud and let paths go wherever the edges lead. That produces impressive diagrams and misleading conclusions. An Azure managed identity cannot read a Google Cloud bucket because both are marked sensitive; it would need credentials stored somewhere it can reach, and that is a different finding (credentials in a data store) with its own evidence.

InsightFortify therefore computes reach per cloud: Azure permissions are matched against Azure resource ids and their scope ancestry, Google Cloud permissions against the resource and its project. A path never crosses a cloud boundary on assumption. Where credentials genuinely bridge two clouds, the credential finding and the path in each cloud together tell the story, and each can be fixed independently.

The same caution shapes how effective permissions are reported. Because Azure deny assignments and Google Cloud IAM conditions are not yet applied, the analysis can report a permission that a deny or a condition removes. We would rather over-report and let a cloud engineer dismiss a finding with a reason than under-report an escalation route.

What it means for each reader

For the CISO

One answer across three clouds to “which public workloads can reach regulated data?”

Sampling that stores counts, not values, is a design your data protection officer can approve.

For the AppSec lead

Prioritise identities that are both reachable from the internet and able to escalate.

Use least-privilege suggestions as a starting point, then test them; they come from observed usage.

For the board

Attack paths end at the data that matters, so the risk number reflects business impact, not resource counts.

Multi-cloud no longer means three partial pictures.

An attack path ends at data. Know what the data is, and who can reach it, in every cloud you run.

Effective permissions and escalation routes on one side, evidence of what the stores hold on the other, joined after every scan.

Keep reading