Wiz

This CLI is provided to perform batch processing and orchestration of the Wiz Cloud-Native Application Protection Platform (CNAPP). It is designed to perform bulk processing of Wiz data to create, update, and otherwise sync with RegScale to allow for compliance automation reporting. The CLI currently supports the following functionalities:

  • authenticate - Authenticate with Wiz and get a JSON Web Token (JWT) for future requests to Wiz
  • add_report_evidence - downloads a Wiz report by ID and attach to Evidence
  • inventory - syncs the Wiz entity types in wizInventoryFilterBy's type list into RegScale as assets (see the default list below)
  • issues - syncs any identified problems as issues/POAMs to RegScale
  • vulnerabilities - process vulnerabilities from Wiz
  • attach_sbom - downloads SBOM report from Wiz into your security plan
  • compliance_report - process Wiz compliance reports and create assessments in RegScale
  • sync_compliance - (deprecated) syncs compliance posture from Wiz to RegScale, use compliance_report instead
  • sync_benchmarks - imports STIG and CIS benchmark definitions from Wiz into RegScale
  • stig_checks - syncs STIG and CIS benchmark check results from Wiz into RegScale

Wiz Service Account Setup

Before using the RegScale CLI with Wiz, you must create a service account in Wiz with the correct permissions. Follow these steps carefully.

Step 1: Create a Service Account in Wiz

  1. Log in to your Wiz tenant
  2. Click the user profile icon in the top right and navigate to Settings > Service Accounts (or use the search bar and enter "Service Accounts")
  3. Click Add Service Account and configure the following fields:
FieldValue
Nameregscale_cli_sa (or your preferred name)
TypeCustom Integration (GraphQL API)
DescriptionRegScale CLI integration
ProjectsLeave empty to grant access to all projects, or select up to 50 specific projects to limit access
Expiration DateOptional - set an expiration date if required by your security policy

Step 2: Configure API Scopes

Under API Scopes, enable the following permissions:

Required Global Scopes:

ScopePermission KeyDescription
Administer all admin entitiesadmin:allRequired for managing reports and configurations
Read all entitiesread:allRequired for reading issues, inventory, vulnerabilities, and compliance data

Required Report Scopes (under Reports section):

All report scopes must be enabled for compliance reporting, SBOM downloads, and evidence collection:

ScopePermission Key
Manage report settingsadmin:reports
Read reportread:reports
Update reportsupdate:reports
Create reportcreate:reports
Delete reportdelete:reports
Create and delete reportswrite:reports

Step 3: Save Credentials

After creating the service account, Wiz will display the Client ID and Client Secret. Copy these values immediately - the Client Secret will not be shown again.

Store the credentials using one of these methods:

Option A: Environment Variables (Recommended)

export WizClientID='YOUR_WIZ_CLIENT_ID'
export WizClientSecret='YOUR_WIZ_CLIENT_SECRET'

Option B: init.yaml Configuration

Add the credentials to your init.yaml file:

wizClientId: YOUR_WIZ_CLIENT_ID
wizClientSecret: YOUR_WIZ_CLIENT_SECRET

Option C: Command-Line Arguments

Pass credentials directly to each command:

regscale wiz authenticate --client_id YOUR_CLIENT_ID --client_secret YOUR_CLIENT_SECRET

Step 4: Get the Wiz API URL

  1. In Wiz, click the user profile icon in the top right and navigate to Tenant Info
  2. Copy the API Endpoint URL and set it in your init.yaml:
wizUrl: https://api.us27.app.wiz.io/graphql

Note for GovCloud customers: The default wizAuthUrl is https://auth.wiz.io/oauth/token. Government customers may need to use an alternate authentication URL. Set wizAuthUrl in your init.yaml if needed.

init.yaml Configuration

The following configuration variables are available for the Wiz integration in your init.yaml file:

VariableTypeDefaultDescription
wizUrlstringhttps://api.us27.app.wiz.io/graphqlGraphQL endpoint for your Wiz instance
wizClientIdstringWiz service account Client ID
wizClientSecretstringWiz service account Client Secret
wizAccessTokenstringAuto-populated after authentication
wizFullPullLimitHoursint8Maximum age of cached Wiz data, in hours, before a sync fetches it again
wizIncrementalPullsboolfalseDelta pulls — each sync fetches only what changed since its last successful run. Planned to become the default in a later major release (still opt-in in 7.0.0)
wizIncrementalRebaselineHoursint168With delta pulls on, force a full pull once the last full pull is this many hours old
wizPullWatermarksmapWritten by the CLI: each sync scope's delta watermark and last full pull. Do not edit by hand
wizLastInventoryPull, wizLastVulnerabilityPull, wizLastIssuePull and their *FullPull formsstringDeprecated, no longer read. Replaced by wizPullWatermarks; delete them
wizRetentionReconciliationboolfalseClose RegScale issues whose Wiz findings have aged out of Wiz's retention window
wizDataRetentionDaysint7Wiz's detection-data retention window; only used when wizRetentionReconciliation is enabled
wizCollapseRepresentativeAssetsboolfalseKeep only the Wiz Representative Resource where an ephemeral/representative pair is proven (shared grouping and same container image); findings on a collapsed container are re-pointed at its representative, so no CVE is lost
wizCollapseRepresentativeAssetsDryRunboolfalseReport what would collapse and change nothing; works on its own, and is the recommended first run on an established tenant because the collapse removes assets from the register
wizDropUndeployedRegistryImagesboolfalseSkip vulnerability and end-of-life findings on container images Wiz found only in a registry (scan source exactly REGISTRY) with no execution controller. Turning it on closes any such findings already imported at the next full sync
wizInventoryFilterBystring(default type list)Default JSON filter for inventory pulls
wizIssueFilterBystring{}Default JSON filter for issue pulls
wizVulnerabilitiesFilterBystring{}Default JSON filter for vulnerability pulls
useWizHardwareAssetTypesboolfalseWhether to use wizHardwareAssetTypes to classify hardware vs software assets
wizHardwareAssetTypeslistVIRTUAL_MACHINE, CONTAINER, ...Asset types from Wiz to create as hardware assets in RegScale
wizExcludesstringComma-separated list of asset names to exclude from syncing
wizReportAgeint15 (14 if the key is absent)Maximum age in days for reusing existing Wiz reports
wizStigMapperFilestringWritten to the default init.yaml template but not read by the STIG mapper; set stigMapperFile instead (see STIG Mapper)
issues.wiz.criticalint30Shipped default; not read by wiz issues/wiz vulnerabilities — due dates come from first detection + the plan's compliance-settings SLA (see the issue workflow)
issues.wiz.highint90Shipped default; not read by the Wiz commands
issues.wiz.mediumint90Shipped default; not read by the Wiz commands
issues.wiz.lowint365Shipped default; not read by the Wiz commands
issues.wiz.statusstringOpenDefault status for new RegScale issues

Quick Start

  1. Log into RegScale (skip if using a RegScale Service Account):
regscale login
  1. Authenticate to Wiz (credentials auto-detected from environment or init.yaml):
regscale wiz authenticate
  1. Run the desired sync command:
# Sync issues
regscale wiz issues --regscale_ssp_id=5

# Sync inventory
regscale wiz inventory --regscale_ssp_id=5

# Sync vulnerabilities
regscale wiz vulnerabilities -p "project-123" --regscale_ssp_id=5

# Sync compliance
regscale wiz compliance_report -p "project-123" --regscale_id=5

Issue Processing Workflow

The issue sync pulls Wiz issues in all four statuses — OPEN, IN_PROGRESS, RESOLVED,
REJECTED (PS-590: resolved and rejected issues land too, so a rejection closes its RegScale
record instead of orphaning it) — and writes them to RegScale:

  1. Authenticates to Wiz (auto-authenticates if credentials are configured)
  2. Retrieves all existing RegScale issues for the given security plan
  3. Fetches the project's issues with a GraphQL query (issuesV2), grouped by their
    source rule — no report is created in Wiz for this command
  4. Writes one RegScale issue per source-rule group (the control for a control issue),
    not one per Wiz issue: the group's vulnerability and issue stay the same records for as
    long as the rule keeps failing (REG-30187)
  5. Closes any RegScale issues where the corresponding Wiz issues no longer exist (remediated)

Due dates: a Wiz issue's RegScale due date is its finding's first detection date plus
the security plan's compliance-settings SLA for its severity
(KEV findings aside, which
follow the KEV clock). The issues.wiz day counts in init.yaml are not read by
wiz issues or wiz vulnerabilities.

# Basic usage
regscale wiz issues --regscale_ssp_id=5

# With project filter and severity filter
regscale wiz issues \
  -p "project-123" \
  --regscale_ssp_id=5 \
  --filter_by_override='{"severity": ["HIGH", "CRITICAL"]}'

Inventory Processing Workflow

The inventory sync retrieves cloud entities from Wiz and creates or updates assets in RegScale:

  1. Authenticates to Wiz
  2. Retrieves all existing assets in RegScale for the given security plan
  3. Pulls only the entity types in the filter's type list (wizInventoryFilterBy, or
    --filter_by_override for one run). A filter with no type key pulls every type. A project can hold thousands of entities of other
    types (DNS records, subnets, IAM artifacts, …); those never become assets. The shipped
    default list is:
    VIRTUAL_MACHINE, VIRTUAL_DESKTOP, KUBERNETES_CLUSTER, VIRTUAL_MACHINE_IMAGE,
    CONTAINER_IMAGE, CONTAINER, POD, SERVERLESS, SERVERLESS_PACKAGE, APPLICATION,
    WEB_SERVICE, KUBERNETES_SERVICE, CONTAINER_REGISTRY, CONTAINER_SERVICE, DATABASE,
    DB_SERVER, BUCKET, STORAGE_ACCOUNT, VOLUME, FILE_SYSTEM_SERVICE, BACKUP_SERVICE,
    FIREWALL, LOAD_BALANCER, MESSAGING_SERVICE, SECRET_CONTAINER
  4. For each Wiz entity: updates the existing RegScale asset if found, otherwise creates a new one
# Basic usage
regscale wiz inventory --regscale_ssp_id=5

# With project and type filters
regscale wiz inventory \
  --wiz_project_id="project-123" \
  --regscale_ssp_id=5 \
  --filter_by_override='{"type": ["VIRTUAL_MACHINE", "DATABASE"]}'

Data-Retention Reconciliation

Wiz keeps vulnerability and issue detection data for a limited window — seven days by
default. Once a finding ages out of that window it stops appearing in every subsequent
pull, and because Wiz never reports it as resolved, nothing in a normal sync tells
RegScale the finding is gone. The matching RegScale issue stays open indefinitely.

Reconciliation closes those issues. It is off by default because closing issues is
destructive:

wizRetentionReconciliation: true
wizDataRetentionDays: 7   # must match your Wiz tenant's retention setting

After each sync writes its findings, reconciliation compares the open Wiz-sourced issues
on the plan against the findings the run reported. An issue is closed only when all of
the following hold:

  • its finding was not reported by this run
  • it was last seen more than wizDataRetentionDays days ago
  • it is not protected from auto-closure (preventAutoClose, a PREVENT_AUTO_CLOSE
    property, or a manual-reopen note)

Anything that cannot be proven gone is left open. Reconciliation is skipped entirely —
with a log line explaining which condition tripped — when the run processed a paginated
subset, when the run was incremental or otherwise incomplete, or when it reported zero
findings (far more often a scoping or credential problem than an empty tenant).

On RegScale platform 6.35.1.0 and newer, when the run's findings are posted in a single
final vulnerability batch flush of one request, the comparison and the closures happen on the server: the sync sends
wizDataRetentionDays with that request (the Client API's mopUpMaxAgeDays option) and
RegScale closes the aged-out issues, writes the audit note and refreshes the status of the
controls they were linked to; the sync logs "Closed N outdated issues." from the server's
count once the server has confirmed it ran the pass. On an older platform, or when the run's
findings are posted in more than one flush or request (the server's pass only knows the
findings of the request that carries the option), the CLI performs the same pass itself, as
6.x did, and logs once why. A run whose findings exactly fill a finding chunk
(findingChunkSize, 5000 by default) is also closed client-side, because the flush that
carries its findings is not marked as the run's final one. preventAutoClose turns the retention close
off on either path; it does not affect the server's close-findings-not-in-scan mop-up.

Setting wizDataRetentionDays shorter than the tenant's real Wiz retention window will
close findings that Wiz is still reporting. If you are unsure of the window, leave the
default and confirm with your Wiz administrator before shortening it.

Filter Parameters

All commands that support --filter_by_override accept a JSON string with one or more of the following parameters:

ParameterTypeDescription
projectarrayWiz project IDs, as a list (auto-injected from --wiz_project_id for issues/inventory)
projectIdarrayMultiple project IDs (auto-injected from --wiz_project_id for vulnerabilities)
typearrayResource type filter (e.g., ["VIRTUAL_MACHINE", "DATABASE"])
statusarrayIssue status filter (["OPEN", "IN_PROGRESS", "RESOLVED", "REJECTED"])
severityarraySeverity filter (["CRITICAL", "HIGH", "MEDIUM", "LOW"])
searchstringFree text search on resource name
subscriptionExternalIdarrayExternal subscription IDs (AWS Account, Azure Subscription, etc.)
providerUniqueIdarrayCloud provider unique identifiers
updatedAtobjectDate filter with before/after in ISO 8601 format
deletedAtobjectDate filter for deleted resources

Note: The --wiz_project_id parameter is automatically injected into your filter. You do not need to include the project ID in your --filter_by_override JSON.

init.yaml Example

domain: https://mycompany.regscale.com
maxThreads: 1000
wizClientId: your-wiz-client-id
wizClientSecret: your-wiz-client-secret
wizUrl: https://api.us27.app.wiz.io/graphql
wizAuthUrl: https://auth.wiz.io/oauth/token
wizFullPullLimitHours: 8
wizReportAge: 14
wizInventoryFilterBy: '{}'
wizIssueFilterBy: '{}'
wizVulnerabilitiesFilterBy: '{}'
useWizHardwareAssetTypes: true
wizHardwareAssetTypes:
  - VIRTUAL_MACHINE
  - VIRTUAL_MACHINE_IMAGE
  - CONTAINER
  - CONTAINER_IMAGE
  - DB_SERVER
  - SERVER_APPLICATION
  - CLIENT_APPLICATION
  - VIRTUAL_APPLIANCE
wizExcludes: Azure AD Builtin Application Service Principal, Azure Active Directory (AAD) User
wizStigMapperFile: /path/to/stig_mapper_rules.json
issues:
  wiz:
    critical: 30
    high: 90
    low: 365
    medium: 90
    status: Open

Note: The wizAccessToken and wizScope fields are auto-populated after authenticating to Wiz via the CLI.

Building a Bash Script to Execute the CLI

You can chain together RegScale CLI commands using scripts. These scripts could be in Bash, Python, PowerShell, etc. Below is an example Bash file for executing the Wiz CLI:

#!/bin/sh
# Wiz auto-authenticates on every execution of issues or inventory functions
regscale wiz issues --regscale_ssp_id=5
regscale wiz inventory --regscale_ssp_id=5
regscale wiz vulnerabilities -p "project-123" --regscale_ssp_id=5
regscale wiz compliance_report -p "project-123" --regscale_id=5

Compliance Report

Process Wiz compliance reports and create assessments in RegScale. This is the recommended command for compliance sync (replaces the deprecated sync_compliance).

regscale wiz compliance_report [OPTIONS]

Options:
  -p, --wiz_project_id TEXT              Wiz project ID [required]
  --regscale_id INTEGER                  RegScale record ID [required]
  --regscale_module TEXT                 RegScale module (default: securityplans)
  -i, --client_id TEXT                   Wiz Client ID
  -s, --client_secret TEXT               Wiz Client Secret
  -f, --report_file_path TEXT            Path to existing CSV compliance report
  --create-issues/--no-create-issues     Create issues for failed assessments (default: enabled)
  --update-control-status/--no-update-control-status  Update control status (default: enabled)
  --create-poams/--no-create-poams       Mark issues as POAMs (default: disabled)
  --reuse-existing-reports/--no-reuse-existing-reports  Reuse existing Wiz reports (default: enabled)
  --force-fresh-report/--no-force-fresh-report  Force new report creation (default: disabled)
  --create-evidence/--no-create-evidence Attach the report as evidence mapped to controls (default: enabled)

The command can either create a new compliance report from Wiz or process an existing CSV file. By default, it reuses existing compliance reports in Wiz to prevent accumulation of duplicate reports.

Prerequisite: the security plan must have the framework's catalogue controls attached —
assessments are written per control implementation, so a plan without the report's controls
assesses nothing.

What it writes:

  • One control assessment per control in the report (37 controls in a NIST report assess 37
    implementations).
  • Assets for the report's resources whose entity type is inventory-eligible — the same
    wizInventoryFilterBy type list the inventory pull uses, so compliance never creates an
    entity kind wiz inventory would not.
  • Issues for failed assessments (--create-issues, default on; --create-poams marks them
    POAMs).
  • With --create-evidence (default on), the report file is attached as evidence mapped to the
    assessed controls
    .
  • A report the command creates in Wiz is left in place with a weekly schedule, and later
    runs reuse it (--reuse-existing-reports, default on; --force-fresh-report creates a new one).
# Basic compliance sync
regscale wiz compliance_report -p "project-123" --regscale_id=5

# With POAM creation and fresh report
regscale wiz compliance_report \
  -p "project-123" \
  --regscale_id=5 \
  --create-poams \
  --force-fresh-report

# Process existing CSV report file
regscale wiz compliance_report \
  -p "project-123" \
  --regscale_id=5 \
  --report_file_path=/path/to/compliance_report.csv

Vulnerabilities Processing Workflow

wiz vulnerabilities pulls eight finding streams from Wiz, each with its own GraphQL query,
and writes one RegScale vulnerability per finding (the platform opens issues per the
vulnerabilityCreation setting):

StreamFamily name (for the filter options)Wiz source
VULNERABILITYvulnerabilityVulnerability findings (CVEs on workloads)
CONFIGURATIONconfiguration_findingCloud configuration findings
HOST_FINDINGhost_findingHost configuration findings
DATA_FINDINGdata_findingData findings
SECRET_FINDINGsecret_findingSecret findings
NETWORK_EXPOSURE_FINDINGnetwork_exposure_findingNetwork exposure findings
END_OF_LIFE_FINDINGend_of_life_findingEnd-of-life technology findings
EXCESSIVE_ACCESS_FINDINGexcessive_access_findingExcessive access findings

External attack surface exposures arrive through the NETWORK_EXPOSURE_FINDING stream; the
separate EXTERNAL_ATTACH_SURFACE stream is no longer pulled, because it returned the same
exposures a second time. Each stream lands once per finding; due dates follow the plan's compliance-settings SLA as
described under the issue workflow.

Filtering by family (REG-32996): --finding-families imports only the named families
(use the family names from the table above, not the stream names);
--exclude-finding-families imports everything else (e.g. --exclude-finding-families network_exposure for tenants that do not consider network exposures vulnerabilities). The
_finding suffix may be omitted and names are case-insensitive. A skipped family reports
nothing, so its findings already in RegScale may be closed as no longer reported when
mop-up runs.

SBOM Management

Download and attach SBOMs from Wiz reports:

regscale wiz attach_sbom \
  --regscale_ssp_id=5 \
  --report_id YOUR_WIZ_REPORT_ID \
  --standard CycloneDX

Options:

  • --client_id, -ci - Wiz Client ID (falls back to environment variable)
  • --client_secret, -cs - Wiz Client Secret (falls back to environment variable)
  • --regscale_ssp_id - RegScale SSP ID [required]
  • --report_id, -r - Wiz Report ID [required]
  • --standard, -s - SBOM standard: CycloneDX or SPDX (default: CycloneDX)

Evidence Management

Download a Wiz report and attach it to the RegScale Evidence locker:

regscale wiz add_report_evidence \
  --evidence_id 123 \
  --report_id YOUR_WIZ_REPORT_ID \
  --report_file_name evidence_report \
  --report_file_extension csv

Filtering Guide

Filtering Methods

1. Command-Line Filter Override

The most direct way to apply filters is using the --filter_by_override parameter:

regscale wiz issues --filter_by_override='{"status": ["OPEN"], "severity": ["HIGH", "CRITICAL"]}'

2. Configuration Variables

Set default filters using Wiz-specific configuration variables in your init.yaml file.

3. Environment Variables

Use environment variables to set filter configurations.

4. Programmatic Filtering

Apply filters directly in code when using the integration classes.

Project ID Auto-Injection

Important: When you use the -p or --wiz_project_id option, the project ID is automatically injected into your filter. You do NOT need to include it in your --filter_by_override or init.yaml configuration.

CommandAuto-Injected KeyFormat
inventory"project"String
issues"project"String
vulnerabilities"projectId"Array
# You provide a simple filter (no project ID needed):
regscale wiz vulnerabilities -p "abc123" -f '{"severity": ["CRITICAL", "HIGH"]}'

# CLI automatically creates this filter for the Wiz API:
# {"severity": ["CRITICAL", "HIGH"], "projectId": ["abc123"]}

Multi-Tenant Configuration

This enables easy multi-tenant deployments. Configure a single filter in init.yaml:

# init.yaml - DO NOT include projectId, it's added automatically per run
wizVulnerabilitiesFilterBy: '{"severity": ["CRITICAL", "HIGH"]}'

Then run for different tenants/projects:

regscale wiz vulnerabilities -p "tenant-a-project" --regscale_ssp_id 123
regscale wiz vulnerabilities -p "tenant-b-project" --regscale_ssp_id 456

Issue Filtering

By default, the Wiz issue integration applies this filter:

{
  "project": ["project-id"],
  "status": ["OPEN", "IN_PROGRESS", "RESOLVED", "REJECTED"]
}

Issues in all four statuses are synchronized. If your filter (wizIssueFilterBy or
--filter_by_override) has no status list, the integration adds all four statuses. If your
filter has a status list, the integration uses your list.

If your list does not include RESOLVED and REJECTED, Wiz does not return an issue after it
is resolved or rejected. Mop-up then closes the RegScale issue as remediated, and the rejection
reason does not reach RegScale.

Configuration Variable: wizIssueFilterBy

# init.yaml - project ID is auto-injected from --wiz_project_id, no need to include it
wizIssueFilterBy: '{"status": ["OPEN"], "severity": ["HIGH", "CRITICAL"]}'

Issue Filter Examples

# Filter by severity
regscale wiz issues \
  --wiz_project_id "project-123" \
  --regscale_ssp_id 456 \
  --filter_by_override='{"severity": ["HIGH", "CRITICAL"]}'

# Filter by status and time
regscale wiz issues \
  --wiz_project_id "project-123" \
  --regscale_ssp_id 456 \
  --filter_by_override='{"status": ["OPEN"], "updatedAt": {"after": "2023-06-14T14:07:06Z"}}'

# Complex filtering (project auto-injected from --wiz_project_id)
regscale wiz issues \
  --wiz_project_id "project-123" \
  --regscale_ssp_id 456 \
  --filter_by_override='{"status": ["OPEN", "IN_PROGRESS"], "severity": ["HIGH", "CRITICAL"], "search": "database"}'

Asset Filtering

The asset integration pulls only the entity types in the filter's type list. The default
wizInventoryFilterBy filter is the shipped list from the
Inventory Processing Workflow:

{
  "type": [
    "VIRTUAL_MACHINE", "VIRTUAL_DESKTOP", "KUBERNETES_CLUSTER", "VIRTUAL_MACHINE_IMAGE",
    "CONTAINER_IMAGE", "CONTAINER", "POD", "SERVERLESS", "SERVERLESS_PACKAGE", "APPLICATION",
    "WEB_SERVICE", "KUBERNETES_SERVICE", "CONTAINER_REGISTRY", "CONTAINER_SERVICE", "DATABASE",
    "DB_SERVER", "BUCKET", "STORAGE_ACCOUNT", "VOLUME", "FILE_SYSTEM_SERVICE", "BACKUP_SERVICE",
    "FIREWALL", "LOAD_BALANCER", "MESSAGING_SERVICE", "SECRET_CONTAINER"
  ]
}

A filter that you set replaces this list. If your filter has a type list, entities of other
types do not become assets. If your filter has no type key, no type filter is sent and Wiz
returns entities of every type.

Configuration Variable: wizInventoryFilterBy

# init.yaml - project ID is auto-injected from --wiz_project_id, no need to include it
wizInventoryFilterBy: '{"type": ["VIRTUAL_MACHINE", "DATABASE"]}'

Asset Filter Examples

# Filter by resource type
regscale wiz inventory \
  --wiz_project_id "project-123" \
  --regscale_ssp_id 456 \
  --filter_by_override='{"type": ["VIRTUAL_MACHINE", "DATABASE"]}'

# Filter by subscription (project auto-injected from --wiz_project_id)
regscale wiz inventory \
  --wiz_project_id "project-123" \
  --regscale_ssp_id 456 \
  --filter_by_override='{"subscriptionExternalId": ["sub-456"]}'

# Time-based filtering for incremental updates
regscale wiz inventory \
  --wiz_project_id "project-123" \
  --regscale_ssp_id 456 \
  --filter_by_override='{"updatedAt": {"after": "2023-06-14T14:07:06Z"}}'

Vulnerability Filtering

The vulnerabilities integration requires a project ID to be specified. The filter uses projectId as an array.

Configuration Variable: wizVulnerabilitiesFilterBy

# init.yaml - projectId is auto-injected from --wiz_project_id, no need to include it
wizVulnerabilitiesFilterBy: '{"severity": ["CRITICAL", "HIGH"]}'

Vulnerability Filter Examples

# Filter by severity
regscale wiz vulnerabilities \
  --wiz_project_id "project-123" \
  --regscale_ssp_id 456 \
  --filter_by_override='{"severity": ["CRITICAL", "HIGH"]}'

# Filter by CVE detection date
regscale wiz vulnerabilities \
  --wiz_project_id "project-123" \
  --regscale_ssp_id 456 \
  --filter_by_override='{"detectedAt": {"after": "2023-06-14T14:07:06Z"}}'

# Filter by exploit availability
regscale wiz vulnerabilities \
  --wiz_project_id "project-123" \
  --regscale_ssp_id 456 \
  --filter_by_override='{"hasExploit": true}'

Detailed Filter Parameters

Project and Subscription Filters

ParameterTypeDescriptionExample
projectarrayProject IDs, as a list["project-123"]
projectIdarrayMultiple project IDs["project-123", "project-456"]
subscriptionExternalIdarraySubscription external IDs["sub-123", "sub-456"]
providerUniqueIdarrayProvider unique identifiers["provider-123"]

Status Filters

ParameterTypeDescriptionValid Values
statusarrayIssue status filter["OPEN", "IN_PROGRESS", "RESOLVED", "REJECTED"]

Severity Filters

ParameterTypeDescriptionValid Values
severityarraySeverity level filter["CRITICAL", "HIGH", "MEDIUM", "LOW"]

Resource Type Filters

ParameterTypeDescriptionExample
typearrayResource type filter["VIRTUAL_MACHINE", "DATABASE", "CONTAINER"]

Time-based Filters

ParameterTypeDescriptionExample
updatedAtobjectFilter by update time{"after": "2023-06-14T14:07:06Z"}
createdAtobjectFilter by creation time{"before": "2023-12-31T23:59:59Z"}

Search Filters

ParameterTypeDescriptionExample
searchstringText search filter"database"

Filter Usage Examples

High-Priority Security Issues Only

regscale wiz issues \
  --wiz_project_id "prod-project" \
  --regscale_ssp_id 123 \
  --filter_by_override='{"status": ["OPEN"], "severity": ["HIGH", "CRITICAL"]}'

Recent Changes in Specific Resource Types

regscale wiz inventory \
  --wiz_project_id "prod-project" \
  --regscale_ssp_id 123 \
  --filter_by_override='{"type": ["DATABASE", "STORAGE_ACCOUNT"], "updatedAt": {"after": "2023-11-01T00:00:00Z"}}'

Multi-Project Vulnerability Scan

To scan multiple projects, explicitly specify projectId in the filter override (overrides the auto-injected single project):

regscale wiz vulnerabilities \
  --wiz_project_id "prod-project" \
  --regscale_ssp_id 123 \
  --filter_by_override='{"projectId": ["proj-1", "proj-2"], "severity": ["CRITICAL"]}'

Comprehensive Security Review

The project key is auto-injected from --wiz_project_id, so you only need to specify other filters:

{
  "status": ["OPEN", "IN_PROGRESS"],
  "severity": ["HIGH", "CRITICAL"],
  "type": ["DATABASE", "API_GATEWAY", "STORAGE_ACCOUNT"],
  "updatedAt": {"after": "2023-10-01T00:00:00Z"},
  "search": "encryption"
}

Setting Default Filters

In init.yaml

# Issue filtering defaults
wizIssueFilterBy: |
  {
    "status": ["OPEN", "IN_PROGRESS"],
    "severity": ["HIGH", "CRITICAL"]
  }

# Asset filtering defaults
wizInventoryFilterBy: |
  {
    "type": ["VIRTUAL_MACHINE", "DATABASE", "STORAGE_ACCOUNT"],
    "updatedAt": {"after": "2023-01-01T00:00:00Z"}
  }

Environment Variables

export WIZ_ISSUE_FILTER_BY='{"status": ["OPEN"], "severity": ["CRITICAL"]}'
export WIZ_INVENTORY_FILTER_BY='{"type": ["DATABASE", "VIRTUAL_MACHINE"]}'

Time-based Incremental Updates

Incremental (delta) pulls are off by default and planned to become the default in a later major release; they stayed opt-in on the 7.0.0 line. Turn
them on with wizIncrementalPulls:

wizIncrementalPulls: true
wizIncrementalRebaselineHours: 168  # Force a full pull once the last *full* pull is a week old

Each sync then asks Wiz only for what changed since its last successful run — inventory
filters on updatedAt, vulnerabilities on updatedAt, and issues on statusChangedAt.

The CLI keeps a separate watermark for every sync scope: the topic (inventory,
vulnerabilities or issues), the RegScale SSP, the Wiz project and the filter. Syncing project A
into one SSP and project B into another therefore never shares a watermark, and each scope's
first incremental run is a full pull. The watermarks are written to wizPullWatermarks in
init.yaml; leave that map to the CLI. Deleting it forces the next run of every sync to be a
full pull. A --dry-run never moves a watermark, because it writes nothing to RegScale.

The global keys used before (wizLastInventoryPull, wizLastVulnerabilityPull,
wizLastIssuePull and their *FullPull forms) are deprecated and no longer read. The CLI
warns while one still holds a timestamp; delete them.

Three behaviors follow from a delta result set being a deliberate subset of the project:

  • Nothing is closed for being absent. Close-findings-not-in-scan (mop-up) is disabled
    automatically for any run that pulls incrementally, because a delta says nothing about the
    findings it did not return. wizRetentionReconciliation is suppressed along with it: it closes
    issues by their absence from the sync, which a delta cannot distinguish from "unchanged".
    Findings that Wiz reports as resolved still close on a delta run, because the status change
    is itself a change the delta returns. Closing by absence is not switched off, only deferred
    to the next full pull — which wizIncrementalRebaselineHours guarantees happens periodically.
  • Assets missing from a delta are not marked Inactive. A full inventory sync marks assets
    that are no longer in Wiz Inactive. A delta inventory sync turns that off, because it only
    returns the assets that changed; the next full pull marks the assets that really left Wiz.
  • Cached pages are never reused. A delta run always calls Wiz, so it cannot skip records
    that arrived between the cached run and now.

A watermark only moves forward after a run that read its whole window and wrote every
record to RegScale: if a query fails, a result type is skipped, or any record fails to save,
the watermark stays put and the next run re-reads the same window. With incremental pulls on,
every run reads Wiz rather than a cached copy, full pulls included, because the watermark it
records says RegScale is current as of that run.

wizIncrementalRebaselineHours is the interval at which the CLI re-baselines with a full
pull, so a record a delta missed cannot stay missing indefinitely, and findings and assets
that left Wiz without a status change get closed. The default of 168 hours (a week) keeps a
daily sync incremental between re-baselines. Wiz recommends incremental pulls for daily
updates and full pulls for the initial baseline and periodic full assessments (WIN API docs,
"Reports"); lower it if absent findings must close sooner. It is
separate from wizFullPullLimitHours, which only limits how old cached Wiz data may be. It is
measured against each scope's last full pull, written only when a full pull of that scope
completes — not against the delta watermark above. The delta watermark cannot serve that purpose: it carries the newest updatedAt /
statusChangedAt the run actually saw, so on a quiet project it reads hours or days old while
the sync itself ran minutes ago. If no full-pull timestamp is recorded yet, the next run is a
full pull to establish one.

Filtering Best Practices

  1. Start with broad filters and gradually narrow them down
  2. Use time-based filtering for large environments to reduce data volume
  3. Combine multiple filter types for precise data selection
  4. Test filters before production with a small dataset first
  5. Use specific project IDs when possible for better performance
  6. Document your filters for different environments (production, development, security audit)

Scanner Integration Base Filtering

The Wiz integration extends the base ScannerIntegration class, which provides additional filtering capabilities:

VariableDescriptionDefaultOptions
issueCreationHow issues are created"Consolidated""PerAsset", "Consolidated"
vulnerabilityCreationVulnerability handling"IssueCreation""IssueCreation", "PoamCreation" ("NoIssue" is deprecated and treated as "IssueCreation")

These are set in init.yaml (there is no command-line override for them).

ingestClosedIssues is deprecated and no integration reads it. The Wiz issue pull already
fetches resolved and rejected issues. Delete the key from init.yaml. To pull only some
statuses, set a status list in the filter:

regscale wiz issues \
  --wiz_project_id "project-123" \
  --regscale_ssp_id 456 \
  --filter_by_override='{"status": ["OPEN", "RESOLVED"]}'

Filter Troubleshooting

  1. No results returned: Check if your filter criteria are too restrictive
  2. Too many results: Add more specific filters like severity or time ranges
  3. Authentication errors: Ensure your Wiz credentials are correctly configured
  4. Invalid filter format: Verify JSON syntax in filter strings

Enable debug logging to see applied filters:

# --debug is a global option and goes before the command group
regscale --debug wiz issues \
  --regscale_ssp_id 456 \
  --filter_by_override='{"status": ["OPEN"]}'

STIG Mapper

The STIG Mapper module automatically maps STIGs to assets based on configurable rules. The scanner
framework loads the rules file named by the root-level stigMapperFile variable in your init.yaml
(default: stig_mapper_rules.json in the current working directory); if that file does not exist,
STIG mapping is skipped:

stigMapperFile: /path/to/stig_mapper_rules.json

Note: wizStigMapperFile appears in the default init.yaml template but is not read by the
mapper. The rules can also be applied on demand with
regscale stig_mapper run --json-file <rules.json> --regscale_id <id> --regscale_module securityplans.

STIG Mapper Rules Format

The rules file uses JSON with comparator-based matching against asset properties:

{
    "rules": [
        {
            "stig": "Windows 2012 Configuration STIG",
            "comparators": [
                {"comparator": "contains", "value": "Windows 2012", "property": "name"},
                {"comparator": "notin", "value": "Windows 2012 Account Access Group", "property": "name"}
            ]
        },
        {
            "stig": "Network Security STIG",
            "comparators": [
                {"comparator": "startswith", "value": "Kubernetes", "property": "name"},
                {"comparator": "endswith", "value": "Security", "property": "name"}
            ]
        }
    ]
}

Available Comparators

ComparatorDescription
equalsExact string match
containsString contains value
startswithString starts with value
endswithString ends with value
notinString does not contain value
inString is present in value
ninString is not present in value
gt, lt, gte, lte, neComparison operators

Rules can match against any asset property including name, operatingSystem, manufacturer, description, and others.


Did this page help you?