> For the complete documentation index, see [llms.txt](https://docs.nullify.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.nullify.ai/tools/defender-action.md).

# Defender GitHub Action

The Nullify Defender GitHub Action (`nullify-platform/nullify-defender-action`) scans your dependencies for vulnerabilities, malware, and unpinned versions using Nullify Defender. It runs as a composite action that downloads the Nullify Defender CLI, scans your repository, and surfaces results as GitHub annotations, SARIF (Code Scanning), a pull-request comment, and a step summary.

## Quick start

```yaml
name: Nullify Defender Scan
on:
  pull_request:
  push:
    branches: [main]

permissions:
  contents: read
  security-events: write
  pull-requests: write

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: nullify-platform/nullify-defender-action@v1
        with:
          api-key: ${{ secrets.NULLIFY_API_KEY }}
```

## Required permissions

| Permission               | Why it is needed                           |
| ------------------------ | ------------------------------------------ |
| `contents: read`         | Check out the repository code to scan.     |
| `security-events: write` | Upload SARIF results to Code Scanning.     |
| `pull-requests: write`   | Post the summary comment on pull requests. |

## Inputs

| Name                | Required | Default                                | Description                                                                                      |
| ------------------- | -------- | -------------------------------------- | ------------------------------------------------------------------------------------------------ |
| `api-key`           | Yes      |                                        | Nullify API key.                                                                                 |
| `api-url`           | No       | `https://api.nullify.ai/vuln-database` | Nullify API base URL.                                                                            |
| `scan-mode`         | No       | `auto`                                 | Scan mode: `full`, `diff`, or `auto`. `auto` uses `diff` for pull requests and `full` otherwise. |
| `resolve`           | No       | `false`                                | Force re-resolution of dependencies before scanning.                                             |
| `policy`            | No       |                                        | Override which severities cause failures (e.g. `critical,high,malware`).                         |
| `fail-on-findings`  | No       | `true`                                 | Fail the action if any findings are detected.                                                    |
| `output-format`     | No       | `github-annotations`                   | Output format: `github-annotations`, `sarif`, or `json`.                                         |
| `working-directory` | No       | `.`                                    | Working directory for the scan.                                                                  |
| `cli-version`       | No       | `latest`                               | Version of the Nullify Defender CLI to use.                                                      |

## Outputs

| Name             | Description                             |
| ---------------- | --------------------------------------- |
| `findings-count` | Total number of findings.               |
| `critical-count` | Number of critical severity findings.   |
| `high-count`     | Number of high severity findings.       |
| `medium-count`   | Number of medium severity findings.     |
| `low-count`      | Number of low severity findings.        |
| `malware-count`  | Number of malware findings.             |
| `unpinned-count` | Number of unpinned dependency findings. |
| `sarif-file`     | Path to the generated SARIF file.       |

## Features

* **Automatic scan mode** — runs a diff scan on pull requests and a full scan on pushes when `scan-mode` is left at `auto`.
* **SARIF upload** — findings are uploaded to GitHub Code Scanning and appear in the repository's **Security** tab.
* **PR comments** — posts a summary table on pull requests, updating the existing comment on re-runs instead of stacking new ones.
* **Configurable policy** — override which severity levels cause the workflow to fail via the `policy` input.
* **Step summary** — results are written to the GitHub Actions step summary.

## Advanced usage

### Custom policy

Only fail on critical, high, and malware findings:

```yaml
- uses: nullify-platform/nullify-defender-action@v1
  with:
    api-key: ${{ secrets.NULLIFY_API_KEY }}
    policy: "critical,high,malware"
```

### Force dependency resolution

Re-resolve all dependencies before scanning:

```yaml
- uses: nullify-platform/nullify-defender-action@v1
  with:
    api-key: ${{ secrets.NULLIFY_API_KEY }}
    resolve: "true"
```

### Scan a subdirectory

```yaml
- uses: nullify-platform/nullify-defender-action@v1
  with:
    api-key: ${{ secrets.NULLIFY_API_KEY }}
    working-directory: "packages/backend"
```

### Pin the CLI version

```yaml
- uses: nullify-platform/nullify-defender-action@v1
  with:
    api-key: ${{ secrets.NULLIFY_API_KEY }}
    cli-version: "v0.5.0"
```

### Non-blocking scan

Run the scan without failing the workflow:

```yaml
- uses: nullify-platform/nullify-defender-action@v1
  with:
    api-key: ${{ secrets.NULLIFY_API_KEY }}
    fail-on-findings: "false"
```

### Use outputs in subsequent steps

```yaml
- uses: nullify-platform/nullify-defender-action@v1
  id: defender
  with:
    api-key: ${{ secrets.NULLIFY_API_KEY }}
    fail-on-findings: "false"

- name: Check results
  run: |
    echo "Total findings: ${{ steps.defender.outputs.findings-count }}"
    echo "Critical: ${{ steps.defender.outputs.critical-count }}"
    if [ "${{ steps.defender.outputs.critical-count }}" -gt 0 ]; then
      echo "::error::Critical vulnerabilities found!"
      exit 1
    fi
```
