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

# Containers

> Scan container images for vulnerable packages, secrets, and misconfigurations

export const ScarfPixel = () => <img referrerPolicy="no-referrer-when-downgrade" src="https://static.scarf.sh/a.png?x-pxid=831669b6-b4bd-42cb-8832-2122c03e1d5f" alt="" width="1" height="1" style={{
  position: "absolute",
  width: 0,
  height: 0,
  opacity: 0,
  pointerEvents: "none"
}} />;

<ScarfPixel />

With Containers, you connect a registry, add images, and scan each image for vulnerable packages, malicious packages, secrets, misconfigurations, and outdated base images. Strix identifies an image by its digest, so a scan always applies to one immutable image.

Containers is part of the Enterprise plan. Every request in this guide returns `403` with the code `enterprise_plan_required` on other plans.

## How a scan works

1. Strix resolves the image reference to a manifest digest and a platform.
2. Strix pulls the image layers with the registry credential on the trusted orchestrator. The credential never enters the scan sandbox.
3. The scan sandbox receives the image as a read-only OCI layout and runs the package, secret, and configuration checks.
4. Strix stores each finding in the same vulnerability list that the rest of the workspace uses. Findings that appear in a new scan of the same image keep their history. Findings that no longer appear are marked as fixed.

Strix stores only a masked value or a SHA-256 fingerprint for a secret finding. Strix does not store the secret value.

## Connect a registry

Every image belongs to a registry connection. Create the connection first. For a public registry, leave the credential fields empty.

```bash theme={null}
curl -X POST "https://app.strix.ai/api/v1/containers/registries" \
  -H "Authorization: Bearer <YOUR_API_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
    "provider": "generic",
    "registry_host": "registry.example.com",
    "label": "Production registry",
    "auth_kind": "basic_token",
    "username": "strix-readonly",
    "secret": "<REGISTRY_TOKEN>"
  }'
```

Every registry uses the same OCI Distribution API. The `provider` field selects the host rules and the credential shape:

| `provider` | `registry_host` | `auth_kind` | Credential |
| - | - | - | - |
| `generic` | Any registry host, for example Harbor, Nexus, Artifactory, Quay, or GitLab | `basic_token` or `none` | `username` and `secret` |
| `dockerhub` | Fixed to `docker.io` | `basic_token` or `none` | Docker Hub `username` and an access token in `secret` |
| `ghcr` | Fixed to `ghcr.io` | `basic_token` | GitHub `username` and a personal access token with the `read:packages` scope in `secret` |
| `gar` | A regional Artifact Registry host, for example `us-docker.pkg.dev` | `basic_token` | The service account key file (JSON) in `secret`. Omit `username`. Strix sets it to `_json_key`. |
| `ecr` | The private registry host, for example `123456789012.dkr.ecr.us-east-1.amazonaws.com` | `aws_assume_role` | `aws_role_arn`. Omit `username` and `secret`. |
| `acr` | The login server, for example `acme.azurecr.io` | `basic_token` | Service principal application ID in `username` and its secret in `secret` |

### Amazon ECR

Strix stores no AWS credential for an Amazon ECR registry. Strix assumes the IAM role in `aws_role_arn` with the external ID of your workspace, then calls `ecr:GetAuthorizationToken` to get a registry password. Strix repeats this on every verification, tag resolution, and pull. The password lives for 12 hours and Strix does not store it.

In the dashboard, **Set up the role** opens a CloudFormation quick-create link that creates the role with the trust policy and the read-only actions filled in. Then paste the role ARN into the dialog.

To create the role by hand, call `GET /containers/registries/ecr-setup` to get the values that the role needs:

* `external_id`: the value that the trust policy of the role must require in the `sts:ExternalId` condition.
* `strix_account_id`: the only AWS account that the role must trust.
* `role_name`: the role name that the CloudFormation template creates.
* `quick_create_url`: a CloudFormation quick-create link that creates the role, or `null` if this server does not host the template.
* `actions`: the ECR actions that the role needs if you create the role by hand.

Trust policy:

```json theme={null}
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": { "AWS": "arn:aws:iam::<strix_account_id>:root" },
    "Action": "sts:AssumeRole",
    "Condition": { "StringEquals": { "sts:ExternalId": "<external_id>" } }
  }]
}
```

Permissions policy:

```json theme={null}
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": [
      "ecr:GetAuthorizationToken",
      "ecr:BatchCheckLayerAvailability",
      "ecr:BatchGetImage",
      "ecr:GetDownloadUrlForLayer",
      "ecr:DescribeImages",
      "ecr:DescribeRepositories"
    ],
    "Resource": "*"
  }]
}
```

The role must be in the AWS account and the AWS partition that own the registry. AWS credentials do not work across partitions, so Strix Cloud connects registries in the commercial `aws` partition only. A self-hosted deployment can connect registries in AWS China (`amazonaws.com.cn`, roles `arn:aws-cn:iam::…`) or AWS GovCloud (roles `arn:aws-us-gov:iam::…`) when its Strix principal is in that partition and `STRIX_AWS_PARTITION` names it. The quick-create link opens the commercial AWS console, so create the role by hand in those partitions. If the trust policy does not allow the Strix account with the external ID, the connection fails with the status `disconnected` and an error that names the role.

### Google Artifact Registry

Create a service account with the **Artifact Registry Reader** role, then create a JSON key for it. Send the full key file in `secret`. Strix checks that the file is a `service_account` key with a `client_email` and a `private_key` before Strix stores it.

Strix identifies the connection by the registry host and the `client_email` of the key. You can connect more than one service account to the same regional host. Strix rejects a second connection with the same host and the same service account.

Strix encrypts the `secret` value and never returns it. Strix verifies the connection when you create it. Call `POST /containers/registries/{registryId}/verify` to check the connection again.

**Required scope:** `containers:write`

Workspace admins and analysts can create, verify, or delete a registry. Members with an asset-scoped role cannot change registries or images, because registries and images have no target, tag, or business-unit labels.

## Add an image

```bash theme={null}
curl -X POST "https://app.strix.ai/api/v1/containers/images" \
  -H "Authorization: Bearer <YOUR_API_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
    "registry_id": "<REGISTRY_ID>",
    "reference": "acme/api:1.4.2",
    "platform": "linux/amd64",
    "scan": true
  }'
```

The `reference` field accepts `name:tag` or `name@sha256:<digest>`, without the registry host. The `registry_id` field is required and must name a connected registry. Set `platform` to `null` to use `linux/amd64`. Strix stores the platform on the image. A later scan uses the stored platform if the scan request does not specify a platform.

Set `scan` to `true` to start the first scan when the image is added. The default is `false`. The response contains the stored image, the resolved digest, and the first scan when `scan` is `true`. If the first scan cannot start, the response contains a `scan_error` message and the image stays in the inventory.

**Required scope:** `containers:write`

Workspace admins and analysts can add, update, scan, and delete images.

### Watch tags

Set `watch_tags` to a tag pattern when you add an image, or change it later with `PATCH /containers/images/{imageId}`. Set `watch_tags` to `null` to stop watching tags.

## Start a scan

```bash theme={null}
curl -X POST "https://app.strix.ai/api/v1/containers/images/<IMAGE_ID>/scans" \
  -H "Authorization: Bearer <YOUR_API_TOKEN>"
```

If the request has no `tag`, the scan resolves the tag from the latest scan. If the image has no tag, the scan resolves the digest from the add request. If the request has no `platform`, the scan uses the platform stored on the image.

Each image has one queued or running scan at a time. A second request returns `409` while that scan runs. List the scan history with `GET /containers/images/{imageId}/scans`.

A scan can have a cost limit (on self-hosted deployments, `CONTAINER_SCAN_MAX_BUDGET_USD`). If a scan reaches the limit before the analysis is complete, the scan completes with `stop_reason` set to `budget_exceeded`. If the model provider limits the run, `stop_reason` is `rate_limited`. Strix keeps the findings that the scan filed before the stop. Strix does not mark findings as fixed after a stopped scan. The scan history shows the scan as **Stopped early**.

**Required scope:** `containers:write`

## Read findings

```bash theme={null}
curl "https://app.strix.ai/api/v1/containers/images/<IMAGE_ID>/findings?type=secret&state=open" \
  -H "Authorization: Bearer <YOUR_API_TOKEN>"
```

Filter with these query parameters:

* `type`: `known_vulnerability`, `malicious_package`, `secret`, `misconfiguration`, or `base_image_outdated`
* `severity`: one severity level
* `state`: `open`, `fixed`, or `ignored`

Each finding contains the layer digest and the file path when Strix knows them. A package finding also contains the package name, the installed version, and the fixed version when one exists.

A secret finding also contains a `verification` verdict, the `verified_by` explanation, and `verified_at`:

* `active`: the credential's own provider accepted it. Rotate it now.
* `inactive`: the provider rejected it. The credential is revoked or rotated.
* `valid_unverified`: an offline proof succeeded, for example a private key that signs and verifies, but there is no provider to ask.
* `unverified`: Strix could not prove or disprove that the credential is real. `verified_by` says what Strix checked.

Strix checks a credential only against its own provider and only with read-only calls. A network or provider failure never produces `inactive`. Strix does not file example, fixture, or placeholder values.

**Required scope:** `containers:read`

## Read the software bill of materials

```bash theme={null}
curl "https://app.strix.ai/api/v1/containers/images/<IMAGE_ID>/components" \
  -H "Authorization: Bearer <YOUR_API_TOKEN>"
```

The response lists the packages of the latest completed scan with the package URL, the ecosystem, the license, and the layer that added the package. Set `scan_id` to read the components of an earlier scan.

To download the same inventory as a standard document, request the export route with `format=spdx` or `format=cyclonedx`:

```bash theme={null}
curl "https://app.strix.ai/api/v1/containers/images/<IMAGE_ID>/sbom?format=cyclonedx" \
  -H "Authorization: Bearer $STRIX_API_KEY" \
  -o image-sbom.json
```

The route returns an SPDX 2.3 or a CycloneDX 1.6 JSON file for the latest completed scan. Set `scan_id` to export an earlier scan. The dashboard uses the same route for the **Export SBOM…** menu on the SBOM tab.

`GET /containers/images/{imageId}` returns the image with its scans, layers, image configuration, findings, and components in one response. `GET /containers/summary` returns the workspace counts of images, critical findings, reachable findings, and secrets.

**Required scope:** `containers:read`

## Delete an image or a registry

```bash theme={null}
curl -X DELETE "https://app.strix.ai/api/v1/containers/images/<IMAGE_ID>" \
  -H "Authorization: Bearer <YOUR_API_TOKEN>"
```

When you delete an image, Strix closes its open findings. When you delete a registry, Strix deletes every image of that registry and closes their findings. If a scan of an affected image is queued or running, both requests return `409`. Wait until the scan finishes, or cancel the scan, and then send the delete request again.

**Required scope:** `containers:write`


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