Documentation
Guides
Exporter Configuration

Exporter Configuration

Exporters pipe security scan findings directly into your issue trackers and alerting systems, so vulnerabilities discovered by NAT automatically become work items your team can act on.

How exporters work

After a scan completes, NAT sends each finding above the configured minimum severity to one or more exporters. Each exporter is a named plugin that knows how to authenticate with and create records in a specific system.

Basic usage

nat security-scan --spec ./openapi.yaml --base-url https://api.example.com \
  --export <exporter-name> \
  --export-config key=value \
  --export-config key2=value2

Filtering by severity

Use --export-min-severity to only export findings at or above a given severity level:

nat security-scan --spec ./openapi.yaml --base-url https://api.example.com \
  --export github-issues \
  --export-config token=$GITHUB_TOKEN \
  --export-config repo=myorg/myrepo \
  --export-min-severity high

Valid values are informational, low, medium, high, and critical.

Custom exporter directories

To load exporters from a local directory in addition to the built-ins:

nat security-scan --spec ./openapi.yaml --base-url https://api.example.com \
  --export my-custom-exporter \
  --exporters-dir ./exporters
⚠️

Never paste tokens or passwords directly into commands. Use environment variables (e.g., $GITHUB_TOKEN) so credentials are not stored in your shell history or CI logs.


GitHub Issues (github-issues)

Creates a GitHub Issue for each finding. Supports deduplication so re-running a scan does not create duplicate issues.

Config

KeyRequiredDescription
tokenRequiredGitHub personal access token (or GITHUB_TOKEN in Actions). Needs repo scope.
repoRequiredRepository in owner/repo format, e.g. myorg/myrepo.
labelsOptionalComma-separated list of labels to apply to each issue.
assigneesOptionalComma-separated list of GitHub usernames to assign.
deduplicateOptionalSet to true to skip creating an issue when one with the same finding title is already open. Default: false.

Example

nat security-scan --spec ./openapi.yaml --base-url https://api.example.com \
  --export github-issues \
  --export-config token=$GITHUB_TOKEN \
  --export-config repo=myorg/myrepo \
  --export-config labels=security,nat \
  --export-config assignees=alice,bob \
  --export-config deduplicate=true

When running inside GitHub Actions, GITHUB_TOKEN is available automatically. Set deduplicate=true to keep your issue tracker tidy on repeated scans.


Jira Cloud (jira)

Creates a Jira issue for each finding using the Jira Cloud REST API.

Config

KeyRequiredDescription
base_urlRequiredYour Jira Cloud base URL, e.g. https://myorg.atlassian.net.
project_keyRequiredThe Jira project key where issues will be created, e.g. SEC.
emailRequiredEmail address of the Atlassian account used for authentication.
api_tokenRequiredAtlassian API token. Generate one at id.atlassian.com (opens in a new tab).
issue_typeOptionalIssue type name, e.g. Bug, Task, Story. Default: Bug.
componentOptionalComponent name to assign to each issue.

Example

nat security-scan --spec ./openapi.yaml --base-url https://api.example.com \
  --export jira \
  --export-config base_url=https://myorg.atlassian.net \
  --export-config project_key=SEC \
  --export-config email=$JIRA_EMAIL \
  --export-config api_token=$JIRA_API_TOKEN \
  --export-config issue_type=Bug \
  --export-config component=API

GitLab Issues (gitlab)

Creates a GitLab issue for each finding using the GitLab REST API. Works with both GitLab.com and self-hosted GitLab instances.

Config

KeyRequiredDescription
gitlab_urlRequiredBase URL of your GitLab instance, e.g. https://gitlab.com or https://gitlab.myorg.com.
project_idRequiredNumeric ID of the GitLab project. Find it on the project's General Settings page.
private_tokenRequiredGitLab personal access token with api scope.
labelsOptionalComma-separated list of label names to apply to each issue.
assignee_idsOptionalComma-separated list of numeric GitLab user IDs to assign.
confidentialOptionalSet to true to mark issues as confidential. Default: false.

Example

nat security-scan --spec ./openapi.yaml --base-url https://api.example.com \
  --export gitlab \
  --export-config gitlab_url=https://gitlab.com \
  --export-config project_id=12345678 \
  --export-config private_token=$GITLAB_TOKEN \
  --export-config labels=security,vulnerability \
  --export-config confidential=true

Linear (linear)

Creates a Linear issue for each finding using the Linear GraphQL API.

Config

KeyRequiredDescription
api_keyRequiredLinear API key. Generate one in your Linear workspace settings under API.
team_idRequiredThe ID of the Linear team where issues will be created.
project_idOptionalLinear project ID to associate issues with a specific project.
assignee_idOptionalLinear user ID to assign each issue to.
label_idsOptionalComma-separated list of Linear label IDs to apply.

Example

nat security-scan --spec ./openapi.yaml --base-url https://api.example.com \
  --export linear \
  --export-config api_key=$LINEAR_API_KEY \
  --export-config team_id=TEAM_ID \
  --export-config project_id=PROJECT_ID \
  --export-config label_ids=LABEL_ID_1,LABEL_ID_2

To find your team ID and project ID, use the Linear API explorer at https://api.linear.app/graphql or check the URL when viewing a team or project in the Linear web app.


Azure DevOps (azure-devops)

Creates an Azure DevOps work item for each finding.

Config

KeyRequiredDescription
organizationRequiredAzure DevOps organization name, e.g. myorg from https://dev.azure.com/myorg.
projectRequiredAzure DevOps project name.
patRequiredAzure DevOps personal access token with Work Items (Read & Write) scope.
work_item_typeOptionalWork item type, e.g. Bug, Issue, Task. Default: Bug.
area_pathOptionalArea path for the work item, e.g. MyProject\Security.
iteration_pathOptionalIteration (sprint) path, e.g. MyProject\Sprint 5.
assigneeOptionalEmail address of the user to assign work items to.

Example

nat security-scan --spec ./openapi.yaml --base-url https://api.example.com \
  --export azure-devops \
  --export-config organization=myorg \
  --export-config project=MyProject \
  --export-config pat=$AZURE_DEVOPS_PAT \
  --export-config work_item_type=Bug \
  --export-config area_path=MyProject\\Security \
  --export-config assignee=alice@myorg.com

Shortcut (shortcut)

Creates a Shortcut (formerly Clubhouse) story for each finding.

Config

KeyRequiredDescription
api_tokenRequiredShortcut API token. Find it in Settings β†’ API Tokens.
project_idRequiredNumeric ID of the Shortcut project.
group_idOptionalID of the Shortcut team (group) to associate with each story.
epic_idOptionalID of an existing epic to add stories to.
workflow_state_idOptionalID of the workflow state (column) to place new stories in.
story_typeOptionalStory type: bug, feature, or chore. Default: bug.
labelsOptionalComma-separated list of label names to apply.

Example

nat security-scan --spec ./openapi.yaml --base-url https://api.example.com \
  --export shortcut \
  --export-config api_token=$SHORTCUT_API_TOKEN \
  --export-config project_id=12345 \
  --export-config story_type=bug \
  --export-config labels=security,nat \
  --export-config epic_id=67890

PagerDuty (pagerduty)

Sends each finding as a PagerDuty alert, triggering your on-call escalation policies for critical security issues.

Config

KeyRequiredDescription
routing_keyRequiredPagerDuty Events API v2 integration key (32-character string).
service_idOptionalPagerDuty service ID to associate events with.
escalation_policyOptionalEscalation policy ID to use when creating incidents.
sourceOptionalLogical name of the source system. Default: nat-security-scan.
componentOptionalComponent of the source machine that triggered the event.
groupOptionalLogical grouping for the event, e.g. api-gateway.
playbook_urlOptionalURL to a runbook or playbook for responders.
artifact_urlOptionalURL to supporting artifact (e.g., scan report).
timeoutOptionalHTTP request timeout in seconds. Default: 30.

Example

nat security-scan --spec ./openapi.yaml --base-url https://api.example.com \
  --export pagerduty \
  --export-config routing_key=$PAGERDUTY_ROUTING_KEY \
  --export-config source=production-api \
  --export-config component=auth-service \
  --export-min-severity critical
⚠️

PagerDuty exporters are best combined with --export-min-severity critical or --export-min-severity high to avoid paging on-call engineers for low-severity informational findings.


ServiceNow (servicenow)

Creates a ServiceNow incident or record for each finding. Supports both OAuth token and username/password authentication.

Config

KeyRequiredDescription
instance_urlRequiredYour ServiceNow instance URL, e.g. https://myorg.service-now.com.
oauth_tokenRequired (or username+password)OAuth 2.0 bearer token for authentication.
usernameRequired (or oauth_token)ServiceNow username for basic authentication.
passwordRequired with usernameServiceNow password for basic authentication.
tableOptionalServiceNow table to create records in. Default: incident.
categoryOptionalCategory value for the created record, e.g. software.
field_mappingOptionalJSON string mapping NAT finding fields to ServiceNow fields.

Authentication modes

ServiceNow supports two authentication modes β€” use whichever matches your instance configuration:

OAuth token (recommended):

nat security-scan --spec ./openapi.yaml --base-url https://api.example.com \
  --export servicenow \
  --export-config instance_url=https://myorg.service-now.com \
  --export-config oauth_token=$SERVICENOW_TOKEN \
  --export-config table=incident \
  --export-config category=software

Username and password:

nat security-scan --spec ./openapi.yaml --base-url https://api.example.com \
  --export servicenow \
  --export-config instance_url=https://myorg.service-now.com \
  --export-config username=$SERVICENOW_USER \
  --export-config password=$SERVICENOW_PASS \
  --export-config table=incident

You must provide either oauth_token or both username and password. Providing both sets of credentials will cause a validation error.


Webhook (webhook)

POSTs a JSON payload to any HTTP or HTTPS endpoint for each finding, enabling integration with any system that accepts webhooks.

Config

KeyRequiredDescription
webhook_urlRequiredThe full URL to POST findings to. Must start with http:// or https://.
auth_headerOptionalValue for the Authorization header, e.g. Bearer my-token.
custom_headersOptionalJSON string of additional headers to include, e.g. {"X-Source": "nat"}.
hmac_secretOptionalSecret key for HMAC-SHA256 request signing. The signature is sent in the X-NAT-Signature header.
include_report_contextOptionalSet to true to include full scan metadata alongside each finding. Default: false.
batch_modeOptionalSet to true to send all findings in a single request as a JSON array instead of one request per finding. Default: false.
timeoutOptionalHTTP request timeout in seconds. Default: 30.

Example

nat security-scan --spec ./openapi.yaml --base-url https://api.example.com \
  --export webhook \
  --export-config webhook_url=https://hooks.example.com/nat-findings \
  --export-config auth_header=Bearer\ $WEBHOOK_SECRET \
  --export-config hmac_secret=$HMAC_KEY \
  --export-config include_report_context=true \
  --export-config batch_mode=true
⚠️

The webhook_url must begin with http:// or https://. A URL that does not pass this validation will cause the export to fail immediately without sending any findings.

Use hmac_secret to verify the authenticity of incoming payloads on your server. Compare the value in the X-NAT-Signature header against an HMAC-SHA256 of the raw request body using your secret.


Using multiple exporters

You can specify --export more than once to send findings to multiple destinations in a single scan:

nat security-scan --spec ./openapi.yaml --base-url https://api.example.com \
  --export github-issues \
  --export-config token=$GITHUB_TOKEN \
  --export-config repo=myorg/myrepo \
  --export jira \
  --export-config base_url=https://myorg.atlassian.net \
  --export-config project_key=SEC \
  --export-config email=$JIRA_EMAIL \
  --export-config api_token=$JIRA_API_TOKEN \
  --export-min-severity high

When using multiple exporters, --export-min-severity and --exporters-dir apply to all exporters in the command.

Next steps

Was this helpful?