Pentest Copilot's agents ran 119 supported Google Cloud attack-path checks from a Compute Engine service account. We analyzed each run through proof, recovery, and retest.

A Compute Engine VM requests a token. The token belongs to its attached service account. Google returns it, but a protected-object request responds with 403 Forbidden. Authentication succeeded; access did not. An engineer following a false escalation report would change an IAM grant even though no privileged action occurred.
Pentest Copilot is organized into assessment modules. We used its Internal Assessment module for these cloud security checks.
Its agents treat token issuance as sign-in evidence. They report escalation only after the target account completes an action denied to the source account.
Before each run, we approved one project and set the safety rules. The agents stayed inside that project. When a resource met a check's requirements, they ran it without waiting for an operator to choose each action.
For example, a federation exchange returned short-lived Google authority. The agents did not count it as escalation yet. The destination service account first had to complete an action denied to the source account.
We reviewed each complete run. One hundred nineteen Google Cloud checks met the source-to-consequence evidence rule. We grouped them into 34 categories.
| Field | Result |
|---|---|
| Research question | When does one Compute Engine service account become a verified path to stronger identity, runtime execution, protected data, or project impact? |
| Starting condition | Code execution on a VM using its attached service account |
| Unit of analysis | One service-account-to-resource-to-runtime transition |
| Evidence threshold | The target identity or service completes an action denied to the source |
| Recovery threshold | Reversible IAM, workload, data, and network state returns to baseline |
| Coverage | 119 attack paths across 34 vulnerability categories |
The agents read the project and attached service-account email from the local Google metadata endpoint. They do not follow redirects to a substituted endpoint.
The detected project must match the approved project before enumeration begins. The service account attached to the compute resource remains the workload identity throughout the assessment.
| Boundary | Required observation | Failure meaning |
|---|---|---|
| Metadata | Google metadata behavior is present | Machine source is not trusted |
| Project | Metadata project equals approved project | Discovery stops |
| Service account | Attached identity resolves through an authenticated API | Results can be attributed to the workload |
| Resource reference | Project and specific target identifier are valid | Target is rejected rather than repaired or widened |
A human administrator session is excluded. It answers what the administrator can see, not what code on the VM can reach.
Google Cloud discovery crosses many APIs. An empty result can mean the service is disabled, the service account is denied, no matching resource exists, or the request failed. Those states remain separate.
| API result | Interpretation |
|---|---|
| Disabled | Service is unavailable through the current project API |
| Permission denied | Resources may exist, but the workload cannot enumerate them |
| Empty success | Approved query found no matching object |
| Malformed or unexpected failure | Visibility remains unknown |
A denied API does not stop unrelated checks, but the agents never infer a relationship through an API they could not query.
The relationship map connects each VM to its service account and each IAM binding to a specific resource. A federation subject is linked to its target account. GKE workloads, builds, and serverless revisions are separately linked to the identities that execute them.
The federation check begins with a signed assertion from the expected machine identity. The agent sends it to the configured provider. The provider checks the issuer and audience, then maps the subject. Workload Identity Federation exchanges the accepted assertion for short-lived Google authority. A separate permission decides whether the represented workload may impersonate the destination service account.
After the provider accepts the assertion, Google Security Token Service issues federated authority. The configured destination service account must then accept impersonation.
| Stage | Required evidence |
|---|---|
| Source | Assertion belongs to the expected workload |
| Provider | Issuer, audience, and mapped subject are accepted |
| Impersonation | Google resolves the exact target service account |
| Baseline | Source account is denied the selected action |
| Consequence | Target account completes the same action |
| Confidentiality | Assertion and tokens are not published or persisted |
If federation succeeds but the target action fails, the result stops at authentication. It is not privilege escalation.
Several permissions can point toward the same stronger service account but cross different mechanisms.
| Mechanism | Transition | Required proof |
|---|---|---|
| Token creation | Source impersonates target | Target identity plus one newly allowed action |
| Key creation | Source creates temporary authentication material | Exact target authenticates, then material is deleted |
actAs | Source assigns target to a workload | Runtime executes as target |
| Compute update | VM receives a different service account | Guest or API output resolves the replacement |
| IAM policy write | Source changes authorization at a scope | Before-and-after permission delta |
| Tag or condition change | Source changes which requests match | One previously denied request becomes allowed |
These mechanisms are not interchangeable. Token creation can be short-lived; key creation can outlive the source session; actAs needs a workload that accepts the identity; IAM writes change authorization directly.
The agents treated a build or deployment permission as execution only after the resulting workload ran under the claimed service account.
| Runtime path | Functional evidence |
|---|---|
| OS Login or SSH | Intended VM returns its OS and service-account identity |
| Startup script | Proof VM in the approved subnet returns a serial-console marker |
| Managed notebook | Ephemeral kernel resolves its attached identity |
| GKE host mount | Admitted pod reads a non-sensitive marker from the intended node path |
| GKE token | API server accepts the selected pod token and reports its identity |
| Cloud Build | Controlled build runs as the build service account and completes a protected action |
| Cloud Run or Function | Temporary revision processes a marker as the configured runtime account |
| Mutable image | Trusted workload consumes the changed digest and original digest is restored |
A successful deployment API response is not the evidence. Runtime output is.
Secret Manager, Cloud KMS, Cloud SQL, BigQuery, Cloud Storage, disks, backups, logs, and Pub/Sub expose different data models. They share one evidence rule: select one target and retain only enough output to prove the operation.
| Target | Retained evidence |
|---|---|
| Secret Manager | Version and non-reversible fingerprint |
| Cloud KMS | Length and fingerprint of a non-sensitive canary |
| Cloud SQL or BigQuery | Limited authentication or row result |
| Cloud Storage | Object identifier, version, and operation result |
| Disk or image | Marker from a read-only clone or approved launch |
| Pub/Sub | Message fingerprint without acknowledgement or deletion |
| Logs or source package | Expected marker or fingerprint, not raw content |
For a reversible impact check, the agent records the original state, applies one approved change, observes the expected loss of function, restores the resource, and verifies recovery. The agents run destructive actions only when the approved procedure includes a safe recovery path.
Across the Google Cloud runs we reviewed, the agents exercised 119 supported checks. The set includes distinct delegation and workload-execution mechanisms, each with different prerequisites and controls.
IAM Conditions can restrict a binding by resource, time, request attribute, or tag. They can also create escalation paths when a principal controls the attribute on which the condition depends.
To test an IAM condition gap, the agent has the source and target identities attempt the same read against a fixed object generation. The source must be denied before the agent creates the target session through the intended delegation path. The target read stops at the configured byte limit, and the record retains only the generation, byte count, HTTP status, and object digest.
For a condition-weakening or tag-mutation check, the agent records the original policy or tag binding before making the temporary change. The mutation must explain the denied-to-allowed transition. The agent restores the original state only while the live policy still matches its temporary mutation.
The permissions to impersonate a service account, create one of its keys, or attach it to a workload are separate paths.
A short-lived impersonation token proves direct delegation. A temporary key proves durable authentication material and therefore requires deletion and post-delete verification. actAs proves nothing until a workload accepts the target account. A VM replacement path must show the guest or a protected API executing as that service account.
The clearest representation is:
source account -> delegation mechanism -> target account -> protected action
The delegation mechanism determines both prevention and persistence risk.
Build services are attractive because source-level control can become execution under a dedicated build identity. The agent submits a controlled build, resolves the service account used by that build, and requires one protected action denied to the source.
The agents test artifact mutation separately. The responsible agent changes a mutable tag, package, or image to a controlled digest and requires a trusted workload to consume that digest and emit a marker. It then restores and reads back the original digest. If the workload never consumes the changed artifact, the result remains write access rather than a completed supply-chain path.
This distinction prevents a writable registry from being reported as code execution when no consumer relationship is known.
GKE paths cross cloud IAM, the Kubernetes API, and the node:
| Layer | Representative transition | Required evidence |
|---|---|---|
| Google Cloud | Cluster or node-pool control | Change targets the selected cluster and project |
| Kubernetes API | Administrative binding or pod token | API server accepts the intended subject |
| Node | Privileged pod, host mount, or node proxy | Known marker comes from the intended node context |
A pod admitted by the API is not automatically a node compromise. A host-mount path must read an approved marker from the selected node path. A workload-identity path must show that the pod receives the mapped Google service account and can complete its protected action.
For Cloud Run replacement and function-update checks, the agent records the baseline revision or source package, deploys a reproducible temporary version, invokes it, and confirms its runtime identity. For an event check, the agent sends a unique marker through the selected trigger and requires it to reach the intended service; a trigger definition without observed delivery is configuration evidence only.
The agent restores the resource with generation-aware or revision-aware updates. If the deployed state no longer matches its temporary version, it stops and reports drift rather than replacing another release.
Snapshot and image permissions can bypass guest authentication. Before creating a temporary resource, the agent validates the project, zone, disk, and attached source instance. It checks the complete set of required permissions, creates a snapshot and read-only clone, and launches an isolated reader only long enough to retrieve a predetermined marker.
The agent ties every temporary resource name to the proof, polls each operation to completion, and removes the reader, clone, and snapshot in dependency order. It rejects the result if the source disk changed, has an unexpected attachment shape, or falls outside the selected subnet or project.
Shared-image extraction is a related but distinct path: the image is consumed in an approved project, and the agent reads the expected marker without modifying the source image.
Permission to ask Cloud KMS for a signature proves only key use. The agent first submits a non-sensitive assertion for signing, then presents the signed assertion to the intended relying service. The path is established only when that service accepts the assertion as the claimed identity.
The record keeps the key version, algorithm, assertion digest, and relying-service response. It does not keep a reusable assertion. Project moves, quota changes, object deletion, logging changes, key state, and backup impact remain separate checks in the coverage matrix.
| State | Meaning |
|---|---|
| API disabled | The service is unavailable in the measured project |
| Permission denied | Resources may exist, but the workload cannot enumerate them |
| Empty successful response | The scoped query found no matching target |
| Identity token issued | Authentication succeeded; escalation is not yet shown |
| Deployment accepted | Control-plane write succeeded; runtime proof is pending |
| Target action accepted | The path reached its intended consequence |
| Baseline fingerprint restored | The reversible mutation was recovered |
| Concurrent drift detected | Rollback stops and the changed state is reported |
Keeping these states separate prevents a disabled API from appearing empty, a token from appearing as privilege escalation, and a successful deployment from appearing as runtime execution.
| Category | Paths | Measured result |
|---|---|---|
| Classic service authentication | 8 | SFTP, MSSQL, MySQL, RDP, SMB, SSH, WMI, and WinRM acceptance |
| Classic share exposure | 2 | Controlled SFTP and SMB file operations |
| Compute execution | 3 | OS Login/SSH, startup script, and managed notebook |
| Delegation and trust | 5 | Service-account replacement, actAs, project binding, federation, and subject mapping |
| Discovery | 7 | Resource, permission, project, secret, storage, metadata, and foothold context |
| Identity validation | 1 | Caller identity resolution |
| Local secret discovery | 1 | Environment authentication material |
| Managed secrets and keys | 3 | KMS administration, KMS decrypt, and Secret Manager read |
| Metadata identity access | 4 | Container, default account, VM, and application-to-metadata paths |
| Permission enumeration | 1 | Effective reachable actions |
| Permission escalation | 8 | API key, service-account material, HMAC, IAM, primitive role, tag, custom role, and resource policy |
| Database and data services | 6 | IAM database, secret-backed SQL, BigQuery, backup, public database, and stored authentication material |
| Network and exposure | 9 | Administration, egress, peering, public bypass, RDP, WinRM, ingress, load balancer, and DNS |
| Storage exposure | 6 | ACL, authenticated-user, old version, public read/write, and signed URL |
| Deployment automation | 2 | General pipeline and Cloud Build |
| Disk and image exfiltration | 5 | Disk share, image launch, snapshot export/create, and image extraction |
| Hybrid identity bridge | 3 | Private network, federation, and linked database |
| Kubernetes and containers | 7 | Node proxy, admin binding, host mount, image change, privileged pod, pod token, and workload identity |
| Serverless and event execution | 3 | Function, Cloud Run, and event path |
| Audit and telemetry access | 3 | Audit read, log-sink change, and sensitive log values |
| Defense evasion | 5 | Log delivery, audit, flow logs, management bypass, and network protection |
| Impact | 5 | Backup, object, compute, key, and quota outcomes |
| Persistence | 8 | SSH, IAM, application, serverless, access, storage, network, and bootstrap paths |
| Cloud identity initial access | 1 | Application or workload identity is accepted |
| Authentication control bypass | 2 | IAM condition gap and weakening |
| Cross-scope trust | 2 | External identity and cross-project trust |
| Cryptographic signing abuse | 1 | KMS-signed assertion accepted by the relying service |
| Federation persistence | 1 | Reusable or forged certificate authentication |
| Application foothold | 1 | Public application to workload metadata |
| Configuration secret exposure | 2 | VM bootstrap and serverless environment data |
| Deployment history exposure | 1 | Build substitution or retained deployment data |
| Software supply chain | 1 | Mutable package, artifact, bundle, or image |
| Messaging data access | 1 | Pub/Sub message read without deletion |
| Serverless data mining | 1 | Function source package read |
| Total | 119 | 34 categories |
Before its first write, the responsible agent records the project, region or zone, resource name, IAM ETag or resource generation, runtime revision, and temporary resources it expects to create. It also records which denial, runtime response, data request, or control state must be repeated after cleanup.
| Stage | Google Cloud evidence |
|---|---|
| Baseline | Source action is denied or the original revision, policy, object generation, or control state is observed |
| Owned mutation | One binding, condition, tag, service-account attachment, revision, image reference, network entry, or guardrail changes |
| Functional proof | The intended service account, workload, cluster, data service, or relying party accepts the controlled action |
| Conditional rollback | Restoration proceeds only while the live policy fingerprint, generation, revision, and owned resource set match |
| Retest | The temporary identity loses access, the original revision or policy returns, and baseline behavior succeeds |
IAM rollback restores the complete policy with its concurrency control rather than deleting only the visible binding. Temporary service-account keys, HMAC material, federation mappings, custom roles, tags, and conditions are removed and read back. The agent then repeats the target action as the temporary identity and requires a denial while confirming that the original service account still works.
Cloud Run and Functions return to the recorded revision or source package. A fresh invocation must produce the baseline marker and resolve to the original runtime service account. Build and artifact paths restore the original digest, trigger the approved consumer again, and verify that the temporary digest is no longer executed.
GKE cleanup removes only the temporary binding, pod, access path, or workload mapping created for the proof. The API request and node-level marker read are retried and must fail for the temporary subject. Offline disk and image checks delete the isolated reader, cloned disk, and snapshot in dependency order, poll every operation to completion, and verify that the source disk never changed.
Logging, flow-control, security-service, key, quota, project-move, backup, and object-impact checks restore the recorded state before repeating the observation that demonstrated impact. A returned API success is not recovery; the configuration fingerprint, removed authority, and normal baseline behavior must all agree.
A service account should be reviewed through the workloads and services that turn its permissions into action. Restricting impersonation, actAs, IAM condition changes, workload mutation, build identities, and federation mappings breaks the transitions that produced the tested impact.
With project scope and safety constraints fixed, Pentest Copilot's agents handled discovery, delegation, runtime proof, rollback, and post-cleanup retesting without step-by-step operator control. We reviewed the complete evidence chain, including API state, source denial, target identity, runtime consequence, restored policy or resource state, and the final denial. The published paths show what the workload identity actually reached, not what a role name or successful deployment request appeared to imply.