> For the complete documentation index, see [llms.txt](https://docs.xygeni.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.xygeni.io/xygeni-products/application-security-posture-management-aspm/importing-reports-from-3rd-party-tools/pull-mode-fetch.md).

# Pull-mode fetch

Pull mode lets the Xygeni scanner call a third-party tool's API directly, fetch the findings, and route them through the same loader+converter pipeline that processes file uploads. No intermediate report file on disk; credentials read from environment variables; resolved auth headers and tokens redacted from logs.

When you'd use it over [convert+upload](/xygeni-products/application-security-posture-management-aspm/importing-reports-from-3rd-party-tools.md#report_upload):

* The tool exposes a documented findings API and your pipeline doesn't already collect a report file.
* You'd rather not stage credentials inside a CI artifact or a checked-in JSON.
* You want one CLI invocation to drive both the fetch and the conversion.

When **not** to use it:

* The tool only writes to disk — keep using convert+upload.
* The tool actively pushes to consumers — see the [push (webhook) mode](/xygeni-products/application-security-posture-management-aspm/importing-reports-from-3rd-party-tools.md#the-three-ingestion-modes); the per-adapter setup guide will be added to this section as each webhook integration ships.

## How to invoke

```bash
xygeni report-upload --pull --format <id> \
  --selector key=value [--selector ...] \
  --filter  key=value [--filter ...] \
  [--name <project>] [--no-upload] [--output <path>]
```

* `--pull` switches the command from reading `--report` files to fetching from the API.
* `--format` (exactly one) selects the registry entry; the entry must declare a `pull:` block (i.e. one of the formats listed below).
* `--selector` carries **per-scan identifiers** the tool needs — project key, branch, application name, organization, scan id, tenant. Always required for tools that scope findings to a project.
* `--filter` carries **tool-specific findings filters** — severity, status, time window, cloud platform. Optional; each fetcher documents its own filter keys.
* `--no-upload` runs the fetch + conversion but skips the upload to Xygeni. Pair with `--output <file>` to inspect the converted payload before wiring the command into CI.

## Credentials and environment variables

Each tool reads its credentials from environment variables. The scanner refuses to start if a referenced variable is unset (fail-closed); it never embeds the resolved secret into the converted output; and it registers the resolved value with the log redactor so any subsequent log line that would print it shows `***` instead.

The naming convention is `<TOOL>_URL`, `<TOOL>_TOKEN` / `<TOOL>_CLIENT_ID` / `<TOOL>_CLIENT_SECRET`, etc. — the exact set is listed per-tool below.

{% hint style="info" %}
You can also pass `-Dname=value` on the Java command line as a fall-through when an environment variable can't be exported (e.g. some containerised runners). The framework checks env vars first, then Java system properties.
{% endhint %}

## Worked examples per tool

### SonarQube / SonarCloud

Two registry entries — `sast-sonarcloud` (bearer-token auth) and `sast-sonarqube` (basic auth with the API token as the username and an empty password, per SonarQube Server's traditional auth scheme).

**SonarCloud**

```bash
export SONARCLOUD_URL=https://sonarcloud.io
export SONARCLOUD_TOKEN=squ_xxxxxxxxxxxxxxxxxxxxxxxxxx

xygeni report-upload --name MyApp --pull \
  -f sast-sonarcloud \
  --selector project_key=acme/web \
  --selector branch=main \
  --selector organization=acme            # SonarCloud only; required for org-scoped projects
```

**SonarQube Server**

```bash
export SONARQUBE_URL=https://sonarqube.internal.example.com
export SONARQUBE_TOKEN=sq-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

xygeni report-upload --name MyApp --pull \
  -f sast-sonarqube \
  --selector project_key=acme:web \
  --selector branch=main
```

Both invocations pull security issues from `/api/issues/search` and security hotspots from `/api/hotspots/search`, merge and deduplicate, and write a single document in the same shape the existing `sast-sonarqube` / `sast-sonarcloud` loaders consume for file uploads. Pagination, retry/backoff and log redaction are handled by the framework.

| Selector       | Required | Notes                              |
| -------------- | :------: | ---------------------------------- |
| `project_key`  |    yes   | SonarQube / SonarCloud project key |
| `branch`       |    no    | Branch analysis to query           |
| `pullRequest`  |    no    | PR analysis id                     |
| `organization` |    no    | SonarCloud only                    |

| Filter     | Notes                                                                                                                                                           |
| ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `severity` | Comma-separated severities (e.g. `HIGH,CRITICAL`). Applied to issues; hotspots use a different vulnerability-probability filter that isn't currently forwarded. |
| `status`   | Comma-separated for issues. Hotspots accept only `TO_REVIEW` / `REVIEWED` — when multiple values are supplied, only the first is forwarded to that endpoint.    |

### Kiuwan

Two registry entries:

* `sast-kiuwan` — **file upload** of the XML report produced by the Kiuwan Local Analyzer custom `ExportRule`. Documented in the [Report upload for Kiuwan](/xygeni-products/application-security-posture-management-aspm/importing-reports-from-3rd-party-tools/external-scanners-supported/report-upload-for-kiuwan.md) page; recommended only if you already have that pipeline set up.
* `sast-kiuwan-api` — **pull mode**, calling Kiuwan's native REST API. **Recommended for new integrations**: no Kiuwan-side install, no Local Analyzer custom rule, no quality-model edits. Carries source/sink data-flow detail that SARIF / CSV exports drop.

```bash
export KIUWAN_URL=https://api.kiuwan.com              # SaaS; on-prem tenants use their own URL
export KIUWAN_USER=<your Kiuwan API user code>
export KIUWAN_TOKEN=<your Kiuwan API token>

xygeni report-upload --name MyApp --pull \
  -f sast-kiuwan-api \
  --selector application='My Application'
```

With an explicit analysis + filters:

```bash
xygeni report-upload --name MyApp --pull \
  -f sast-kiuwan-api \
  --selector application='My Application' \
  --selector analysisCode=A-1234567890123 \
  --filter priority='High,Very high'
```

| Selector       | Required | Notes                                                                     |
| -------------- | :------: | ------------------------------------------------------------------------- |
| `application`  |    yes   | Kiuwan application name                                                   |
| `analysisCode` |    no    | Specific scan to fetch. Default: result of `/applications/last_analysis`. |

| Filter           | Notes                                                                                             |
| ---------------- | ------------------------------------------------------------------------------------------------- |
| `priority`       | Comma-separated. `Very low,Low,Normal,High,Very high`.                                            |
| `characteristic` | Comma-separated. Defaults to `Security` (SAST scope); pass to widen, e.g. `Security,Reliability`. |
| `language`       | Comma-separated tool-defined language list (e.g. `java,javascript`).                              |
| `muted`          | `true` / `false`.                                                                                 |

Auth is HTTP Basic with the Kiuwan API user code as the username and the token as the password.

### Checkmarx One — SAST + SCA + IaC

Pull mode is wired on **three** registry entries — `sast-checkmarx-one`, `sca-checkmarx-one`, `iac-checkmarx-one`. They share a single fetcher; Checkmarx One's `/api/results` endpoint returns all three engines' findings in one document and each entry's converter slices its own engine out.

```bash
export CHECKMARX_URL=https://ast.checkmarx.net          # SaaS regions: ast / eu.ast / anz.ast / etc.
export CHECKMARX_CLIENT_ID=<OAuth2 client id>
export CHECKMARX_CLIENT_SECRET=<OAuth2 client secret>

# SAST findings:
xygeni report-upload --pull -f sast-checkmarx-one \
  --selector tenant=acme --selector project_name='My App'

# SCA findings (same project, refetched independently):
xygeni report-upload --pull -f sca-checkmarx-one \
  --selector tenant=acme --selector project_name='My App'

# IaC (KICS) findings:
xygeni report-upload --pull -f iac-checkmarx-one \
  --selector tenant=acme --selector project_name='My App'
```

With an explicit scan + filters:

```bash
xygeni report-upload --pull -f sast-checkmarx-one \
  --selector tenant=acme \
  --selector project_id=11111111-2222-3333-4444-555555555555 \
  --selector scan_id=99999999-8888-7777-6666-555555555555 \
  --filter severity='HIGH,MEDIUM'
```

| Selector       | Required | Notes                                                                      |
| -------------- | :------: | -------------------------------------------------------------------------- |
| `tenant`       |    yes   | Checkmarx One tenant name; interpolated into the OAuth2 token endpoint URL |
| `project_id`   |  one of  | UUID of the Checkmarx One project                                          |
| `project_name` |  one of  | Human-readable name; resolved to `project_id` via `/api/projects?name=…`   |
| `scan_id`      |    no    | Specific scan to fetch. Default: latest scan for the project.              |

| Filter     | Notes                                                              |
| ---------- | ------------------------------------------------------------------ |
| `severity` | Comma-separated `HIGH,MEDIUM,LOW,INFO`                             |
| `state`    | Result state enum (`TO_VERIFY`, `NOT_EXPLOITABLE`, `CONFIRMED`, …) |
| `status`   | `NEW`, `RECURRENT`, `FIXED`                                        |

Auth: OAuth2 client credentials. The framework caches the access token by its declared `expires_in` and refreshes it automatically.

### Prisma Cloud — CSPM alerts + asset inventory

Two registry entries — `iac-prisma-cloud` (CSPM security alerts / policy violations) and `inventory-prisma-cloud` (cloud asset inventory). One fetcher drives both; each entry picks its endpoint internally.

```bash
export PRISMACLOUD_URL=https://api.prismacloud.io            # api.eu.prismacloud.io, api.anz.prismacloud.io, …
export PRISMACLOUD_ACCESS_KEY=<access key>
export PRISMACLOUD_SECRET_KEY=<secret key>

# Security alerts (CSPM policy violations):
xygeni report-upload --pull -f iac-prisma-cloud

# Cloud asset inventory:
xygeni report-upload --pull -f inventory-prisma-cloud
```

With filters:

```bash
xygeni report-upload --pull -f iac-prisma-cloud \
  --filter status=open \
  --filter severity=critical,high \
  --filter cloud=aws,azure \
  --filter time_range_days=7
```

| Filter               | Applies to | Notes                                                                                                                                                                             |
| -------------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `time_range_days`    | both       | Window length. Default `30` for alerts, `1` for inventory.                                                                                                                        |
| `cloud`              | both       | Comma-separated cloud providers (`aws`, `azure`, `gcp`, `alibaba_cloud`, `oci`).                                                                                                  |
| `status`             | alerts     | Single value: `open`, `dismissed`, `resolved`, `snoozed`. Default `open`.                                                                                                         |
| `severity`           | alerts     | Comma-separated `critical,high,medium,low,informational`.                                                                                                                         |
| `resource_type`      | inventory  | Comma-separated resource types (e.g. `aws_ec2_instance,gcp_compute_instance`).                                                                                                    |
| `rql`                | inventory  | Raw RQL query used verbatim (escape hatch — disables the `cloud` / `resource_type` composition). Example: `--filter rql="config from cloud.resource where finding.type = 'CVE'"`. |
| `with_resource_json` | inventory  | `true` (default) embeds the full provider-specific resource JSON in each item; set to `false` for a leaner payload.                                                               |

Inventory uses Prisma Cloud's [RQL (Resource Query Language)](https://docs.prismacloud.io/en/enterprise-edition/content-collections/search-and-investigate/rql-reference/rql-reference). Auth is handled by the fetcher (POST `/login` for an `x-redlock-auth` token; transparent re-auth on 401); the registry declares `auth.type: basic` only to flow the access key + secret key through env-var resolution and log redaction.

### Wiz CNAPP

Four registry entries — `iac-wiz-issues`, `sca-wiz-cnapp`, `iac-wiz-config`, `inventory-wiz-cnapp`. A single fetcher drives all four via per-entry `selectorDefaults.mode`. Wiz is the first GraphQL fetcher in the pull framework; the GraphQL endpoint and OAuth2 token URL are both configurable so any region (US / EU / Gov) works without code changes.

```bash
export WIZ_API_URL=https://api.us1.app.wiz.io/graphql              # full GraphQL endpoint
export WIZ_CLIENT_ID=<service-account client id>
export WIZ_CLIENT_SECRET=<service-account client secret>
# Optional — defaults to Cognito; legacy Auth0 tenants use https://auth.wiz.io/oauth/token
# export WIZ_TOKEN_URL=https://auth.app.wiz.io/oauth/token

# Issues (Toxic Combinations, Threats, Cloud Misconfigurations):
xygeni report-upload --pull -f iac-wiz-issues

# CVEs detected on cloud workloads:
xygeni report-upload --pull -f sca-wiz-cnapp --filter severity=CRITICAL,HIGH

# CSPM policy violations:
xygeni report-upload --pull -f iac-wiz-config --filter result=FAIL,ERROR

# Cloud asset inventory:
xygeni report-upload --pull -f inventory-wiz-cnapp --filter cloud_platform=AWS
```

| Filter           | Applies to                                  | Notes                                                                                                                    |
| ---------------- | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `status`         | issues / vulnerabilities / config\_findings | Filtering the resolution state                                                                                           |
| `severity`       | issues / vulnerabilities / config\_findings | Wiz severity enum. The fetcher remaps the filter key to `vendorSeverity` for the vulnerabilities mode (Wiz schema quirk) |
| `type`           | issues / cloud\_resources                   | Issue category for issues; Wiz resource type for inventory                                                               |
| `result`         | config\_findings                            | `FAIL`, `ERROR`                                                                                                          |
| `cloud_platform` | cloud\_resources                            | `AWS`, `AZURE`, `GCP`, …                                                                                                 |
| `page_size`      | all                                         | Page size — clamped to Wiz's documented 500 max                                                                          |

Auth: OAuth2 client credentials with the `audience=wiz-api` claim. The framework caches the access token by `expires_in` and refreshes it automatically; the token URL is configurable so the same registry entry works against both Cognito-backed and legacy Auth0-backed Wiz tenants.

## Dry-run and inspecting the converted payload

Before wiring the command into CI, run it once with `--no-upload --output <path>` to inspect the converted JSON:

```bash
xygeni report-upload --pull -f sast-sonarcloud \
  --selector project_key=acme/web --selector branch=main \
  --no-upload --output /tmp/sonarcloud-converted.json
```

The output file holds the same payload that would have been uploaded — useful for verifying severity mapping, project name inference, or filter coverage.

## Troubleshooting

**"No value for `${env:X}` — set the Java system property `-DX=…` or export the env var X"** The scanner refuses to run with an unresolved secret. Export the variable in the same shell that invokes `xygeni`, or pass `-DX=value` on the Java command line if your runner can't export environment variables.

**"Format '' has no pull: block configured"** The format you passed to `-f` exists as a convert+upload entry but doesn't yet support pull mode. Either drop `--pull` and supply `--report`, or pick a format from the supported list above.

**"--pull requires exactly one --format"** Pull mode takes one format per invocation. If you need to fetch from multiple tools, issue multiple commands.

**HTTP 401 / 403** The token doesn't have permission for the resource you asked for. The error message includes the path that failed — verify the project key / scan id / tenant against the tool's UI, and check the token's scope.

**Retries exhausted** The fetcher retries transient failures (HTTP 5xx, network errors) with exponential backoff. If retries exhaust, the tool's API is likely down — check the tool's status page and rerun. Pull mode is idempotent; re-invoking after a transient failure is safe.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.xygeni.io/xygeni-products/application-security-posture-management-aspm/importing-reports-from-3rd-party-tools/pull-mode-fetch.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
