> ## Documentation Index
> Fetch the complete documentation index at: https://docs.plerion.com/llms.txt
> Use this file to discover all available pages before exploring further.

# How GCP workload scanning works

> Step-by-step mechanics of each GCP workload scanning flow, the identities involved, encrypted disks, cleanup, and limits

With **[GCP workload scanning](/guides/integrations/gcp/workload-scanning/overview)**, Plerion scans workloads without installing anything on them. Compute Engine workloads are scanned from a copy of their disk. Cloud Run services and Cloud Functions are scanned from the image or source they run. Every flow runs inside the scanning project in your own organization and deletes what it created when it finishes.

Every GCP API call below is made by the **tenant service account**, reached through the same keyless [Workload Identity Federation](https://cloud.google.com/iam/docs/workload-identity-federation) chain the GCP organization integration uses for posture scanning.

***

## When scans run

Workload scanning has no schedule of its own. After each project's posture scan completes, whether scheduled or started with `Scan now`, Plerion starts a workload scan run for that project covering every enabled workload type. On the default daily schedule that means one workload scan per project per day.

Before enumerating anything, each run checks four organization policy constraints against the scanning project. A blocking result fails the run for that project rather than producing a silent empty result. The run shows as failed on the project's **Workload scans** tab, and the constraint that blocked it is recorded in Plerion's logs. See [Prerequisites](/guides/integrations/gcp/workload-scanning/prerequisites#organization-policies) for the constraints and what to change.

Each run's status (in progress, completed, failed, or timed out) appears on the project's **Workload scans** tab. If any scanner VM in a run fails, the whole run is recorded as failed, even if other targets in it were scanned.

***

## Compute Engine instances

<Steps>
  <Step title="Snapshot the boot disk">
    Plerion creates a snapshot of the instance's boot disk in the project the instance lives in. A snapshot is taken out of band, so the running workload isn't paused or slowed. The copy is crash-consistent.
  </Step>

  <Step title="Create a scan disk in the scanning project">
    Plerion creates a disk from the snapshot inside the scanning project, in the same region as the instance. The disk inherits the snapshot's size.
  </Step>

  <Step title="Boot a scanner VM">
    A scanner VM boots in the scanning project and attaches the scan disk read-only. When your organization's [image policy](/guides/integrations/gcp/workload-scanning/prerequisites#organization-policies) allows it, the VM boots from Plerion's pre-built public image (project `pln-public-artifacts`, image family `plerion-appliance`), which already has the scanning toolchain installed. Otherwise, it boots Google's public Ubuntu 22.04 image and installs a checksum-pinned scanning toolchain at startup. Scanning works the same way regardless of which image it boots from; the pre-built image only makes scans start faster. One scanner VM handles up to 10 scan targets in a run.
  </Step>

  <Step title="Scan">
    The scanner VM mounts the disk and scans it for vulnerabilities, a software bill of materials (SBOM), and (if enabled) secrets. It makes no GCP API calls of its own.
  </Step>

  <Step title="Upload results">
    The scanner VM uploads results to Plerion over an authenticated, time-limited upload link that authorizes result uploads only. Findings leave your organization. Disk contents don't.
  </Step>

  <Step title="Clean up">
    Plerion deletes the scan disk, the scanner VM, and the snapshot.
  </Step>
</Steps>

Only instances in the `RUNNING` or `TERMINATED` (stopped) state are scanned, and only their boot disk is scanned.

***

## Compute Engine custom images

A custom image has no running disk to snapshot, so Plerion creates the scan disk **directly from the image** in the scanning project and skips the snapshot step. Everything else matches the instance flow above: same scanner VM, same read-only attach, same upload, and cleanup deletes the disk and VM. Nothing is created in the project that owns the image.

Plerion scans every custom image a project owns that is in the `READY` state, whether or not anything has booted from it, so a golden image is checked before your fleet is built from it. Findings attach to the image itself and are kept separate from any instance booted from it, because an instance can diverge from its image the moment it is patched.

A custom image is a global resource, so it has no region to match. Plerion runs the scan in the first region listed in your **Workload regions** setting. If that setting is empty, it uses a region the same project's instance scans already use. Otherwise, it uses `us-central1`.

***

## Compute Engine managed instance groups

A managed instance group can run hundreds of identical members, so Plerion samples instead of scanning each one.

<Steps>
  <Step title="List the group's members">
    Plerion reads the group's authoritative member list from the Compute Engine API and drops members that are being deleted or don't exist yet.
  </Step>

  <Step title="Skip GKE node pools">
    A group whose members carry the `goog-gke-node` label belongs to a GKE node pool. Plerion skips it at the group level. Its nodes stay covered as ordinary Compute Engine instances.
  </Step>

  <Step title="Group members by boot image">
    Plerion reads each member's boot disk to find the image it was created from and groups members that share an image. A group mid-rolling-update, running two image versions, produces two groups. Members whose boot disk has no recorded source image form one extra group.
  </Step>

  <Step title="Pick one sample per image">
    From each image group Plerion picks one member, preferring a running member over a stopped one and breaking ties by name, so the same unchanged group samples the same member every run. A group is capped at 10 samples per run.
  </Step>

  <Step title="Scan each sample and merge">
    Each sample goes through the instance flow above. Plerion merges the samples into one scan record for the group, labels each sample's findings with the image it came from, and attaches the findings to the group.
  </Step>
</Steps>

While managed instance group scanning is on, members of a scanned group are no longer scanned or reported as standalone instances. Managed instance group scanning needs no additional permission. Turning it on takes effect on the next run without re-running the access command.

***

## Cloud Run services and Cloud Functions (2nd gen)

A Cloud Run service runs a container image, and a 2nd gen function is a Cloud Run service underneath, so both are scanned the same way. The image for a 2nd gen function is the one Google built when it deployed the function, stored in the `gcf-artifacts` repository in your project.

<Steps>
  <Step title="Resolve the serving image digest">
    Plerion reads the service's serving revisions (the latest ready revision and any revision receiving traffic) and takes the exact image digest each one runs. The revision already records the digest, so no registry lookup is needed and a mutable tag such as `:latest` is never trusted. Every container in the revision, including sidecars, is scanned.
  </Step>

  <Step title="Run a Cloud Run job in the scanning project">
    Plerion starts an execution of the standing image scan job for that region (`plerion-scan-artifact-<region>`), passing the digest as a per-execution override. The job runs as the **artifact-scanner service account**, with 1 vCPU and 2 GiB of memory, and fetches its own registry token from the metadata server at runtime. No credential is written into the job definition.
  </Step>

  <Step title="Pull and scan">
    The job pulls the image from your Artifact Registry and scans it for vulnerabilities, an SBOM, and (if enabled) secrets.
  </Step>

  <Step title="Upload results and delete the execution">
    The job uploads results over the same kind of time-limited upload link the scanner VM uses, bound to the digest it was launched to scan. Plerion then deletes the execution.
  </Step>
</Steps>

Nothing is created in the project that owns the service or function. Each scan appears in your console as one execution of the standing job in the scanning project, with the pull and scan visible in the execution's logs.

***

## Cloud Functions (1st gen)

A 1st gen function is deployed from a source archive, not a container image, so Plerion downloads that source and scans it.

<Steps>
  <Step title="Ask Google Cloud for a download link">
    Plerion requests a short-lived download link for the function's currently deployed source. The link is never written into the job definition, the execution record, or Plerion's logs.
  </Step>

  <Step title="Download and unpack in a Cloud Run job">
    An execution of the standing source scan job for that region (`plerion-scan-source-<region>`) downloads the archive and unpacks it inside the job's container, which has no persistent disk. The job runs as the **source-scanner service account**, with 1 vCPU and 4 GiB of memory. Archives over 100 MB compressed or 500 MB unpacked are skipped.
  </Step>

  <Step title="Scan">
    The job scans the source for dependency vulnerabilities, an SBOM, and (if enabled) secrets. Findings attach to the same Cloud Functions asset a 2nd gen function's scan would, so both generations appear in the same place.
  </Step>

  <Step title="Upload results and delete the execution">
    The job uploads results over a time-limited upload link bound to the function and source version it scanned. Plerion then deletes the execution.
  </Step>
</Steps>

Dependency findings need the function's dependencies pinned or locked in the deployed source. See [Coverage](/guides/integrations/gcp/workload-scanning/coverage#cloud-functions-1st-gen-dependency-findings-need-pinned-versions).

***

## The identities involved

| Identity | What it does | What it can reach |
| - | - | - |
| **Tenant service account** | Every GCP API call: snapshots, scan disks, scanner VMs, member and revision lookups, job executions, cleanup | The org-level custom roles and the scanning project's `PlerionWorkloadScanCompute` role. Revocable at any time by deleting the workload identity pool in your Plerion service project |
| **Scanner VM service account** (`plerion-scanner@<scanning-project>.iam.gserviceaccount.com`) | Runs the scanner VM | **No IAM roles.** The VM receives a mounted disk and an upload token; a compromised VM yields one scan disk and the ability to upload results, nothing else |
| **Artifact-scanner service account** (`plerion-scanner-artifact@…`) | Runs the image scan job | One org-wide role, `PlerionWorkloadScanArtifactPull`: read and pull container images. It can read any image in your organization while Cloud Run or Cloud Functions (2nd gen) scanning is on |
| **Source-scanner service account** (`plerion-scanner-source@…`) | Runs the source scan job | One org-wide role, `PlerionWorkloadScanFunctionSourceRead`: download 1st gen function source. It can read any 1st gen function's deployed source in your organization while that type is on |

The three scanner identities are separate, so compromising one grants none of the others' access. See [Access and permissions](/guides/integrations/gcp/workload-scanning/access-and-permissions) for every permission.

***

## Encrypted disks and images

* **Customer-managed encryption keys (CMEK)**: the snapshot keeps the source disk's key, but the scan disk Plerion creates in the scanning project uses **Google-managed encryption**. Plerion creates it without your key. For the minutes the scan disk exists, Google's key protects it rather than yours. It is deleted at the end of the scan. The same applies to a scan disk created from a CMEK-protected custom image.
* **Customer-supplied encryption keys (CSEK)**: Plerion has no way to supply your key, so CSEK-encrypted disks are skipped.

***

## Cleanup and the sweeper

Every resource Plerion creates for a scan is labeled `owner=plerion`, plus the tenant, integration, and execution that own it. Snapshots, scan disks, and scanner VMs are also named with a `plerion-scan-` prefix. Cleanup runs at the end of every scan, whether it succeeded or not. A separate sweeper runs every hour in the scanning project and removes any Plerion-labeled resource older than 24 hours, so an interrupted scan can't leave resources behind for long. Because the scanning project is yours, you can also delete any leftover resource yourself.

***

## Limits

| Limit | Value |
| - | - |
| Scanner VM machine type | `e2-standard-2`, or `e2-highmem-4` when **Sensitive data** is on |
| Scanner VMs per scan run, per project | Up to 10, within the scanning project's regional quotas |
| Scan targets per scanner VM | Up to 10 |
| Disk scan run timeout | 12 hours, after which the run is torn down and recorded as timed out |
| Image or source scan timeout | 15 minutes per job execution, 30 minutes for the run |
| Custom image size | Images larger than 2048 GB are skipped |
| Managed instance group samples | 10 per group per run |
| 1st gen source archive | 100 MB compressed, 500 MB unpacked |
| Workload regions | Up to 16 |

***

## Next steps

* [Access and permissions](/guides/integrations/gcp/workload-scanning/access-and-permissions)
* [Coverage](/guides/integrations/gcp/workload-scanning/coverage)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.