daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

2-4-cheatsheet-gitleaks.md (17822B)


      1 ---
      2 title: "2.4 - Cheatsheet - Gitleaks"
      3 description: "brew install gitleaks"
      4 category: enumeration
      5 alsoIn: ["osint"]
      6 tags: ["enumeration", "osint", "secret-scanning"]
      7 tools: ["Gitleaks"]
      8 difficulty: intermediate
      9 updated: "2026-08-10"
     10 source: "vault:Enumeration/GitHub-Enum/2.4 - Cheatsheet - Gitleaks.md"
     11 ---
     12 ## Installation
     13 
     14 ```bash
     15 # macOS — Homebrew
     16 brew install gitleaks
     17 
     18 # Linux — direct binary download (always check latest release)
     19 wget https://github.com/gitleaks/gitleaks/releases/latest/download/gitleaks_8.30.1_linux_x64.tar.gz
     20 tar -xzf gitleaks_8.30.1_linux_x64.tar.gz
     21 mv gitleaks /usr/local/bin/
     22 
     23 # Verify install
     24 gitleaks version
     25 # Output:
     26 # v8.30.1
     27 ```
     28 
     29 > [!info]+ Command Breakdown
     30 > 1. Gitleaks ships as a **single static binary** — no dependencies, no runtime needed
     31 > 2. Always check the [releases page](https://github.com/gitleaks/gitleaks/releases) for the latest version before downloading
     32 > 3. **v8.19.0+** deprecated `detect` and `protect` — replaced by `git`, `dir`, and `stdin` subcommands
     33 
     34 ---
     35 
     36 ## Subcommands at a Glance
     37 
     38 | Subcommand | What It Scans | Typical Use Case |
     39 |---|---|---|
     40 | `git` | Git repository — full commit history | Cloned public repos, any local git repo |
     41 | `dir` | Directories and individual files | Non-git folders, downloaded archives, local files |
     42 | `stdin` | Piped data stream | Scanning output of another command, log files |
     43 | `version` | N/A | Verify installed version |
     44 
     45 > [!warning]+ v8.19.0 Command Change
     46 > 1. `gitleaks detect` → replaced by `gitleaks git`
     47 > 2. `gitleaks protect` → replaced by `gitleaks git --pre-commit` / `gitleaks git --staged`
     48 > 3. The old commands still work but are **hidden from `--help`** — don't rely on them in scripts
     49 
     50 ---
     51 
     52 ## Core Scan Commands
     53 
     54 ### Scan a Cloned Repo (Most Common — OSINT Use)
     55 
     56 ```bash
     57 # Clone the target repo first
     58 git clone https://github.com/target-org/target-repo.git
     59 cd target-repo
     60 
     61 # Scan the full git history — verbose output
     62 gitleaks git -v .
     63 
     64 # Output example:
     65 # ○
     66 #     ○
     67 #         ○
     68 # ○       ○
     69 #     ○
     70 #
     71 # Finding:     AWS Access Key detected
     72 # Secret:      AKIAIOSFODNN7EXAMPLE
     73 # RuleID:      aws-access-key-id
     74 # Entropy:     3.88
     75 # File:        config/aws.py
     76 # Line:        12
     77 # Commit:      a3f2c1d9e8b74561...
     78 # Author:      dev@target.com
     79 # Date:        2023-04-18T14:22:01Z
     80 # Fingerprint: a3f2c1d9:config/aws.py:aws-access-key-id:12
     81 ```
     82 
     83 > [!info]+ Command Breakdown
     84 > 1. **git** — subcommand that scans using `git log -p` under the hood — reads every commit diff
     85 > 2. **-v** — verbose mode; prints each finding as it is discovered in real time
     86 > 3. **.** — target path; current directory (must be a git repo); can be an absolute path to any git repo
     87 > 4. **Finding** — the rule that matched
     88 > 5. **Secret** — the actual leaked value (may be redacted with `--redact`)
     89 > 6. **RuleID** — the specific detection rule that triggered (useful for filtering false positives)
     90 > 7. **Entropy** — Shannon entropy score of the matched string — higher = more likely to be a real secret
     91 > 8. **Commit** — the exact commit hash where the secret exists or existed
     92 > 9. **Fingerprint** — unique identifier for this finding — used in `.gitleaksignore` to suppress it
     93 
     94 ---
     95 
     96 ```bash
     97 # Scan a remote repo without cloning manually
     98 gitleaks git -v https://github.com/target-org/target-repo.git
     99 ```
    100 
    101 > [!info]+ Command Breakdown
    102 > 1. Gitleaks can accept a **remote URL** directly — it clones to a temp directory, scans, then cleans up
    103 > 2. Faster than manual clone for quick checks — but no persistent copy of the repo
    104 > 3. *For offensive recon, clone manually first so you can inspect files directly after gitleaks surfaces findings*
    105 
    106 ---
    107 
    108 ### Scan a Specific Commit Range
    109 
    110 ```bash
    111 # Scan only the last 50 commits
    112 gitleaks git -v --log-opts="-n 50" .
    113 
    114 # Scan between two specific commits
    115 gitleaks git -v --log-opts="commitA..commitB" .
    116 
    117 # Scan all branches (not just current branch)
    118 gitleaks git -v --log-opts="--all" .
    119 
    120 # Scan commits since a specific date
    121 gitleaks git -v --log-opts="--since=2024-01-01" .
    122 
    123 # Combine — all branches, last 1000 commits
    124 gitleaks git -v --log-opts="--all -n 1000" .
    125 ```
    126 
    127 > [!info]+ Command Breakdown
    128 > 1. **--log-opts** — passes options directly to `git log -p` — accepts any valid `git log` flag
    129 > 2. **-n 50** — limits to the last 50 commits — useful for CI pipelines or quick checks
    130 > 3. **commitA..commitB** — scans only commits between two hashes — useful for PR/MR scanning
    131 > 4. **--all** — scans ALL branches and tags, not just the checked-out branch — critical for OSINT; devs often push secrets to feature branches they forget about
    132 > 5. **--since=** — date filter; ISO format (`2024-01-01`) or relative (`6months`)
    133 
    134 > [!tip]+ OSINT Best Practice
    135 > 1. Always run with **--log-opts="--all"** first — the current branch is rarely where secrets live
    136 > 2. Feature branches, hotfix branches, and old release branches are where rushed, careless commits accumulate
    137 > 3. Combine **--all** with **-n 1000** to catch the breadth without waiting on repos with 10,000+ commits
    138 
    139 ---
    140 
    141 ### Scan a Directory (No Git Required)
    142 
    143 ```bash
    144 # Scan a directory of downloaded files
    145 gitleaks dir -v /path/to/downloaded/files/
    146 
    147 # Scan a single file
    148 gitleaks dir -v /path/to/suspicious/file.env
    149 
    150 # Scan current directory
    151 gitleaks dir -v .
    152 
    153 # Scan and include archives (zip, tar.gz, etc.) — disabled by default
    154 gitleaks dir -v --max-archive-depth=3 /path/to/directory/
    155 ```
    156 
    157 > [!info]+ Command Breakdown
    158 > 1. **dir** — scans the filesystem directly; no git history, no `git log` — just raw file contents
    159 > 2. Useful when you have downloaded files, extracted archives, or scraped content that isn't a git repo
    160 > 3. **--max-archive-depth=3** — tells gitleaks to open and scan inside `.zip`, `.tar.gz`, `.tar`, `.7z`, etc., up to 3 levels deep; default is 0 (disabled)
    161 > 4. *Archive scanning is critical for buckets and file shares — secrets are often in zip archives employees assumed were "safe"*
    162 
    163 ---
    164 
    165 ### Scan via stdin (Piped Input)
    166 
    167 ```bash
    168 # Scan a file piped through stdin
    169 cat suspicious_config.py | gitleaks -v stdin
    170 
    171 # Scan output of another command
    172 curl -s https://raw.githubusercontent.com/target-org/repo/main/config.py | gitleaks -v stdin
    173 
    174 # Scan an env file from a URL
    175 curl -s https://target-bucket.s3.amazonaws.com/.env | gitleaks -v stdin
    176 ```
    177 
    178 > [!info]+ Command Breakdown
    179 > 1. **stdin** — accepts raw text piped from any source — anything that produces output can be scanned
    180 > 2. Combine with `curl` to scan files directly from URLs **without saving them locally**
    181 > 3. *This is the fastest way to triage a suspicious file found via GrayHatWarfare or Google Dork — pipe it straight through gitleaks*
    182 
    183 ---
    184 
    185 ## Output and Reporting
    186 
    187 ### Save Results to a File
    188 
    189 ```bash
    190 # JSON report (default and most useful)
    191 gitleaks git -v . --report-path=findings.json --report-format=json
    192 
    193 # CSV report — easy to open in a spreadsheet
    194 gitleaks git -v . --report-path=findings.csv --report-format=csv
    195 
    196 # SARIF — standard format for integration with SIEMs and security dashboards
    197 gitleaks git -v . --report-path=findings.sarif --report-format=sarif
    198 
    199 # JUnit XML — for CI/CD pipeline integration
    200 gitleaks git -v . --report-path=findings.xml --report-format=junit
    201 ```
    202 
    203 > [!info]+ Command Breakdown
    204 > 1. **--report-path** — file path to write the report to; gitleaks still prints to terminal alongside writing
    205 > 2. **--report-format** — output format: `json` | `csv` | `junit` | `sarif`
    206 > 3. **json** — best format for OSINT work — easy to parse with `jq`, import into tools, or read manually
    207 > 4. **sarif** — industry-standard static analysis format — importable into GitHub Security, Burp, and SIEMs
    208 
    209 ---
    210 
    211 ```bash
    212 # Parse JSON output with jq — extract only the secret values and their files
    213 cat findings.json | jq -r '.[] | "\(.File):\(.Line) → \(.Secret)"'
    214 
    215 # Output:
    216 # config/aws.py:12 → AKIAIOSFODNN7EXAMPLE
    217 # .env:3 → ghp_aBcDeFgHiJkLmNoPqRsTuVwXyZ123456
    218 
    219 # Get a summary count of findings by rule
    220 cat findings.json | jq 'group_by(.RuleID) | map({rule: ..RuleID, count: length}) | sort_by(-.count)'
    221 
    222 # Output:
    223 # [
    224 #   { "rule": "generic-api-key", "count": 14 },
    225 #   { "rule": "aws-access-key-id", "count": 3 },
    226 #   { "rule": "github-pat", "count": 1 }
    227 # ]
    228 ```
    229 
    230 > [!info]+ Command Breakdown
    231 > 1. **jq -r '.[] | ...'** — iterates every finding in the JSON array
    232 > 2. **\(.File):\(.Line) → \(.Secret)** — formats each finding as `filename:linenumber → secretvalue`
    233 > 3. The **group_by + count** query gives an instant triage view — which secret types appeared most often
    234 > 4. *Start triage with the count summary — AWS keys and GitHub PATs are the highest-value findings to investigate first*
    235 
    236 ---
    237 
    238 ### Redact Secrets from Output
    239 
    240 ```bash
    241 # Redact actual secret values in terminal output and reports
    242 gitleaks git -v --redact .
    243 ```
    244 
    245 > [!info]+ Command Breakdown
    246 > 1. **--redact** — replaces the actual secret value with `REDACTED` in all output
    247 > 2. Use this when **sharing output** with a client, team, or in a report — never paste raw secrets into documents
    248 > 3. The finding is still reported with file, line, commit, and rule — just not the actual value
    249 
    250 ---
    251 
    252 ## Exit Codes
    253 
    254 | Exit Code | Meaning | What to Do |
    255 |---|---|---|
    256 | `0` | No secrets found | Clean — move on |
    257 | `1` | Secrets detected | Review findings — escalate critical ones |
    258 | `126` | Unknown flag or bad argument | Check your command syntax |
    259 | `2` | Unexpected error during scan | Check file permissions or repo state |
    260 
    261 ```bash
    262 # Use exit code in a shell script to branch on findings
    263 gitleaks git . --report-path=findings.json
    264 if [ $? -eq 1 ]; then
    265     echo "[!] Secrets found — review findings.json immediately"
    266 fi
    267 ```
    268 
    269 ---
    270 
    271 ## Suppressing False Positives
    272 
    273 ### Inline Ignore (Single Line)
    274 
    275 ```bash
    276 # In the source file — add this comment on the line with a known false positive
    277 api_key = "test_key_not_real"  # gitleaks:allow
    278 ```
    279 
    280 > [!info]+ Command Breakdown
    281 > 1. Adding `# gitleaks:allow` as a comment on the same line tells gitleaks to skip that match
    282 > 2. Useful for **test files**, mock data, or example values that pattern-match but are not real secrets
    283 > 3. *When scanning target repos during OSINT — if you see `gitleaks:allow` on a line, the dev was aware of gitleaks; look harder at nearby lines for real secrets they may have missed*
    284 
    285 ---
    286 
    287 ### .gitleaksignore File (Persistent Suppression)
    288 
    289 ```bash
    290 # Step 1 — Run a scan and save a baseline
    291 gitleaks git . --report-path=baseline.json
    292 
    293 # Step 2 — Create a .gitleaksignore file from known false positives
    294 # Add the fingerprint of each false positive — one per line
    295 echo "a3f2c1d9:config/test.py:generic-api-key:45" >> .gitleaksignore
    296 
    297 # Step 3 — Future scans will skip anything in .gitleaksignore
    298 gitleaks git . --report-path=new-findings.json
    299 ```
    300 
    301 > [!info]+ Command Breakdown
    302 > 1. **Fingerprint** format: `commit_hash:file:rule_id:line` — uniquely identifies a specific finding
    303 > 2. The fingerprint is shown in gitleaks output for every finding
    304 > 3. *During OSINT scanning of a target repo — ignore the `.gitleaksignore` file found in the repo; it tells you exactly which findings the devs already knew about and tried to hide from gitleaks*
    305 
    306 ---
    307 
    308 ### Baseline Scan (Only Report New Secrets)
    309 
    310 ```bash
    311 # Step 1 — Scan and save the current state as a baseline
    312 gitleaks git . --report-path=baseline.json
    313 
    314 # Step 2 — Run a future scan referencing the baseline
    315 gitleaks git . --report-path=new-findings.json --baseline-path=baseline.json
    316 
    317 # Only NEW findings (not in baseline) appear in new-findings.json
    318 ```
    319 
    320 > [!info]+ Command Breakdown
    321 > 1. **--baseline-path** — provides a previous report; any findings already in it are suppressed in the new report
    322 > 2. Useful for **monitoring** a target repo over time — run weekly and only see what has changed
    323 > 3. *Set up a cron job to scan high-value target repos weekly and alert only on new findings — a passive, ongoing intelligence feed*
    324 
    325 ---
    326 
    327 ## Custom Detection Rules
    328 
    329 > [!tip]+ Write Rules for Target-Specific Patterns
    330 > The default ruleset catches generic secrets. For targeted OSINT, add custom rules for company-specific patterns — internal tokens, system names discovered in job postings, or API formats unique to the target's stack.
    331 
    332 ```toml
    333 # custom-rules.toml
    334 # Place this file anywhere — reference it with --config
    335 
    336 rules
    337 id = "target-internal-token"
    338 description = "Target Corp internal API token format"
    339 regex = '''TGT-[a-zA-Z0-9]{32}'''
    340 tags = ["api", "target-corp"]
    341 
    342 rules
    343 id = "target-jwt-secret"
    344 description = "Hardcoded JWT secret matching target's known format"
    345 regex = '''jwt_secret\s*=\s*["'][a-zA-Z0-9+/=]{40,}["']'''
    346 tags = ["jwt", "target-corp"]
    347 ```
    348 
    349 ```bash
    350 # Use custom rules alongside the defaults
    351 gitleaks git -v --config=custom-rules.toml .
    352 
    353 # Use ONLY custom rules (ignore default ruleset)
    354 gitleaks git -v -c custom-rules.toml --no-banner .
    355 ```
    356 
    357 > [!info]+ Command Breakdown
    358 > 1. **--config / -c** — path to a custom `.toml` config file containing your own rules
    359 > 2. Custom rules **add to** the default ruleset — they don't replace it unless you explicitly override
    360 > 3. **regex** — standard Go regex syntax; test your patterns at [regex101.com](https://regex101.com/) with the Go flavour selected
    361 > 4. **tags** — metadata only; useful for filtering output later with `jq`
    362 > 5. *Build custom rules based on intelligence gathered from job postings and GitHub — if you know the company uses a custom auth token format, write a rule for it*
    363 
    364 ---
    365 
    366 ## Decoded and Encoded Secret Scanning
    367 
    368 ```bash
    369 # Scan for secrets hidden inside Base64, URL-encoded, or other encoded strings
    370 gitleaks git -v --max-decode-depth=5 .
    371 ```
    372 
    373 > [!info]+ Command Breakdown
    374 > 1. **--max-decode-depth** — enables recursive decoding of encoded content; default is 0 (disabled)
    375 > 2. Gitleaks will attempt to decode Base64, URL encoding, and other common formats, then scan the decoded output
    376 > 3. Setting depth to `5` means it will decode up to 5 layers deep (e.g., Base64 inside Base64)
    377 > 4. *Developers sometimes Base64-encode secrets thinking it obscures them — this flag catches that anti-pattern*
    378 > 5. *Setting a very high depth doesn't slow things down significantly — gitleaks stops as soon as there's nothing left to decode*
    379 
    380 ---
    381 
    382 ## Full OSINT Workflow
    383 
    384 ```bash
    385 # 1. Clone the target repo
    386 git clone https://github.com/target-org/target-repo.git
    387 cd target-repo
    388 
    389 # 2. Full scan — all branches, all history, verbose, save JSON
    390 gitleaks git -v \
    391   --log-opts="--all" \
    392   --report-path=target-repo-findings.json \
    393   --report-format=json \
    394   --max-decode-depth=3 \
    395   .
    396 
    397 # 3. Quick triage — count findings by rule type
    398 cat target-repo-findings.json | jq 'group_by(.RuleID) | map({rule: ..RuleID, count: length}) | sort_by(-.count)'
    399 
    400 # 4. Extract highest-value findings — AWS keys, GitHub tokens, private keys
    401 cat target-repo-findings.json | jq '.[] | select(.RuleID == "aws-access-key-id" or .RuleID == "github-pat" or .RuleID == "rsa-private-key") | {file: .File, line: .Line, commit: .Commit, author: .Author, date: .Date}'
    402 
    403 # 5. For each high-value finding, check the exact commit for context
    404 git show <commit_hash>
    405 
    406 # 6. Check if the secret is still present in the current HEAD
    407 grep -r "AKIAIOSFODNN7EXAMPLE" .
    408 ```
    409 
    410 > [!info]+ Workflow Breakdown
    411 > 1. **Step 2** — `--all` ensures all branches are included; `--max-decode-depth=3` catches encoded secrets; JSON output enables scripted triage
    412 > 2. **Step 3** — group by RuleID first; triage by secret type, not by file — AWS keys and GitHub PATs are worth more than generic API keys
    413 > 3. **Step 4** — `select()` filter in jq isolates the highest-priority findings immediately
    414 > 4. **Step 5** — `git show <hash>` shows the full diff for that commit — gives context (what else changed, who committed, what the surrounding code does)
    415 > 5. **Step 6** — `grep -r` confirms whether the secret still exists in current files or was only in history
    416 
    417 ---
    418 
    419 > [!success]+ What to Do with a Finding
    420 > 1. **Record** the secret value, file path, commit hash, author email, and date
    421 > 2. **Check if still active** — grep current files; if still present, it is likely live and exploitable
    422 > 3. **Identify the service** — AWS key? Try `aws sts get-caller-identity`. GitHub PAT? Try `curl -H "Authorization: token <PAT>" https://api.github.com/user`
    423 > 4. **Document in your report** — include rule ID, file, commit hash, author, and date discovered
    424 > 5. **Do not use the credential** beyond confirming it is valid — exploitation beyond scope verification is out of bounds
    425 
    426 ---
    427 
    428 ## References
    429 
    430 1. [Gitleaks GitHub Repository](https://github.com/gitleaks/gitleaks)
    431 2. [Gitleaks Releases Page](https://github.com/gitleaks/gitleaks/releases)
    432 3. [Gitleaks Default Rules Config (gitleaks.toml)](https://github.com/gitleaks/gitleaks/blob/master/config/gitleaks.toml)
    433 4. [Gitleaks Playground](https://gitleaks.io/playground)
    434 5. [v8.19.0 Command Translation Gist](https://gist.github.com/zricethezav/b325bb93ebf41b9c0b0507acf12810d2)
    435 6. [HTB Academy - Footprinting Module](https://academy.hackthebox.com/module/details/112)
    436 7. [Gitleaks Blog — Advanced Configuration](https://blog.gitleaks.io/stop-leaking-secrets-configuration-2-3-aeed293b1fbf)
    437 8. [HackTricks - OSINT](https://book.hacktricks.xyz/generic-methodologies-and-resources/external-recon-methodology)
    438 9. [MITRE ATT&CK - Search Open Technical Databases (T1596)](https://attack.mitre.org/techniques/T1596/)
    439 10. [Source: 2.0 - Cheatsheet - Infrastructure Enumeration Tools](2.0%20-%20Cheatsheet%20-%20Infrastructure%20Enumeration%20Tools.md)
    440 11. [Source: 2.3 - Theory Staff](2.3%20-%20Theory%20Staff.md)
    441 
    442 ---
    443 
    444 #HTB #Footprinting #OSINT #Gitleaks #SecretScanning #GitHistory #CredentialLeak #Cheatsheet #GitHub #PassiveRecon