---
title: "Automate (CI/CD)"
description: "Using StackHawk in your CI/CD Pipeline Helps Find Security Bugs before they reach Production."
url: https://docs.stackhawk.com/integrations/ci-cd/
---

# Automate (CI/CD)

It’s great to know you can scan your services at any time and get a read on potential vulnerabilities. But why not scan every time you check in code? We made it simple to add HawkScan to your CI/CD pipeline. This means you can catch new issues before your code goes live.

This page describes a general approach to integrating HawkScan into your pipeline. But if you’d rather dive right in to configuring your CI/CD system, check below for our getting started guides. If we don’t have your system listed, let us know so we can add it!

[![AWS Code Services logo](https://docs.stackhawk.com/images/integrations/logos/code-services-tile.svg)](https://docs.stackhawk.com/integrations/ci-cd/aws-code-services/)

### [AWS Code Services](https://docs.stackhawk.com/integrations/ci-cd/aws-code-services/)

[![Atlassian Bamboo logo](https://docs.stackhawk.com/images/integrations/logos/bamboo-tile.svg)](https://docs.stackhawk.com/integrations/ci-cd/bamboo/)

### [Atlassian Bamboo](https://docs.stackhawk.com/integrations/ci-cd/bamboo/)

[![Azure Pipelines logo](https://docs.stackhawk.com/images/integrations/logos/azure-tile.svg)](https://docs.stackhawk.com/integrations/ci-cd/azure/)

### [Azure Pipelines](https://docs.stackhawk.com/integrations/ci-cd/azure/)

[![Bitbucket Pipelines logo](https://docs.stackhawk.com/images/integrations/logos/bitbucket-tile.svg)](https://docs.stackhawk.com/integrations/ci-cd/bitbucket-pipelines/)

### [Bitbucket Pipelines](https://docs.stackhawk.com/integrations/ci-cd/bitbucket-pipelines/)

[![Buildkite logo](https://docs.stackhawk.com/images/integrations/logos/buildkite-tile.svg)](https://docs.stackhawk.com/integrations/ci-cd/buildkite/)

### [Buildkite](https://docs.stackhawk.com/integrations/ci-cd/buildkite/)

[![CircleCI logo](https://docs.stackhawk.com/images/integrations/logos/circleci-tile.svg)](https://docs.stackhawk.com/integrations/ci-cd/circleci/)

### [CircleCI](https://docs.stackhawk.com/integrations/ci-cd/circleci/)

[![Concourse CI logo](https://docs.stackhawk.com/images/integrations/logos/concourse-ci-tile.svg)](https://docs.stackhawk.com/integrations/ci-cd/concourse-ci/)

### [Concourse CI](https://docs.stackhawk.com/integrations/ci-cd/concourse-ci/)

[![GitHub Actions logo](https://docs.stackhawk.com/images/integrations/logos/github-tile.svg)](https://docs.stackhawk.com/integrations/ci-cd/github-actions/)

### [GitHub Actions](https://docs.stackhawk.com/integrations/ci-cd/github-actions/)

[![GitLab CI/CD logo](https://docs.stackhawk.com/images/integrations/logos/gitlab-tile.svg)](https://docs.stackhawk.com/integrations/ci-cd/gitlab/)

### [GitLab CI/CD](https://docs.stackhawk.com/integrations/ci-cd/gitlab/)

[![Harness logo](https://docs.stackhawk.com/images/integrations/logos/harness-tile.svg)](https://docs.stackhawk.com/integrations/ci-cd/harness/)

### [Harness](https://docs.stackhawk.com/integrations/ci-cd/harness/)

[![Jenkins logo](https://docs.stackhawk.com/images/integrations/logos/jenkins-tile.svg)](https://docs.stackhawk.com/integrations/ci-cd/jenkins/)

### [Jenkins](https://docs.stackhawk.com/integrations/ci-cd/jenkins/)

[![Spinnaker logo](https://docs.stackhawk.com/images/integrations/logos/spinnaker-tile.svg)](https://docs.stackhawk.com/integrations/ci-cd/spinnaker/)

### [Spinnaker](https://docs.stackhawk.com/integrations/ci-cd/spinnaker/)

[![Travis CI logo](https://docs.stackhawk.com/images/integrations/logos/travis-tile.svg)](https://docs.stackhawk.com/integrations/ci-cd/travisci/)

### [Travis CI](https://docs.stackhawk.com/integrations/ci-cd/travisci/)

## Start Simple

We recommend putting a fast, simple scan into your pipeline initially. You want to iterate quickly until you have your scans consistently working, and then you can add detail. For example, we typically start with a HawkScan configuration such as this:

```yaml title="stackhawk.yml"
app:
  applicationId: xxXXXXXX-xXXX-xxXX-XXxX-xXXxxXXXXxXX
  host: http://example.com
  env: Development

hawk:
  startupTimeoutMinutes: 1
  spider:
    base: false
```

With this configuration, HawkScan hits the application running at `http://example.com` in the Development environment, and it makes no attempt to discover routes other than `/`.

In particular, you will want to remove the `hawk.spider.base: false` configuration, which prevents HawkScan from crawling your app to find routes.

Once your scan is working well, you can expand your configuration to discover routes, authenticate, and so forth.

## Hide your Secrets

You should take care to hide any secrets, such as your StackHawk API key, as well as usernames and passwords you may use for authenticated scans against your application. These should be kept out of source control, in a secure secrets store.

Many build systems have some method for storing secrets and retrieving them as environment variables during a job. For example, Jenkins has a [Credentials Plugin](https://docs.cloudbees.com/docs/cloudbees-ci/latest/cloud-secure-guide/injecting-secrets), CircleCI has secure [Environment Variables](https://circleci.com/docs/guides/security/set-environment-variable/), and TravisCI supports secret [Environment Variables](https://docs.travis-ci.com/user/environment-variables#defining-variables-in-repository-settings).

Alternatively you can use general purpose secrets stores such as Hashicorp [Vault](https://www.vaultproject.io/) or AWS [Parameter Store](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store).

In your build pipeline, you will extract secrets as environment variables, and configure HawkScan to inject them into the scan at runtime.

Suppose you have three secrets in three variables, `HAWK_API_KEY`, `SCAN_USERNAME`, and `SCAN_PASSWORD`. Here is a simple configuration that imports the username and password, with a default username of “jdoe”.

```yaml title="stackhawk.yml"
app:
  applicationId: xxXXXXXX-xXXX-xxXX-XXxX-xXXxxXXXXxXX
  host: http://example.com
  env: Development
  authentication:
    loggedInIndicator: "\\Qsigned in as\\E"
    loggedOutIndicator: "\\Qlog in\\E"
    loginPath: /login
    usernameField: User
    scanUsername: ${SCAN_USERNAME:jdoe}
    scanPassword: ${SCAN_PASSWORD}
```

At runtime, the `hawk` CLI reads `SCAN_USERNAME` and `SCAN_PASSWORD` straight from the environment of the step that runs it, so you only need to pass your API key:

```bash
hawk --api-key="${HAWK_API_KEY}" scan stackhawk.yml
```

If you run HawkScan as a Docker container instead, pass each variable into the container:

```bash
docker run -v $(pwd):/hawk -t \
  -e API_KEY="${HAWK_API_KEY}" \
  -e SCAN_USERNAME="${SCAN_USERNAME}" \
  -e SCAN_PASSWORD="${SCAN_PASSWORD}" \
  stackhawk/hawkscan
```

## Requirements

There are really just two requirements for running HawkScan in your pipeline – the `hawk` CLI (or Docker) and access to your running application.

### The `hawk` CLI

As of HawkScan 6.0.0, `hawk` ships as a self-contained native binary with no Docker or Java dependency, which makes it the simplest way to add HawkScan to most pipelines. Install it with the hawk CLI [install script](https://docs.stackhawk.com/stackhawk-cli/#install-with-a-script) for your runner’s shell, put it on the PATH, and run the scan:

**Tab: Linux/macOS**

```bash
# Optional: pin a version (6.0.0 or later). Leave it unset to install the latest release.
# export HAWK_INSTALL_VERSION=6.6.0
curl -fsSL https://download.stackhawk.com/hawk/install.sh | sh
export PATH="$HOME/.hawk/bin:$PATH"
hawk --api-key="${HAWK_API_KEY}" scan stackhawk.yml
```

**Tab: Windows (PowerShell)**

```powershell
# Optional: pin a version (6.0.0 or later). Leave it unset to install the latest release.
# $env:HAWK_INSTALL_VERSION = '6.6.0'
irm https://download.stackhawk.com/hawk/install.ps1 | iex
$env:Path = "$env:USERPROFILE\.hawk\bin;$env:Path"
hawk --api-key="$env:HAWK_API_KEY" scan stackhawk.yml
```

**Tab: Windows (cmd)**

```bat
rem Optional: pin a version (6.0.0 or later). Leave it unset to install the latest release.
rem set "HAWK_INSTALL_VERSION=6.6.0"
curl -fsSL -o "%TEMP%\hawk-install.bat" https://download.stackhawk.com/hawk/install.bat && call "%TEMP%\hawk-install.bat"
set "PATH=%USERPROFILE%\.hawk\bin;%PATH%"
hawk --api-key="%HAWK_API_KEY%" scan stackhawk.yml
```

The script checks the download’s SHA-256 checksum before it installs anything, and it needs no `sudo` or administrator access. It installs to `~/.hawk/bin` (`%USERPROFILE%\.hawk\bin` on Windows); set `HAWK_INSTALL_DIR` to choose another directory.

By default, every run installs the latest HawkScan release, so your pipeline picks up scanner fixes and new tests automatically. To run the same version every time, set `HAWK_INSTALL_VERSION` as shown in the commented lines.

#### Put `hawk` on the PATH

The install script never changes the PATH, so `curl ... | sh && hawk scan` fails with `hawk: command not found`. How you add the install directory depends on whether later commands run in the same shell:

| Where `hawk scan` runs | Add this after the install |
| - | - |
| The same shell as the install: a GitLab job’s `before_script` and `script`, a Bitbucket Pipelines step, a Travis CI job, an AWS CodeBuild `buildspec.yml`, a single Buildkite `command`, or a single Jenkins `sh` block | `export PATH="$HOME/.hawk/bin:$PATH"` |
| A later GitHub Actions step | `echo "$HOME/.hawk/bin" >> "$GITHUB_PATH"` |
| A later CircleCI `run` step | `echo 'export PATH="$HOME/.hawk/bin:$PATH"' >> "$BASH_ENV"` |
| A later Azure Pipelines step | `echo "##vso[task.prependpath]$HOME/.hawk/bin"` |
| A later Jenkins `sh` step | Repeat the `export PATH=...` line in that step |
| The same PowerShell session | `$env:Path = "$env:USERPROFILE\.hawk\bin;$env:Path"` |

Each fresh install downloads a binary of about 320 MB. If your CI system caches directories between runs, you can cache `~/.hawk/bin` keyed on the output of `curl -fsSL https://api.stackhawk.com/hawkscan/version`, and skip the install script when the cache is restored.

For manual downloads, checksum verification, and air-gapped installs, see [Install Programmatically](https://docs.stackhawk.com/stackhawk-cli/#install-programmatically).

### Docker (Alternative)

HawkScan is also distributed as a Docker image, so if you’d rather not install the CLI directly, Docker works too:

```
docker run -v $(pwd):/hawk -t \
  -e API_KEY="${HAWK_API_KEY}" \
  stackhawk/hawkscan
```

### Access to your Running Application

Your build system needs to be able to reach your running application in order to test it. This should be straightforward if your test environment is public, or collocated with your build system. Otherwise you may need to open up access via security groups or firewall rules to allow your build system to reach it.

## Summary

That’s all there is to it! Start with a simple scan that will run quickly so you can iterate. Take care to hide your secrets, such as your StackHawk API key. Install the `hawk` CLI with the install script, or use Docker, and put it on the PATH of the step that runs the scan. And finally, provide access to your running application.
