Security AWS

Gitleaks on AWS User Guide

| Product: Gitleaks on AWS

Overview

Gitleaks is the widely used open source scanner for hardcoded secrets. It reads your source code, configuration files and git commit history and reports every hardcoded API key, cloud access key, token, password and private key it finds, using an embedded ruleset of more than 160 detection rules that recognise the credential formats of the major cloud and SaaS providers.

It works in two complementary modes. gitleaks git walks the entire commit history of a repository, so a secret that was committed once and later deleted is still caught - the exact case a working-tree scan misses. gitleaks dir scans plain files and working trees. Every finding names the rule, the file, the line and the offending value, and results can be written as JSON or SARIF for a code review, a dashboard or a pipeline gate.

The cloudimg image is a ready-to-run secret-scanning host, not just the binary. The detection rules are compiled into the scanner, so it needs no network egress at all - this instance can sit in a locked-down subnet with no outbound internet and still scan. git is preinstalled so history scanning works out of the box, a daily timer scans a directory you choose and writes machine-readable JSON and SARIF reports, and read-only self-test fixtures let you prove detection works on your own instance. Backed by 24/7 cloudimg support.

What is included:

  • Gitleaks 8.30.1 (/usr/local/bin/gitleaks), installed from the official release tarball and verified against the upstream SHA256 checksum
  • git preinstalled, so gitleaks git history scanning works immediately
  • gitleaks-scan-run + gitleaks-scan.timer - a daily scan of your projects, writing JSON + SARIF with latest.* symlinks for CI pickup
  • Read-only self-test fixtures under /usr/share/gitleaks/fixtures (a leaky directory, a leaky git repo and a clean directory) so you can prove the scanner works on your own instance
  • An appliance configuration at /etc/gitleaks/scan.conf
  • 24/7 cloudimg support

This is a command-line product: no web UI, no listening service, no admin account and no password. SSH on port 22 is the only open port, and the SSH key you choose at launch is the only way in.

Prerequisites

  • An AWS account with permission to launch EC2 instances
  • An EC2 key pair for SSH access
  • A security group that allows inbound 22/tcp from your management network. No inbound application ports are needed, and no outbound internet is needed for scanning.

m5.large (2 vCPU / 8 GiB RAM) is a comfortable default; scanning very large monorepos or deep histories benefits from more CPU and RAM.

Step 1 - Launch from the AWS Marketplace

Open the product in the AWS Marketplace, choose Continue to Subscribe, accept the terms, then Continue to Configuration and Continue to Launch. Pick your region, instance type, key pair and a security group that allows SSH (22) from your management network, then launch.

Step 2 - Launch from the AWS CLI

aws ec2 run-instances \
  --image-id <ami-id-for-your-region> \
  --instance-type m5.large \
  --key-name <your-key-pair> \
  --security-group-ids <sg-allowing-ssh> \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=gitleaks}]'

Step 3 - Connect to your instance

Connect over SSH as the login user for your operating system variant:

OS variant SSH login user
Ubuntu 24.04 LTS ubuntu
ssh ubuntu@<instance-public-ip>

There is no password and no console to log in to - this product has no credentials at all. /etc/gitleaks/credentials on the instance is an informational note that says exactly that, and points at the paths below.

Step 4 - Confirm Gitleaks is installed and scan a directory

gitleaks version
8.30.1

Now scan the shipped leaky self-test fixture as a directory. The -v flag prints the detail of each finding:

gitleaks dir -v --no-banner /usr/share/gitleaks/fixtures/leaky
echo "exit code: $?"

Real output from this image - a deliberately fake GitHub token is detected by the github-pat rule:

Finding:     GITHUB_TOKEN=ghp_R8vqZ2mN4pK7wX1yT6bJc3hFdA9sLe5uGoQ0
Secret:      ghp_R8vqZ2mN4pK7wX1yT6bJc3hFdA9sLe5uGoQ0
RuleID:      github-pat
Entropy:     5.221928
File:        /usr/share/gitleaks/fixtures/leaky/config.env
Line:        2
Fingerprint: /usr/share/gitleaks/fixtures/leaky/config.env:github-pat:2

INF scanned ~182 bytes (182 bytes) in 13.3ms
WRN leaks found: 1
exit code: 1

Gitleaks version and a directory scan detecting a hardcoded token

Step 5 - Scan a git repository's full history

This is Gitleaks' headline mode. The shipped leaky-repo fixture has a secret that was committed to history, so only a history scan finds it. gitleaks git walks every commit:

gitleaks git -v --no-banner /usr/share/gitleaks/fixtures/leaky-repo
echo "exit code: $?"

The finding names the commit, author and date, not just the file:

Finding:     GITHUB_TOKEN = "ghp_R8vqZ2mN4pK7wX1yT6bJc3hFdA9sLe5uGoQ0
Secret:      ghp_R8vqZ2mN4pK7wX1yT6bJc3hFdA9sLe5uGoQ0
RuleID:      github-pat
File:        settings.py
Line:        2
Commit:      64d1ddb858fee16cdd3a42b2f7b23494403e5742
Author:      cloudimg-build
Date:        2026-07-21T11:05:43Z

INF 1 commits scanned.
WRN leaks found: 1
exit code: 1

Gitleaks scanning a git repository's full commit history

To scan one of your own repositories, point gitleaks git at its path:

gitleaks git -v /path/to/your/repo

Step 6 - Confirm a clean scan reports nothing

The clean fixture contains no secrets and must report nothing (exit 0):

gitleaks dir --no-banner /usr/share/gitleaks/fixtures/clean
echo "exit code: $?"
INF scanned ~165 bytes (165 bytes) in 2.6ms
INF no leaks found
exit code: 0

Step 7 - Scan your own projects

Put your checkouts under /srv/projects (the default scan target) or point the configuration at wherever they already live, then scan the tree as files:

gitleaks dir -v /srv/projects

Use gitleaks dir for a working tree or plain files, and gitleaks git when you want the full commit history of a repository checked as well.

Step 8 - Scheduled scans and machine-readable reports

gitleaks-scan-run is the scheduled entry point. It reads /etc/gitleaks/scan.conf, scans SCAN_TARGET, and writes both a JSON and a SARIF report with latest.* symlinks. Run it once by hand against the clean fixture to see the reports appear:

sudo gitleaks-scan-run /usr/share/gitleaks/fixtures/clean
ls -l /var/lib/gitleaks/reports/latest.json /var/lib/gitleaks/reports/latest.sarif
[gitleaks-scan-run] scanning /usr/share/gitleaks/fixtures/clean for hardcoded secrets
INF no leaks found
[gitleaks-scan-run] no leaks found
[gitleaks-scan-run] reports: ... (latest.json / latest.sarif updated)
lrwxrwxrwx 1 root root ... latest.json -> .../gitleaks-scan-20260721T110650Z.json
lrwxrwxrwx 1 root root ... latest.sarif -> .../gitleaks-scan-20260721T110650Z.sarif

When the target contains a secret, gitleaks-scan-run exits 1 and the JSON report lists every finding. SARIF is the format GitHub code scanning, AWS CodeCatalyst, Azure DevOps and most IDEs consume directly, so latest.sarif can be uploaded as-is.

Scheduled scan writing JSON and SARIF reports, with the timer and firstboot unit enabled

The scan timer is enabled and armed out of the box, and so is the first-boot provisioning unit:

systemctl is-enabled gitleaks-scan.timer gitleaks-firstboot.service
enabled
enabled

Step 9 - The exit-code contract (CI integration)

gitleaks follows a simple, documented exit-code contract, which is what makes it usable as a pipeline gate:

Exit code Meaning
0 No leaks found
1 Leaks found
gitleaks dir --no-banner /usr/share/gitleaks/fixtures/clean >/dev/null 2>&1; echo "clean fixture exit: $?"
gitleaks dir --no-banner /usr/share/gitleaks/fixtures/leaky >/dev/null 2>&1; echo "leaky fixture exit: $?"
clean fixture exit: 0
leaky fixture exit: 1

A non-zero exit fails a CI job automatically, so gitleaks git . or gitleaks dir . as a merge gate blocks any change that introduces a secret.

Configuration

The scheduled scan reads /etc/gitleaks/scan.conf:

grep -v '^#' /etc/gitleaks/scan.conf | grep .
SCAN_TARGET="/srv/projects"
REPORT_DIR="/var/lib/gitleaks/reports"
GITLEAKS_CONFIG=""
REPORT_RETENTION_DAYS=30
  • SCAN_TARGET - the directory the daily scan walks (scanned as files with gitleaks dir). Point it at your checkouts.
  • GITLEAKS_CONFIG - leave empty to use Gitleaks' comprehensive embedded default ruleset. To use your own, set it to a .toml config path (see below).
  • REPORT_DIR / REPORT_RETENTION_DAYS - where reports are written and how many days of dated reports are kept.

After editing, restart the timer:

sudo systemctl restart gitleaks-scan.timer

Custom rulesets

Gitleaks ships a comprehensive default ruleset compiled into the binary, so most users need no configuration. To add your own rules or allowlists, write a .toml config that extends the default and point the appliance at it:

sudo gitleaks generate config > /etc/gitleaks/gitleaks.toml   # start from a template, then edit
sudo sed -i 's#^GITLEAKS_CONFIG=.*#GITLEAKS_CONFIG="/etc/gitleaks/gitleaks.toml"#' /etc/gitleaks/scan.conf
sudo systemctl restart gitleaks-scan.timer

You can also pass --config <path> to any manual gitleaks dir or gitleaks git run.

Maintenance

  • Scans: run daily by gitleaks-scan.timer; run one on demand with sudo gitleaks-scan-run. Inspect history with journalctl -u gitleaks-scan.service.
  • Reports: /var/lib/gitleaks/reports/latest.json and latest.sarif always point at the most recent scan; dated reports are pruned after REPORT_RETENTION_DAYS.
  • Upgrades: download a newer release tarball from the Gitleaks releases, verify it against the published checksums.txt, and replace /usr/local/bin/gitleaks.
  • Security patches: unattended-upgrades remains enabled, so the OS continues to receive security updates automatically.
  • Air-gapped use: nothing about scanning requires egress - the detection rules are built into the binary, so this instance scans fully offline.

Support

cloudimg provides 24/7 expert support for this image. Contact support@cloudimg.co.uk.