Skip to content

Troubleshooting

Start from the verdict or the message you see. The quoted text on this page is what the CLI prints.

The scanner passes cloud SDK errors through without rewording them. A check that hits a denied call shows the provider's own error inside its summary, such as An error occurred (UnauthorizedOperation) from AWS, an HTTP 403 from Google, or access denied reading <path> from Azure. There's no --verbose or --debug flag; the check summary is the diagnostic.

A check says SKIP

SKIP means not assessed. The check didn't run. The summary says why.

Summary Cause Fix
No instance ID specified; skipping check. (and the same for bucket, KMS key, secret ARN, parameter path, EFS file system, DynamoDB table and DB instance) The scan wasn't given that target. Pass the matching option. Scan inputs maps every check to its options.
Need --gcp-instance, --gcp-zone, and --gcp-project; skipping check. GCP VM checks need all three. Pass all three.
Need --azure-subscription, --azure-resource-group and --azure-vm; skipping check. Azure VM checks need all three. Pass all three.
Need --azure-key-vault and --azure-key; skipping check. The Secure Key Release check needs the vault and the key. Pass both.
Need --instance-id and --pcr-baseline; skipping check. ENCLAVE-05 compares running PCRs with a baseline. Pass --pcr-baseline baseline.json.
No --attestation-doc supplied; skipping check. NITRO-ATT-02 and NITRO-ATT-03 read a captured attestation document. Pass it with --nitro-attestation-doc (the message names the option without its nitro- prefix).
Excluded by passive scan mode. You ran with --read-only, which skips checks that write or run commands. Expected. See what --read-only skips.
Instance is neither a Nitro Enclaves parent nor an AMD SEV-SNP ... The check doesn't apply to this instance type. Expected.

A scan with any SKIP or ERROR ends with ... checks passed; coverage is incomplete. and Skipped checks and errors remain unassessed. A skipped check is never counted as a pass.

A check says ERROR

ERROR means the check started but couldn't reach a verdict. It is never counted as a pass, and it makes untrust scan exit 2.

Permission denied

The summary carries the provider's error, for example Could not describe instance: An error occurred (UnauthorizedOperation) ... or Access denied reading bucket policy: ....

  1. Open the check's page from the check list. Each page lists the API calls the check makes and the permission each one needs.
  2. Grant the missing permission to the scanning identity. The Required permissions page has an example policy or role for every platform.
  3. Scan again.

A Nitro check that can't call kms:DescribeKey says so directly: could not verify ... uses a customer-managed CMK (grant kms:DescribeKey to the audit role).

A Google Cloud API isn't enabled

The check's summary includes Google's error naming the API, for example SERVICE_DISABLED or accessNotConfigured. Enable that API in the project, wait a minute and scan again. The scanner calls Compute Engine, Cloud KMS, IAM, Cloud Storage, Secret Manager, Cloud Resource Manager and Access Context Manager. Which ones a check needs is on its page.

Check raised an exception: ...

The check hit an error it doesn't handle. The rest of the message is the underlying error. Most often it's a missing or expired credential, or a resource name that doesn't exist in that region or project. Check the credentials and the target names, then scan again. If it persists, send the message to your untrust contact.

Not found

Instance <id> not found. or not found reading <path> (Azure) means the resource doesn't exist where the scanner looked. On AWS, check --region: untrust scan and untrust detect default to us-west-2 and ignore AWS_REGION. Pass --region explicitly.

No credentials found

The scanner uses the credentials already present where it runs. It has no message of its own for missing credentials, so each check reports the SDK's error instead.

  • AWS: the standard credential chain (environment variables, AWS_PROFILE, an instance or workload role). Test with aws sts get-caller-identity.
  • GCP: Application Default Credentials. Run gcloud auth application-default login, or attach a service account to the machine. Test with gcloud auth application-default print-access-token.
  • Azure: with the azure extra installed, DefaultAzureCredential. Without it, the scanner asks the Azure CLI for a token:
    • install 'untrust[azure]' or sign in with the Azure CLI means neither is available.
    • Azure CLI could not issue a token; run `az login` means the CLI isn't signed in.
  • untrust detect --platform azure-cvm reads the Activity Log live only with azure-mgmt-monitor and azure-identity installed. Otherwise it tells you to pass --azure-log-file with exported Activity Log JSON.

Nitro host checks

The host and enclave checks run fixed commands on the parent instance through SSM Run Command.

Summary Cause Fix
Could not send SSM command: ... The instance isn't managed by SSM (agent stopped, no instance profile with SSM permissions, or no route to SSM), or the scanning identity lacks ssm:SendCommand. Check the instance appears in Systems Manager's managed nodes, and grant ssm:SendCommand on it and the AWS-RunShellScript document.
SSM command did not complete within timeout. The command ran longer than about 30 seconds. Check the agent's health on the instance and scan again.
nitro-cli not available or no enclaves found. nitro-cli isn't installed on the parent, or no enclave is running. Install the Nitro Enclaves CLI and start the enclave before scanning.
No enclaves are currently running. Nothing to measure. Start the enclave.
Could not locate an .eif file on the host to inspect. ENCLAVE-04 and ENCLAVE-07 inspect the enclave image file on the parent. Keep the EIF on the parent instance.

--read-only skips all of these checks.

The write probes pass even though I didn't grant write access

BOOTSTRAP-01 and GCS-BOOT-02 try to write probe objects. A refused write is the result the check wants, so without write permission they pass. That pass only shows that the scanning identity can't write. BOOTSTRAP-02 and GCS-BOOT-01 read the bucket's policy to see who else can. A transient storage error is reported as ERROR, not as a pass.

Exit codes

Command 0 1 2 3
scan No FAIL, no ERROR At least one FAIL, or no target given At least one ERROR
scan --demo Always
buildscan, iacscan Passed Blocked Incomplete or error
registry scan All verified A confirmed failure Not assessable
pack verify, ledger verify, ci verify Verified Not verified, or the entry wasn't found Missing input, such as --org Unsigned or unbound
report-upload, collector run --once Sent Refused or failed

An invalid option also exits 2, the same code as an incomplete gate. CI treats both as a failure, which is safe, but read the job log before concluding that a scan was incomplete.

ledger verify without --org exits 2 and prints INTEGRITY VERIFIED, ORGANIZATION NOT CHECKED (pass --org): .... Pass --org with your organization ID.

CI gates

  • 2 on a gate: the analysis was incomplete (an input over a size limit, an unparsable file, the time limit). The receipt's findings say which. It is never safe to treat as a pass. See the limits in CI gates.
  • Plan and output paths must be different. iacscan --output points at the plan file.
  • Give one of --policy, --policy-url or one or more --image. registry scan needs a trust policy or an image.
  • Upload refused for a build receipt: --commit must be the full commit SHA, and --run-id must be the plain run ID (GitHub) or pipeline ID (GitLab), with no attempt suffix. They are compared with the OIDC token.
  • Uploading from Jenkins, Buildkite or another system: not supported. Only GitHub Actions and GitLab.com tokens are accepted. See CI systems.

Uploads and API calls

report-upload, api get and release verify print one of these when the service refuses a request:

Message Meaning
The request was refused (HTTP 401): the API key or token is invalid, expired or revoked. Create a new key in Settings › API keys. The key is wrong, expired or revoked.
The request was refused (HTTP 403): this key's role cannot do it; ... The key's role can't do this. Create a key with a role that can.
The request was refused (HTTP <code>). Any other refusal. The server's response body isn't shown. A 3xx means the URL redirected; the client never follows redirects, so use the exact https://<host>/v1/organizations/<org>/... URL. A 429 means too many requests: wait and try again.
The request did not complete; inspect and retry. Network failure or the 30-second timeout.
URL must be https://<host>/v1/organizations/<org>/<collection>[/...]. The --org-url is malformed. The organization ID is 32 hexadecimal characters.
The request exceeds the size limit. The body is over 6 MiB.
The attestation token is larger than 16 KiB; not sent. The --cs-attestation-token file is too large to be a token.

The client doesn't retry. Requests time out after 30 seconds.

Collectors

Message Cause Fix
Not enrolled: <path> is missing. Run untrust collector enroll. No enrollment in this state directory. Enroll, or point --state-dir (or UNTRUST_COLLECTOR_STATE) at the right directory.
Already enrolled (<path>). Remove it to re-enroll. This host already has a key. Remove the state file only if you mean to replace the host's identity.
The untrust origin must use HTTPS. --origin isn't https://. Use the HTTPS origin.
Could not reach untrust: ... Network, DNS or TLS failure. Check outbound HTTPS. Use --ca-file if a proxy re-signs TLS.
untrust answered 401: {"error": "Authentication required."} The enrollment token is invalid or expired, or the collector's key is unknown, revoked or its fleet is inactive. The service doesn't say which. Check the host in the fleet; enroll again with a new token if it was revoked.
untrust answered 409: {"error": "Bundle is stale or replayed."} The host clock is more than five minutes off. Fix the time sync (NTP/chrony) on the host.
untrust answered 409: ... That collector key is already enrolled. The same key was enrolled twice. Remove the duplicate host in the fleet.
untrust collector scan runs on Linux hosts; this is <platform>. Host checks run only on Linux. Run it on the confidential host.
Installing the service needs root (sudo). install-service writes a systemd unit. Run it with sudo.

collector run logs report failed, will retry: ... and tries again at the next interval. With --once, it exits 1 instead.

Demo and read-only mode

  • --demo runs against a built-in simulated deployment. It ignores --read-only, always exits 0 and marks its JSON "simulated": true. The console leaves simulated reports out of posture health.
  • --read-only prints READ-ONLY MODE — active probes and host execution are excluded. Excluded checks are listed in the report under coverage.mode_excluded_check_ids, and coverage always shows as incomplete. A --read-only scan can still exit 2 if another check errors.

Still stuck

Send your untrust contact the check ID, its summary, and the CLI version (untrust --version). Remove target names and identifiers you don't want to share first.