Skip to content
Use this GitHub action with your project
Add this Action to an existing workflow or create a new one
View on Marketplace

Repository files navigation

Redflag 🚩

Redflag finds credentials in source files, Git history and files selected for publication. Artifact scans also match explicitly declared private build values and can verify that upload inputs match the bytes that were scanned.

CI Release License: MIT

Install

Install from source with a current Rust toolchain:

cargo install --git https://github.com/iammerus/redflag

Artifact and introduced-change scans also require the pinned Betterleaks engine. From a cloned checkout, run python3 scripts/install_engine.py --directory <redflag-binary-directory>/engines. See engine installation and verification. The legacy scan command needs no external engine; artifacts --engine native selects that detector explicitly for compatibility.

Release tags use the v<version> form. This checkout prepares version 0.2.0; the published v0.1.1 release predates the modernization work. See RELEASES.md for native bundle construction, verification and the current platform validation status, including Apple Silicon.

Quick start

# Scan the current directory
redflag scan .

# Scan the current checkout and history reachable from HEAD
redflag scan . --git-history

# Inspect every introduced commit, including secrets deleted before HEAD
redflag changes . --base origin/main --head HEAD

# In GitHub Actions, use the exact event's PR, push or merge-queue scope
redflag changes . --github-event "$GITHUB_EVENT_PATH"

# Create and use a configuration file
redflag generate-config redflag.toml
redflag show-config .
redflag scan .

# Check all publication files and a private value already present in this build
redflag artifacts dist --private-env INTERNAL_API_KEY --manifest scan-manifest.json
redflag verify-artifacts scan-manifest.json

See ARTIFACTS.md for strict target selection, private-value matching, manifests and checks before publication. See CHANGES.md for committed ranges, trusted base policy, merge handling, coverage and current limitations.

GitHub Action

The prepared v0.2.0 Action installs verified native binaries and supports source changes, publication inputs and manifest verification. It must be published before these release-download examples can run; v0.1.1 retains the older Action.

name: Credential check
on:
  pull_request:
  merge_group:
  push:
    branches: ['**']
permissions:
  contents: read
jobs:
  redflag:
    if: github.event_name != 'push' || !github.event.deleted
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
        with:
          fetch-depth: 0
          persist-credentials: false
      - uses: iammerus/redflag@v0.2.0 # Prefer the published release's full commit SHA
        with:
          mode: changes

For generated output, run mode: artifacts after the trusted build and supply explicit paths and any private-env names. Write a manifest outside those inputs and use mode: verify-artifacts when a later upload consumes copied output. The Action defaults to legacy scan for compatibility with existing path, config and git-history inputs. See ACTION.md for complete workflows, permissions, input contracts and verification requirements.

Detection coverage

Known GitHub, AWS access ID, Stripe secret/restricted, and npm token formats are recognized anywhere on a line, including unnamed values in compiled JavaScript. GitHub classic and fine-grained tokens are supported. Provider rules run even when entropy checks are disabled; they do not verify whether a credential is live.

Credential assignments support JSON, YAML, shell, TOML, and common source syntax, including single quotes, double quotes, backticks, and unquoted values. API-key assignments recognize hexadecimal and base64 values without lowering the global entropy threshold. Password rules recognize literal fallbacks, including shell defaults and JavaScript ||/?? expressions.

Built-in validation excludes plain environment references, explicit template placeholders, and Stripe publishable keys. Database URL findings require a password. Entropy checks skip labeled checksums; provider rules still run on those values. Overlapping built-in rules for the same literal produce one finding.

Process contract

Exit code Meaning
0 The scan completed and found nothing
1 The scan completed and found at least one item
2 Arguments, configuration, input, output, or Git caused an operational failure

stdout contains only the selected report format. Errors, warnings, and progress belong on stderr. Source scan JSON remains an array. artifacts and verify-artifacts use a versioned object with coverage and findings.

Interactive scans show a single-line progress bar on stderr. Redirected output and CI stay quiet automatically. Use --no-progress to disable progress in a terminal.

Matched values are replaced with [REDACTED] by default. Use --show-secrets only when raw values are genuinely required, and treat that output as sensitive.

Scan command

redflag scan [PATH]

PATH defaults to the current directory.

Option Purpose
-c, --config <FILE> Load a TOML configuration
--no-config Use defaults without automatic policy discovery
-f, --format <text|json|json-report> Select text, the legacy JSON array, or versioned JSON with coverage
--show-secrets Include raw matched values
--no-progress Disable interactive progress output
--git-history Also scan reachable Git history
--git-branches <REVISIONS> Scan comma-separated branches, tags, or revisions
--git-max-depth <COUNT> Fail if reachable history exceeds this commit limit
--git-since <YYYY-MM-DD> Ignore older commits
--git-until <YYYY-MM-DD> Ignore newer commits

When no Git revision is configured, history scanning starts from HEAD. Every explicit revision must resolve or the scan exits with code 2.

History scans require a complete checkout. Shallow repositories and histories that exceed --git-max-depth fail with exit code 2; they cannot produce a clean partial result. Fetch full history and increase the limit when needed.

Use scan --format json-report for a version 1 envelope containing the native findings, effective policy digest, working-tree statistics and selected history scope. The scope records each requested revision and its resolved commit, every selected commit ID, date-filter omissions and the traversal limit. Text summaries also show the tips, dates and selected/reachable counts. --format json retains the existing findings-only array. See REPORTING.md.

Dates select commit timestamps inclusively in UTC, from midnight on --git-since through 23:59:59 on --git-until. The commit limit applies to all history reachable from the selected tips before date filtering. A complete filtered scan may omit older or newer history, and its report identifies that omission. Legacy history compares each commit with its first parent and inspects added lines using source extensions, exclusions and comment suppressions. For the trusted policy and merge semantics of a CI source gate, use the changes command.

An explicitly named regular file is scanned regardless of its extension. Directory scans use the configured extensions and recognise .env and names such as .env.local. Common extensionless configuration files including .npmrc, .netrc, credentials, SSH private key names such as id_ed25519, Dockerfile, Makefile, and Jenkinsfile are also recognised. Test, example, fixture, and documentation files are not implicitly skipped.

The former install-hook command has been removed. Its hook was not executable and read working-tree files rather than staged blobs.

Configuration

Generate a complete starting file:

redflag generate-config redflag.toml

Without --config, source scans find the nearest redflag.toml starting at the selected directory (or the parent of a selected file), stopping after checking the Git repository root. Outside Git, discovery stops at the filesystem root. The nearest file is merged with built-in defaults; parent policies are not layered. Artifact scans start discovery at the current workflow directory, so a config file inside generated output cannot select the scan's policy.

--config FILE selects that file explicitly. --no-config disables discovery; the two options conflict. Use a trusted explicit policy in CI when a source branch can modify its own configuration. The Action's changes mode uses trusted base policy by default; see ACTION.md.

Inspect the resolved policy without scanning:

redflag show-config . --format json

The output includes the selected path, merged settings and SHA-256 of the effective configuration. Text output is a reusable TOML file with provenance comments. Both modes validate regexes and globs before output. Unknown top-level sections are errors, so a misspelled section cannot silently leave defaults active.

Configuration is merged with built-in defaults as follows:

  • a user pattern replaces a built-in pattern with the same name, otherwise it is appended;
  • extensions extend the defaults and are deduplicated without regard to case;
  • exclusions extend the defaults, keeping the last occurrence of exact duplicates;
  • a present [entropy], [git] or [limits] section replaces that section after omitted fields receive documented defaults;
  • invalid regular expressions, globs, dates, date ranges, entropy values, and Git limits are fatal.

Source files are read incrementally. Lines longer than 16 MiB fail operationally instead of exhausting memory or being skipped. Set [limits] max_line_bytes to increase this bound when needed; the limit excludes the line's CR/LF terminator. JSON findings use a private temporary spool so report memory does not grow with the total number of findings. Temporary-storage failures also fail the scan. The defaults also limit files to 64 MiB and each scan phase to 100,000 selected files. Set limits.max_file_bytes and limits.max_files to change these bounds. Git blob sizes are checked before patches are constructed.

Example:

extensions = ["kt"]

[entropy]
enabled = false
threshold = 4.8
min_length = 30

[git]
max_depth = 1000
branches = []

[[patterns]]
name = "internal-service-token"
pattern = '''service_token\s*=\s*"(?P<secret>[A-Za-z0-9_-]{32,})"'''
description = "Internal service token"
severity = "High"

[[exclusions]]
pattern = "**/generated/**"
policy = "Ignore"

Exclusion policies are:

Policy Behaviour
Ignore Do not scan the matching path
ScanButWarn Warn on stderr but do not add findings
ScanButAllow Report findings normally

The last matching exclusion rule wins. See PATTERN_GUIDE.md and redflag.example.toml for more examples.

Output

Default text output redacts the matched range:

[CRITICAL] config.rs:42 - AWS Access Key - AWS Access Key ID detected
Snippet: [REDACTED]
Commit: a1b2c3d (Developer, 2025-02-24T00:00:00+00:00)

Scan Summary:
-------------
Working tree: 14 files, 0 findings
Git history: 1000 commits, 321 changed files, 1 finding
Total findings: 1
  Critical: 1
  High:     0
  Medium:   0
  Low:      0

JSON output can be redirected safely:

redflag scan . --git-history --format json > redflag-results.json

Files scanned by default

Group Extensions
Languages php, js, ts, jsx, tsx, py, rb, java, go, rs, cs, cpp, c, h, hpp
Data and configuration xml, yaml, yml, json, config, conf, ini, env, properties, toml, sql, md, txt
Shell and infrastructure sh, bash, zsh, tf, tfvars, hcl
Credentials and build artifacts pem, key, mjs, cjs, map

Limits

  • Entropy detection is heuristic. It can miss secrets and report harmless strings.
  • Scanning is line based. Encoded, split, or dynamically constructed credentials may be missed. Unknown opaque values still depend on heuristics or custom rules.
  • A clean scan is not a security guarantee.
  • Finding a committed secret does not make it safe again. Revoke or rotate it first.
  • Redflag reports history but does not rewrite it.

Development

cargo fmt -- --check
cargo clippy --all-targets -- -D warnings
cargo test --all-targets
cargo build --release

tests/detection_tests.rs generates offline fixtures for provider formats, assignment syntax, file selection, history, redaction, and benign lookalikes. These tests run with the normal CI suite. They measure regression coverage, not the probability of finding every secret in a real repository.

Redflag is available under the MIT licence.

About

Rust-powered secret scanner for codebases | Cross-platform | Git pre-commit hooks | Regex + entropy detection | JSON/text output

Resources

Stars

6 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages