From a76565df3bb8c6b0ed6075189aecb626b23aa59c Mon Sep 17 00:00:00 2001 From: PiX <69745008+pixincreate@users.noreply.github.com> Date: Mon, 14 Sep 2026 21:36:39 +0530 Subject: [PATCH] chore(ci): harden distribution and rewrite the docs Workflows: - ci.yml runs with contents: read; it was the only workflow without a permissions block. - docker-publish gates the image build on the test suite, so a tag whose release preflight failed can no longer ship a container and move the latest tag. - update-baseline routes the ref name through env instead of interpolating it into the script. - release.yml drops the dead aarch64 target step (the toolchain step already installs the matrix target) and adds a major-tag job that moves the moving major tag (v2) to each stable release, the same way official actions maintain theirs. Prerelease tags are skipped. Action: - On a missing or malformed report the published exit-code output is the effective failing status instead of a stale 0, and findings-count stays numeric (-1 when unknown). Distribution and tooling: - The container image sets WORKDIR /workspace so the documented mount works without --workdir. - just check runs clippy with -D warnings to match CI; the bench recipe is dropped (no benches exist). - release.sh calls the validated function directly instead of eval, collapses an if/else with identical branches, and matches CHANGELOG versions as anchored fixed strings. Docs: - README rewritten: usage is split into command-line scanning and git hooks, options are tables, and the wording is plain. - CHANGELOG documents the unreleased behavior changes, the baseline upgrade notes, and the keep-a-changelog section structure is fixed. - The committed baseline is pruned, which also folds pre-anchoring path spellings into repository-root-relative entries. Assisted-by: Claude Fable 5 Signed-off-by: PiX <69745008+pixincreate@users.noreply.github.com> --- .github/workflows/ci.yml | 3 + .github/workflows/docker-publish.yml | 16 + .github/workflows/release.yml | 28 +- .github/workflows/update-baseline.yml | 6 +- .keywatch-baseline.json | 1776 +++++++---------- CHANGELOG.md | 38 +- Dockerfile | 2 + README.md | 379 ++-- action.yml | 5 +- justfile | 6 +- .../keywatch_action_scenarios.py | 4 +- scripts/action_validation/validate.py | 2 +- scripts/release.sh | 12 +- 13 files changed, 1036 insertions(+), 1241 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 626111a..602e90a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,6 +13,9 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true +permissions: + contents: read + env: CARGO_INCREMENTAL: 0 CARGO_NET_RETRY: 10 diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 39ffcc7..54ccf9a 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -15,9 +15,25 @@ env: IMAGE_NAME: pixincreate/keywatch jobs: + test: + name: Test before publish + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v7 + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + toolchain: stable + + - name: Run tests + run: cargo test --release --locked + build-and-push: name: Build and push Docker image runs-on: ubuntu-latest + needs: test steps: - name: Checkout repository diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f6151cf..d80f192 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -114,10 +114,6 @@ jobs: with: targets: ${{ matrix.platform.target }} - - name: Add aarch64 Apple target - if: matrix.platform.target == 'aarch64-apple-darwin' - run: rustup target add aarch64-apple-darwin - # Build the specific package - name: Build Binary run: | @@ -167,3 +163,27 @@ jobs: prerelease: false env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + major-tag: + name: update-major-tag + needs: release + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Checkout repository + uses: actions/checkout@v7 + + - name: Move the major tag to this release + env: + REF_NAME: ${{ github.ref_name }} + run: | + set -euo pipefail + case "$REF_NAME" in + *-*) echo "Prerelease tag; major tag not moved."; exit 0 ;; + esac + major="${REF_NAME%%.*}" + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git tag -fa "$major" -m "Update $major tag" + git push origin "$major" --force diff --git a/.github/workflows/update-baseline.yml b/.github/workflows/update-baseline.yml index 24e6545..b772e2a 100644 --- a/.github/workflows/update-baseline.yml +++ b/.github/workflows/update-baseline.yml @@ -33,12 +33,14 @@ jobs: - name: Open pull request if the baseline changed env: GH_TOKEN: ${{ github.token }} + BASE_REF: ${{ github.ref_name }} + RUN_ID: ${{ github.run_id }} run: | if [ -z "$(git status --porcelain -- .keywatch-baseline.json)" ]; then echo "Baseline unchanged; nothing to do." exit 0 fi - branch="chore/update-baseline-${{ github.run_id }}" + branch="chore/update-baseline-${RUN_ID}" git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" git checkout -b "$branch" @@ -48,4 +50,4 @@ jobs: gh pr create \ --title "chore: update keywatch baseline" \ --body "Regenerated by the update-baseline workflow. Review every newly baselined finding before merging: each entry is a finding KeyWatch will stop reporting." \ - --base "${{ github.ref_name }}" + --base "$BASE_REF" diff --git a/.keywatch-baseline.json b/.keywatch-baseline.json index ef1ec88..640ae66 100644 --- a/.keywatch-baseline.json +++ b/.keywatch-baseline.json @@ -2,1831 +2,1607 @@ "version": "1.0", "entries": [ { - "file_path": "./.github/workflows/ci.yml", - "line_number": 74, + "file_path": ".github/workflows/ci.yml", + "line_number": 77, "finding_type": "AWS Access Key", "matched_content_hash": "3f733150de7916d4778298d7f90493889c38b76876b80c058e439851ce60cb2b", "plugin_name": "AWSKeyDetector" }, { - "file_path": "./.github/workflows/docker-publish.yml", - "line_number": 42, + "file_path": ".github/workflows/ci.yml", + "line_number": 77, + "finding_type": "Generic Key/Secret", + "matched_content_hash": "f1b334a28e2052a9e8870fc7fd7383f477199e8e138f1a46f83ee39a2c80a341", + "plugin_name": "GenericKeyValueDetector" + }, + { + "file_path": ".github/workflows/docker-publish.yml", + "line_number": 58, "finding_type": "Password", "matched_content_hash": "4e433d275810f054b78ebef6ba3971128253dc8fb930dee5f57c5c846b6d42ea", "plugin_name": "PasswordDetector" }, { - "file_path": "./Cargo.toml", + "file_path": "Cargo.toml", "line_number": 6, "finding_type": "Email Address", "matched_content_hash": "dd58c0e81231a24fa00886e14227fc41fa36882ab3965aaa37d1ef013bf3e8f9", "plugin_name": "EmailDetector" }, { - "file_path": "./detectors.toml", + "file_path": "detectors.toml", "line_number": 212, "finding_type": "Certificate", "matched_content_hash": "648ee3671e3bc408c3bce7d0ce237d9716da2c360a5c57c235a21067ac11eea9", "plugin_name": "CertificateDetector" }, { - "file_path": "./detectors.toml", - "line_number": 316, - "finding_type": "SSH Private Key", - "matched_content_hash": "678a65e8968aabff441076ae306e13d4fc85b1d36d8036a10d2100c1dc40d251", - "plugin_name": "SSHPrivateKeyDetector" - }, - { - "file_path": "./detectors.toml", - "line_number": 316, - "finding_type": "Private Key Content", - "matched_content_hash": "f59444f5756fc6dd701c599452c1752e64a97ecb0447ce41a1e19eb15293ef9a", - "plugin_name": "PrivateKeyDetector" - }, - { - "file_path": "./detectors.toml", - "line_number": 316, - "finding_type": "Private Key Content", - "matched_content_hash": "f59444f5756fc6dd701c599452c1752e64a97ecb0447ce41a1e19eb15293ef9a", - "plugin_name": "PrivateKeyContentDetector" - }, - { - "file_path": "./detectors.toml", + "file_path": "detectors.toml", "line_number": 825, "finding_type": "Base64 Encoded String", "matched_content_hash": "e7e83ac014759b0de9f4e42e44daa4ae4820947de0c4436363b752b701dd147f", "plugin_name": "Base64Detector" }, { - "file_path": "./docs/architecture/cli-modules.svg", + "file_path": "docs/architecture/cli-modules.svg", "line_number": 7, "finding_type": "Base64 Encoded String", "matched_content_hash": "c7499b2b8fb43780aa044148fb9ecdcb6795c4604db9ad468644fa974cb87ae6", "plugin_name": "Base64Detector" }, { - "file_path": "./docs/architecture/cli-modules.svg", + "file_path": "docs/architecture/cli-modules.svg", "line_number": 92, - "finding_type": "Base64 Encoded String", - "matched_content_hash": "4b235f293c86102514fce21c17c77c9e46da4e34ca3f36642dde269bf593a42a", - "plugin_name": "Base64Detector" + "finding_type": "Random String", + "matched_content_hash": "91e0e33ed1c5151578d8fac6d4f139bab71ac57c9feb4f68ecda5fc49e3e8bbf", + "plugin_name": "RandomString" }, { - "file_path": "./docs/architecture/cli-modules.svg", + "file_path": "docs/architecture/cli-modules.svg", "line_number": 92, - "finding_type": "Base64 Encoded String", - "matched_content_hash": "9cb066ba3697cbcd17f51c83125e42b3b09256edd013145402d9066613eba929", - "plugin_name": "Base64Detector" + "finding_type": "Random String", + "matched_content_hash": "318e014fa33dc923021432ac2c388ccb64d2e886e32e82095d590caf37412da3", + "plugin_name": "RandomString" + }, + { + "file_path": "docs/architecture/cli-modules.svg", + "line_number": 92, + "finding_type": "Random String", + "matched_content_hash": "7363f682607f5d1c84d39f90fe9559d9f16b0b21fc287c006b07ed038c43ffe1", + "plugin_name": "RandomString" + }, + { + "file_path": "docs/architecture/cli-modules.svg", + "line_number": 92, + "finding_type": "Random String", + "matched_content_hash": "f359f7aacd4e316cadc07e5a2561ed82ffdd4afc171581390d638f248c958735", + "plugin_name": "RandomString" }, { - "file_path": "./docs/architecture/cli-modules.svg", + "file_path": "docs/architecture/cli-modules.svg", "line_number": 92, "finding_type": "Base64 Encoded String", - "matched_content_hash": "3f469ae3bade9899dc4902162eade7e691ea17aeef930ef0f12c82f99a3b2ded", + "matched_content_hash": "118aa0afdb39a144fd8285e2b9174fac00c729cd5f8a66eca1ddf975997a37fc", "plugin_name": "Base64Detector" }, { - "file_path": "./docs/architecture/cli-modules.svg", + "file_path": "docs/architecture/cli-modules.svg", "line_number": 92, "finding_type": "Base64 Encoded String", - "matched_content_hash": "118aa0afdb39a144fd8285e2b9174fac00c729cd5f8a66eca1ddf975997a37fc", + "matched_content_hash": "4b235f293c86102514fce21c17c77c9e46da4e34ca3f36642dde269bf593a42a", "plugin_name": "Base64Detector" }, { - "file_path": "./docs/architecture/cli-modules.svg", + "file_path": "docs/architecture/cli-modules.svg", "line_number": 92, "finding_type": "Base64 Encoded String", "matched_content_hash": "8e3cb34aae11dc73b875cc925ef3b875c7fc154ca52c133f90159fb65aeb80ee", "plugin_name": "Base64Detector" }, { - "file_path": "./docs/architecture/cli-modules.svg", + "file_path": "docs/architecture/cli-modules.svg", "line_number": 92, - "finding_type": "Random String", - "matched_content_hash": "318e014fa33dc923021432ac2c388ccb64d2e886e32e82095d590caf37412da3", - "plugin_name": "RandomString" + "finding_type": "Base64 Encoded String", + "matched_content_hash": "9cb066ba3697cbcd17f51c83125e42b3b09256edd013145402d9066613eba929", + "plugin_name": "Base64Detector" }, { - "file_path": "./docs/architecture/cli-modules.svg", + "file_path": "docs/architecture/cli-modules.svg", "line_number": 92, - "finding_type": "Random String", - "matched_content_hash": "f359f7aacd4e316cadc07e5a2561ed82ffdd4afc171581390d638f248c958735", - "plugin_name": "RandomString" + "finding_type": "Base64 Encoded String", + "matched_content_hash": "3f469ae3bade9899dc4902162eade7e691ea17aeef930ef0f12c82f99a3b2ded", + "plugin_name": "Base64Detector" + }, + { + "file_path": "docs/architecture/detector-config-trust.svg", + "line_number": 7, + "finding_type": "Base64 Encoded String", + "matched_content_hash": "c77955587c1ef977a8ef77ed7c143faf1c8922f858da143af3e146a3f95fe841", + "plugin_name": "Base64Detector" }, { - "file_path": "./docs/architecture/cli-modules.svg", + "file_path": "docs/architecture/detector-config-trust.svg", "line_number": 92, "finding_type": "Random String", - "matched_content_hash": "91e0e33ed1c5151578d8fac6d4f139bab71ac57c9feb4f68ecda5fc49e3e8bbf", + "matched_content_hash": "fa9cafeea120bb26d43f09cb134a5b71ba21c0d8178533aaa29ff72db4a83816", "plugin_name": "RandomString" }, { - "file_path": "./docs/architecture/cli-modules.svg", + "file_path": "docs/architecture/detector-config-trust.svg", "line_number": 92, "finding_type": "Random String", - "matched_content_hash": "7363f682607f5d1c84d39f90fe9559d9f16b0b21fc287c006b07ed038c43ffe1", + "matched_content_hash": "de239f05cccb06dd9750a39355706433951533d49d597dd94ab1413ca76af498", "plugin_name": "RandomString" }, { - "file_path": "./docs/architecture/detector-config-trust.svg", - "line_number": 7, - "finding_type": "Base64 Encoded String", - "matched_content_hash": "c77955587c1ef977a8ef77ed7c143faf1c8922f858da143af3e146a3f95fe841", - "plugin_name": "Base64Detector" - }, - { - "file_path": "./docs/architecture/detector-config-trust.svg", + "file_path": "docs/architecture/detector-config-trust.svg", "line_number": 92, "finding_type": "Base64 Encoded String", - "matched_content_hash": "83929a84ca0439480236425c060e4e784dfd74f72d7f3cc5dbad2ea4c0bb18e1", + "matched_content_hash": "e7741b12ff6c08334c644e0593b38a566bf878e8bd6550855ec268f097654c29", "plugin_name": "Base64Detector" }, { - "file_path": "./docs/architecture/detector-config-trust.svg", + "file_path": "docs/architecture/detector-config-trust.svg", "line_number": 92, "finding_type": "Base64 Encoded String", - "matched_content_hash": "56dda2c9c468a9ed6a08bec9cb49ddd201e98b179951477abc5188f4a47a1d6e", + "matched_content_hash": "83929a84ca0439480236425c060e4e784dfd74f72d7f3cc5dbad2ea4c0bb18e1", "plugin_name": "Base64Detector" }, { - "file_path": "./docs/architecture/detector-config-trust.svg", + "file_path": "docs/architecture/detector-config-trust.svg", "line_number": 92, "finding_type": "Base64 Encoded String", "matched_content_hash": "045c378999d40cdba4d8400c824996e20c6e324d85078accd2619d8d13bb6dde", "plugin_name": "Base64Detector" }, { - "file_path": "./docs/architecture/detector-config-trust.svg", + "file_path": "docs/architecture/detector-config-trust.svg", "line_number": 92, "finding_type": "Base64 Encoded String", - "matched_content_hash": "aafcd1d46e6640f70204ee1979df445d2c2f30975f2db678a52ae1c335613dbf", + "matched_content_hash": "56dda2c9c468a9ed6a08bec9cb49ddd201e98b179951477abc5188f4a47a1d6e", "plugin_name": "Base64Detector" }, { - "file_path": "./docs/architecture/detector-config-trust.svg", + "file_path": "docs/architecture/detector-config-trust.svg", "line_number": 92, "finding_type": "Base64 Encoded String", - "matched_content_hash": "e7741b12ff6c08334c644e0593b38a566bf878e8bd6550855ec268f097654c29", + "matched_content_hash": "aafcd1d46e6640f70204ee1979df445d2c2f30975f2db678a52ae1c335613dbf", "plugin_name": "Base64Detector" }, { - "file_path": "./docs/architecture/detector-config-trust.svg", - "line_number": 92, - "finding_type": "Random String", - "matched_content_hash": "fa9cafeea120bb26d43f09cb134a5b71ba21c0d8178533aaa29ff72db4a83816", - "plugin_name": "RandomString" - }, - { - "file_path": "./docs/architecture/detector-config-trust.svg", - "line_number": 92, - "finding_type": "Random String", - "matched_content_hash": "de239f05cccb06dd9750a39355706433951533d49d597dd94ab1413ca76af498", - "plugin_name": "RandomString" - }, - { - "file_path": "./docs/architecture/scan-pipeline.svg", + "file_path": "docs/architecture/scan-pipeline.svg", "line_number": 7, "finding_type": "Base64 Encoded String", "matched_content_hash": "f3753f090549b3529cacad629e2bfcbd8864d45851010ffedc5159fc3bb74e91", "plugin_name": "Base64Detector" }, { - "file_path": "./docs/architecture/scan-pipeline.svg", + "file_path": "docs/architecture/scan-pipeline.svg", "line_number": 14, "finding_type": "Base64 Encoded String", "matched_content_hash": "ba34e96d0f5312b12c26d734c3cd0c5f468e318de78c5fb54c13f5b6df6515a8", "plugin_name": "Base64Detector" }, { - "file_path": "./docs/architecture/scan-pipeline.svg", + "file_path": "docs/architecture/scan-pipeline.svg", "line_number": 99, - "finding_type": "Base64 Encoded String", - "matched_content_hash": "b5458e408e59b20b5f8bb66bb996cf3229bba0f4260ab705070fe7bf7029afa4", - "plugin_name": "Base64Detector" + "finding_type": "Random String", + "matched_content_hash": "6b6adc15e5af26b2c97bfd0a9efa20983d3da2bd27d9cb3b9fd20e33b6bb00a3", + "plugin_name": "RandomString" }, { - "file_path": "./docs/architecture/scan-pipeline.svg", + "file_path": "docs/architecture/scan-pipeline.svg", "line_number": 99, - "finding_type": "Base64 Encoded String", - "matched_content_hash": "863a91ad1862061e7a75d0c35635387e87c46d03f419fedf85776419a0857c12", - "plugin_name": "Base64Detector" + "finding_type": "Random String", + "matched_content_hash": "fb1a63b387f03e5a3c47f9524380935ddbcf2fc2fa4cea99d6dcd00d9bb7dd3a", + "plugin_name": "RandomString" }, { - "file_path": "./docs/architecture/scan-pipeline.svg", + "file_path": "docs/architecture/scan-pipeline.svg", "line_number": 99, - "finding_type": "Base64 Encoded String", - "matched_content_hash": "0f3980221f6fd3f6b36a6c1ad85672be41f74a19ca07fe476139e93dca97a2f1", - "plugin_name": "Base64Detector" + "finding_type": "Random String", + "matched_content_hash": "888b0d80b6cb228df1b6bf35bc6201908bc74a15d2012ce3b1417d043d4d169c", + "plugin_name": "RandomString" }, { - "file_path": "./docs/architecture/scan-pipeline.svg", + "file_path": "docs/architecture/scan-pipeline.svg", "line_number": 99, "finding_type": "Base64 Encoded String", - "matched_content_hash": "60f82ca7405be5f3a6c7f4b68b73ac5860326d1803f68cb2c59a6f8cf385b5a4", + "matched_content_hash": "ba9a801e888aa9b07340db3e28892741e9d96ee7603dd608769900ef4c0ccb8b", "plugin_name": "Base64Detector" }, { - "file_path": "./docs/architecture/scan-pipeline.svg", + "file_path": "docs/architecture/scan-pipeline.svg", "line_number": 99, "finding_type": "Base64 Encoded String", - "matched_content_hash": "ba9a801e888aa9b07340db3e28892741e9d96ee7603dd608769900ef4c0ccb8b", + "matched_content_hash": "37af6e0b2eabc53664239dccdc3cbc94143615480a8125c127c0886b7919d7ed", "plugin_name": "Base64Detector" }, { - "file_path": "./docs/architecture/scan-pipeline.svg", + "file_path": "docs/architecture/scan-pipeline.svg", "line_number": 99, "finding_type": "Base64 Encoded String", - "matched_content_hash": "37af6e0b2eabc53664239dccdc3cbc94143615480a8125c127c0886b7919d7ed", + "matched_content_hash": "60f82ca7405be5f3a6c7f4b68b73ac5860326d1803f68cb2c59a6f8cf385b5a4", "plugin_name": "Base64Detector" }, { - "file_path": "./docs/architecture/scan-pipeline.svg", + "file_path": "docs/architecture/scan-pipeline.svg", "line_number": 99, "finding_type": "Base64 Encoded String", - "matched_content_hash": "d11ae8f43eb29643b289cadb28ef5ffbaf4455ea37b89d7c2858ccbd270171be", + "matched_content_hash": "0f3980221f6fd3f6b36a6c1ad85672be41f74a19ca07fe476139e93dca97a2f1", "plugin_name": "Base64Detector" }, { - "file_path": "./docs/architecture/scan-pipeline.svg", + "file_path": "docs/architecture/scan-pipeline.svg", "line_number": 99, - "finding_type": "Random String", - "matched_content_hash": "888b0d80b6cb228df1b6bf35bc6201908bc74a15d2012ce3b1417d043d4d169c", - "plugin_name": "RandomString" + "finding_type": "Base64 Encoded String", + "matched_content_hash": "863a91ad1862061e7a75d0c35635387e87c46d03f419fedf85776419a0857c12", + "plugin_name": "Base64Detector" }, { - "file_path": "./docs/architecture/scan-pipeline.svg", + "file_path": "docs/architecture/scan-pipeline.svg", "line_number": 99, - "finding_type": "Random String", - "matched_content_hash": "6b6adc15e5af26b2c97bfd0a9efa20983d3da2bd27d9cb3b9fd20e33b6bb00a3", - "plugin_name": "RandomString" + "finding_type": "Base64 Encoded String", + "matched_content_hash": "d11ae8f43eb29643b289cadb28ef5ffbaf4455ea37b89d7c2858ccbd270171be", + "plugin_name": "Base64Detector" }, { - "file_path": "./docs/architecture/scan-pipeline.svg", + "file_path": "docs/architecture/scan-pipeline.svg", "line_number": 99, - "finding_type": "Random String", - "matched_content_hash": "fb1a63b387f03e5a3c47f9524380935ddbcf2fc2fa4cea99d6dcd00d9bb7dd3a", - "plugin_name": "RandomString" + "finding_type": "Base64 Encoded String", + "matched_content_hash": "b5458e408e59b20b5f8bb66bb996cf3229bba0f4260ab705070fe7bf7029afa4", + "plugin_name": "Base64Detector" }, { - "file_path": "./src/baseline.rs", + "file_path": "src/baseline.rs", "line_number": 313, "finding_type": "Random String", "matched_content_hash": "c40c9141cd77d55f1ba9d21fb045f8e7c5e900c16f2e563779e7ed75cee6b15b", "plugin_name": "RandomString" }, { - "file_path": "./src/config/tests/application.rs", + "file_path": "src/config/tests/application.rs", "line_number": 317, "finding_type": "Credit Card Number", "matched_content_hash": "4541206d542811878a9374508fe296fa321a8b56c2902736a02f388836f6e108", "plugin_name": "CreditCardDetector" }, { - "file_path": "./src/detector.rs", - "line_number": 145, - "finding_type": "Aadhaar Card Number", - "matched_content_hash": "c941e88b8d0be7288dcc792a8ecfae22482b8a83ea4494f1ca0e36293009730b", - "plugin_name": "AadhaarCardDetector" - }, - { - "file_path": "./src/detector.rs", - "line_number": 151, - "finding_type": "Aadhaar Card Number", - "matched_content_hash": "0476e6cf99db1c000b7e0a433ff83591ffe0472f3156c9ebac7b11d0862f3429", - "plugin_name": "AadhaarCardDetector" + "file_path": "src/detector.rs", + "line_number": 293, + "finding_type": "Random String", + "matched_content_hash": "6bb761274b9fe9cb8eaad9e1c7a0a519c6aa21f619a88bf7c10b6ddc41476822", + "plugin_name": "RandomString" }, { - "file_path": "./src/detector.rs", - "line_number": 152, - "finding_type": "Aadhaar Card Number", - "matched_content_hash": "a1de1619345526170197aa72dd7bcb7e805e4c694270d74c752c317afd4a625e", - "plugin_name": "AadhaarCardDetector" + "file_path": "src/detector.rs", + "line_number": 293, + "finding_type": "Base64 Encoded String", + "matched_content_hash": "55aed33555bb9537c54581d477cb02670b2dc79458c39e02fd8796ccb3aa9cc2", + "plugin_name": "Base64Detector" }, { - "file_path": "./src/detector.rs", + "file_path": "src/detector.rs", "line_number": 669, "finding_type": "Credit Card Number", "matched_content_hash": "4541206d542811878a9374508fe296fa321a8b56c2902736a02f388836f6e108", "plugin_name": "CreditCardDetector" }, { - "file_path": "./src/detector.rs", + "file_path": "src/detector.rs", "line_number": 670, "finding_type": "Credit Card Number", "matched_content_hash": "13ae894eedbfba2dbd06400ba5b215ffd661885646ab86e050fb1a0d192c1c5b", "plugin_name": "CreditCardDetector" }, { - "file_path": "./src/detector.rs", + "file_path": "src/detector.rs", "line_number": 671, "finding_type": "Credit Card Number", "matched_content_hash": "0d30829f4cbd240de78f8dc72d0a5ed0a77887656aa572ee8fb1392cf9ae34a1", "plugin_name": "CreditCardDetector" }, { - "file_path": "./src/detector.rs", + "file_path": "src/detector.rs", "line_number": 686, "finding_type": "Random String", "matched_content_hash": "e51298df0e431de2bfdf6180e3a7b9f3f092c3e9a912facd350e8c7179936e75", "plugin_name": "RandomString" }, { - "file_path": "./src/scanner/lines.rs", + "file_path": "src/scanner/lines.rs", "line_number": 476, "finding_type": "AWS Access Key", "matched_content_hash": "3f733150de7916d4778298d7f90493889c38b76876b80c058e439851ce60cb2b", "plugin_name": "AWSKeyDetector" }, { - "file_path": "./src/scanner/lines.rs", - "line_number": 476, - "finding_type": "Password", - "matched_content_hash": "f6bd37622d846ac435a7b7dcbde2347d59494dfd3c3a787604e8b91491a39c95", - "plugin_name": "PasswordDetector" - }, - { - "file_path": "./src/scanner/lines.rs", + "file_path": "src/scanner/lines.rs", "line_number": 476, "finding_type": "Generic Key/Secret", "matched_content_hash": "f6bd37622d846ac435a7b7dcbde2347d59494dfd3c3a787604e8b91491a39c95", "plugin_name": "GenericKeyValueDetector" }, { - "file_path": "./src/scanner/lines.rs", + "file_path": "src/scanner/lines.rs", "line_number": 532, "finding_type": "SSH Private Key", "matched_content_hash": "678a65e8968aabff441076ae306e13d4fc85b1d36d8036a10d2100c1dc40d251", "plugin_name": "SSHPrivateKeyDetector" }, { - "file_path": "./src/scanner/lines.rs", - "line_number": 532, - "finding_type": "Base64 Encoded String", - "matched_content_hash": "3dde06bf268892d4210f4b0bf1402ecc6a8ad1e015f8204cdc31667762572ef5", - "plugin_name": "Base64Detector" - }, - { - "file_path": "./src/scanner/lines.rs", + "file_path": "src/scanner/lines.rs", "line_number": 532, "finding_type": "Private Key Content", "matched_content_hash": "f91082d1cbd2032b5ea19f2bbf6b3f88e02c12ae320fc9e08e6dc0f73d82bdd1", "plugin_name": "PrivateKeyDetector" }, { - "file_path": "./src/scanner/lines.rs", + "file_path": "src/scanner/lines.rs", "line_number": 532, - "finding_type": "Private Key Content", - "matched_content_hash": "f91082d1cbd2032b5ea19f2bbf6b3f88e02c12ae320fc9e08e6dc0f73d82bdd1", - "plugin_name": "PrivateKeyContentDetector" + "finding_type": "Base64 Encoded String", + "matched_content_hash": "3dde06bf268892d4210f4b0bf1402ecc6a8ad1e015f8204cdc31667762572ef5", + "plugin_name": "Base64Detector" }, { - "file_path": "./src/scanner/lines.rs", + "file_path": "src/scanner/lines.rs", "line_number": 555, "finding_type": "Password", "matched_content_hash": "f260ab98a91b6cf1495f7d0048606e54f4ea955195e06f0523068b49a9611b44", "plugin_name": "PasswordDetector" }, { - "file_path": "./tests/baseline_tests.rs", + "file_path": "tests/baseline_tests.rs", "line_number": 53, "finding_type": "AWS Access Key", "matched_content_hash": "3f733150de7916d4778298d7f90493889c38b76876b80c058e439851ce60cb2b", "plugin_name": "AWSKeyDetector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 254, "finding_type": "Generic Key/Secret", "matched_content_hash": "78eb69b065478e9702683ad7731074c1b46c2ab9c59ef29e9a38754005970888", "plugin_name": "GenericKeyValueDetector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 271, "finding_type": "Stripe API Key", "matched_content_hash": "f5e0f4b16462b5c0a472bc8650167795b846f2b7f825a6a3d9804a8aca2e7864", "plugin_name": "StripeAPIKeyDetector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 272, "finding_type": "Generic Key/Secret", "matched_content_hash": "64ac92e0d5a31bef34682076a022571a87ebbaa61a1c74d7a43bbfa354087548", "plugin_name": "GenericKeyValueDetector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 273, "finding_type": "Password", "matched_content_hash": "4018438f1eaf55ea32baee0422d118935b7a6a4d0a9cb3ce86e41a5ec5827e4b", "plugin_name": "PasswordDetector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 274, "finding_type": "Generic Key/Secret", "matched_content_hash": "650dfe7ddce0129182c60029ba66733efa412ba0824523dd6b096482c4eb8ac9", "plugin_name": "GenericKeyValueDetector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 275, "finding_type": "Generic Key/Secret", "matched_content_hash": "0a47d0e96603faeb13fbcb58b5edf2bc8679cb6e2c9e62d248034b3062f9f5de", "plugin_name": "GenericKeyValueDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 391, - "finding_type": "Password", - "matched_content_hash": "13fb70e44a6b53c3a0a8676508d5308892a889f22d4b86ca2303956e9298e87c", - "plugin_name": "PasswordDetector" - }, - { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 391, "finding_type": "Generic Key/Secret", "matched_content_hash": "13fb70e44a6b53c3a0a8676508d5308892a889f22d4b86ca2303956e9298e87c", "plugin_name": "GenericKeyValueDetector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 392, "finding_type": "Password", "matched_content_hash": "eae6619d56847e403082838f0f97ce6a3e0f78f02af93e652147853a5cbe16c8", "plugin_name": "PasswordDetector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 413, "finding_type": "Credit Card Number", "matched_content_hash": "4541206d542811878a9374508fe296fa321a8b56c2902736a02f388836f6e108", "plugin_name": "CreditCardDetector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 414, "finding_type": "Credit Card Number", "matched_content_hash": "e2e5b50c7d336fb0ed238a9c1dd7520b847fe55b990c8f90ecb810a398854d52", "plugin_name": "CreditCardDetector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 415, "finding_type": "Credit Card Number", "matched_content_hash": "13ae894eedbfba2dbd06400ba5b215ffd661885646ab86e050fb1a0d192c1c5b", "plugin_name": "CreditCardDetector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 416, "finding_type": "Credit Card Number", "matched_content_hash": "7eafa99f1c4d8c35d2a84d390f9e1a9806fb518aaad3bd0c6dde7c9669e1ab97", "plugin_name": "CreditCardDetector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 424, "finding_type": "Credit Card Number", - "matched_content_hash": "52d19e14a2590e721948f58bf1e9dacf8a07049ee1b3238f193a8f15c0f997bf", + "matched_content_hash": "b542aa1c9d50b5b2f457050ecab5fa170d57ae38ebaeb3ef7d4cfcf97b9d4389", "plugin_name": "CreditCardDetector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 424, "finding_type": "Credit Card Number", - "matched_content_hash": "b542aa1c9d50b5b2f457050ecab5fa170d57ae38ebaeb3ef7d4cfcf97b9d4389", + "matched_content_hash": "52d19e14a2590e721948f58bf1e9dacf8a07049ee1b3238f193a8f15c0f997bf", "plugin_name": "CreditCardDetector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 447, "finding_type": "Phone Number", - "matched_content_hash": "af0d73c957c0706f71d0421fd5dd40748b5663537855374b60d71c0624962486", + "matched_content_hash": "9a90be7e1667c88c036f8f271e9746c37d99740f5762fb056090339a75ef24e6", "plugin_name": "PhoneNumberDetector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 447, "finding_type": "Phone Number", - "matched_content_hash": "9a90be7e1667c88c036f8f271e9746c37d99740f5762fb056090339a75ef24e6", + "matched_content_hash": "950cf54889ab5374a01729d84c2e3cf6a086f403b24e4109f522d22d03f1fcf3", "plugin_name": "PhoneNumberDetector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 447, "finding_type": "Phone Number", - "matched_content_hash": "950cf54889ab5374a01729d84c2e3cf6a086f403b24e4109f522d22d03f1fcf3", + "matched_content_hash": "af0d73c957c0706f71d0421fd5dd40748b5663537855374b60d71c0624962486", "plugin_name": "PhoneNumberDetector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 458, "finding_type": "Phone Number", "matched_content_hash": "33360227b18134e6e594a3df05104457bac9713999bb6374dc9bd74fd54c49ee", "plugin_name": "PhoneNumberDetector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 468, "finding_type": "SSH Private Key", "matched_content_hash": "1b01887f477e98dd56ec542c12433dee8c323176bd532c05163823079263ba31", "plugin_name": "SSHPrivateKeyDetector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 469, "finding_type": "SSH Private Key", "matched_content_hash": "32006da0b4e4851aa7946ffa4f040f364cac7c317f312b5d742ca5833dd8760f", "plugin_name": "SSHPrivateKeyDetector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 470, "finding_type": "SSH Private Key", "matched_content_hash": "678a65e8968aabff441076ae306e13d4fc85b1d36d8036a10d2100c1dc40d251", "plugin_name": "SSHPrivateKeyDetector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 481, "finding_type": "Random String", "matched_content_hash": "e51298df0e431de2bfdf6180e3a7b9f3f092c3e9a912facd350e8c7179936e75", "plugin_name": "RandomString" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 501, - "finding_type": "Generic Key/Secret", - "matched_content_hash": "6daabe7b8b2ca9ca4362fee06c2d25e32e59004c5834d23a755f774b02a054c1", - "plugin_name": "GenericKeyValueDetector" - }, - { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 506, "finding_type": "AWS Access Key", "matched_content_hash": "0cbae582394e61dc81d9946ed87ec44f4c83cf1167181f62cd1454eb5e2e5469", "plugin_name": "AWSKeyDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 533, - "finding_type": "Password", - "matched_content_hash": "f6bd37622d846ac435a7b7dcbde2347d59494dfd3c3a787604e8b91491a39c95", - "plugin_name": "PasswordDetector" - }, - { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 533, "finding_type": "Generic Key/Secret", "matched_content_hash": "f6bd37622d846ac435a7b7dcbde2347d59494dfd3c3a787604e8b91491a39c95", "plugin_name": "GenericKeyValueDetector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 534, "finding_type": "Generic Key/Secret", "matched_content_hash": "c98bc65cd589366ec37fedb07e874646469d675fc56078e5b8a3e18d2a70e51e", "plugin_name": "GenericKeyValueDetector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 535, "finding_type": "Password", "matched_content_hash": "af29a321067a1bbd4a7d3f56ba583751c3f0496bd204f642e1e5764766fe9a8c", "plugin_name": "PasswordDetector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 561, "finding_type": "Email Address", "matched_content_hash": "ebe162e5d3cc06b42201b0bfe39fde3379a3fe97c9836631f1750f21db142808", "plugin_name": "EmailDetector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 565, "finding_type": "Email Address", "matched_content_hash": "5900c8c1bad1f56492d653fe4ef68106fd227f791667e7825e183060067aedca", "plugin_name": "EmailDetector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 582, "finding_type": "Phone Number", "matched_content_hash": "8f44b5588c26ec7be961e53be0c11ced694d220020312a942da3a6fa0a1297d2", "plugin_name": "PhoneNumberDetector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 596, "finding_type": "Base64 Encoded String", "matched_content_hash": "097eda6585aa25d794c938beab55a00e7f2e7471a39375a3356535aa2e76efa6", "plugin_name": "Base64Detector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 602, - "finding_type": "Generic Key/Secret", - "matched_content_hash": "c9bff1b4953e132d00a1d95477c81e7e73f15847b0e7d538c5a3a9c022858899", - "plugin_name": "GenericKeyValueDetector" + "finding_type": "Random String", + "matched_content_hash": "f56884431ad6ea3a4fb741ca53cae314b4d3202d6f14bf69aafe86440f799403", + "plugin_name": "RandomString" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 602, "finding_type": "Base64 Encoded String", "matched_content_hash": "a011d6c6ecfe7ed080c7c4bfcc08efc5a3744a7be7a117c466d2536c2ee30a9b", "plugin_name": "Base64Detector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 602, + "finding_type": "Generic Key/Secret", + "matched_content_hash": "c9bff1b4953e132d00a1d95477c81e7e73f15847b0e7d538c5a3a9c022858899", + "plugin_name": "GenericKeyValueDetector" + }, + { + "file_path": "tests/detector_tests.rs", + "line_number": 614, "finding_type": "Random String", - "matched_content_hash": "f56884431ad6ea3a4fb741ca53cae314b4d3202d6f14bf69aafe86440f799403", + "matched_content_hash": "4b98f33784e3a2e93ade7cd0d84c9bebe903fc6cae40c951d055e13e241440f4", "plugin_name": "RandomString" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 614, "finding_type": "Base64 Encoded String", "matched_content_hash": "e64a42fa536515c68483f9b16cae91558748e69c9e7119bc8f32964322a67fe2", "plugin_name": "Base64Detector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 614, + "file_path": "tests/detector_tests.rs", + "line_number": 615, "finding_type": "Random String", - "matched_content_hash": "4b98f33784e3a2e93ade7cd0d84c9bebe903fc6cae40c951d055e13e241440f4", + "matched_content_hash": "74b06d8603b542ac6581dcac272c221820e7dddb4710cd68ad2542892a6c8f2a", "plugin_name": "RandomString" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 613, + "file_path": "tests/detector_tests.rs", + "line_number": 615, "finding_type": "Base64 Encoded String", - "matched_content_hash": "ac20ab4424d46b99caa1d2212a6d5e7898b489819dac4aca5b4befa673d86eb9", + "matched_content_hash": "b5a2901b320d7344b1ed5676cf19aa3bc3d14ed2e513b5b086e4f01f9d85a0da", "plugin_name": "Base64Detector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 613, + "file_path": "tests/detector_tests.rs", + "line_number": 617, "finding_type": "Random String", - "matched_content_hash": "58973fdbd77bc2b26d5b4dd9a4f2a620503900f97cdb5ea0b6a2a096cbf40ad8", + "matched_content_hash": "8f492c68c7d44324c4babb1ab7c115ba365aa9e702b85cb96b2432ed6a9967f2", "plugin_name": "RandomString" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 614, + "file_path": "tests/detector_tests.rs", + "line_number": 617, "finding_type": "Base64 Encoded String", - "matched_content_hash": "e7782831a57b955e7f9103749ee668d9435262c8786ab05c4628ada70049fc44", + "matched_content_hash": "764c955c280af7eb75cdd5ced467826bbec01bb7474379d1bbae74b91f107c97", "plugin_name": "Base64Detector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 614, + "file_path": "tests/detector_tests.rs", + "line_number": 618, "finding_type": "Random String", - "matched_content_hash": "fba74328fc7ea68bf6e93c8e4040972b2940618f35135736bbf17d36e2f6511c", + "matched_content_hash": "be963ea18a45cce7e6304bbbb555137f550f13d598e71b748057ce45b0dfe762", "plugin_name": "RandomString" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 619, + "file_path": "tests/detector_tests.rs", + "line_number": 618, "finding_type": "Base64 Encoded String", - "matched_content_hash": "41e2a39a10ab1a5d623590de9962259020ba4218cb57ebbcd7e90b7f87aa1546", + "matched_content_hash": "9793e393aabc5b9fe76299897081c6f14e6393998549defea81667d04bf22de0", "plugin_name": "Base64Detector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 619, "finding_type": "Random String", "matched_content_hash": "b28d3a52df9a1c7a7d59cbfb6741fdd3d35216675d170a9bc7dbef2744f2b3ec", "plugin_name": "RandomString" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", + "line_number": 619, + "finding_type": "Base64 Encoded String", + "matched_content_hash": "41e2a39a10ab1a5d623590de9962259020ba4218cb57ebbcd7e90b7f87aa1546", + "plugin_name": "Base64Detector" + }, + { + "file_path": "tests/detector_tests.rs", "line_number": 644, "finding_type": "Random String", "matched_content_hash": "30223dbf4c6f1329a106b8f7583cb64cf8d3f583f3eefda7041c662fc2fa87d9", "plugin_name": "RandomString" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 649, "finding_type": "Generic Key/Secret", "matched_content_hash": "7e5cddbc0123c9ac48d6ec86899945d296c02974ff3fd24c89cbdb5a8e7cd74e", "plugin_name": "GenericKeyValueDetector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 663, "finding_type": "Generic Key/Secret", "matched_content_hash": "31ab04ad69305e88b42ca887b277c80c84694d95c2867d19cb48cf3ea745e0fb", "plugin_name": "GenericKeyValueDetector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 696, "finding_type": "Base64 Encoded String", "matched_content_hash": "e10e88c7f8ade4bef7e1129d88ee488f3ca18b10225fe63173133eda5a7e4ecf", "plugin_name": "Base64Detector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 725, "finding_type": "Generic Key/Secret", "matched_content_hash": "3c8321f2331972cb4b8c59d16de3fae99fe333508dfd8741b332817f0c0045c4", "plugin_name": "GenericKeyValueDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 753, - "finding_type": "Generic Key/Secret", - "matched_content_hash": "73e2d76ad4b9f5d13b11b59426ec03ea630309c848008d952e026a173e7b2ab4", - "plugin_name": "GenericKeyValueDetector" - }, - { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 753, "finding_type": "Random String", "matched_content_hash": "c8930ac0699b2ac783fbeeaa531643cf1f97933a23bf50c1e83ca93df8a2c86a", "plugin_name": "RandomString" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 753, "finding_type": "Netlify Token", "matched_content_hash": "a689cfd83519a1d7baacb966f5703133ec6282972f9a80fd6f51295295ffcc3c", "plugin_name": "NetlifyTokenDetector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", + "line_number": 753, + "finding_type": "Generic Key/Secret", + "matched_content_hash": "73e2d76ad4b9f5d13b11b59426ec03ea630309c848008d952e026a173e7b2ab4", + "plugin_name": "GenericKeyValueDetector" + }, + { + "file_path": "tests/detector_tests.rs", "line_number": 762, "finding_type": "Generic Key/Secret", "matched_content_hash": "98c20b40b5197777f3a7dd7251776a09823b3fe2e37c83ca43d36ce74ab49412", "plugin_name": "GenericKeyValueDetector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 770, "finding_type": "Random String", "matched_content_hash": "0d9d69f46579dfe3ed087d18bb0225e0e8412ff02ab21bfa6e1e3b4b50b865f7", "plugin_name": "RandomString" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 777, "finding_type": "Generic Key/Secret", "matched_content_hash": "d48fd8fe619073c8e7853ae91002e34b1687914ed270ebf78ffaa4e73c573bd7", "plugin_name": "GenericKeyValueDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 792, - "finding_type": "Email Address", - "matched_content_hash": "6c6b72437ed83fbd7189e7b99110468ad4356bb9b3231e1178edd2bfc48750fd", - "plugin_name": "EmailDetector" - }, - { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 792, "finding_type": "Generic Key/Secret", "matched_content_hash": "8d4694948a126f262ba0e7839b70fe61f9392018de5334500bd2656f6baf11e5", "plugin_name": "GenericKeyValueDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 801, + "file_path": "tests/detector_tests.rs", + "line_number": 792, + "finding_type": "Email Address", + "matched_content_hash": "6c6b72437ed83fbd7189e7b99110468ad4356bb9b3231e1178edd2bfc48750fd", + "plugin_name": "EmailDetector" + }, + { + "file_path": "tests/detector_tests.rs", + "line_number": 797, + "finding_type": "Generic Key/Secret", + "matched_content_hash": "062952b9995efce6d1c968542689fdd6d3c57e8e362c428f91acaf6450a79f21", + "plugin_name": "GenericKeyValueDetector" + }, + { + "file_path": "tests/detector_tests.rs", + "line_number": 801, + "finding_type": "Generic Key/Secret", + "matched_content_hash": "cc716c48492ba96fbcd95232be522664f95b6d6b112af2919f1f9caae91825cf", + "plugin_name": "GenericKeyValueDetector" + }, + { + "file_path": "tests/detector_tests.rs", + "line_number": 801, "finding_type": "Razorpay API Key", "matched_content_hash": "4357d9b5d7262f331e5bf679bca5850fd5c3d0cc7a3f3f59f32b34ce22ca83a0", "plugin_name": "RazorpayAPIKeyDetector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 808, "finding_type": "IP Address", - "matched_content_hash": "1b7185fb80bd4ae042a8de37da216e5f3c979ae606434c0b35ee7b474f07587c", + "matched_content_hash": "8847dd86386a47986b28e9cc2a6975f510292e2f5a028634b6542164ff4bb6f8", "plugin_name": "IPAddressDetector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 808, "finding_type": "IP Address", - "matched_content_hash": "2e8d922b332b47bc5e30c20c2956e1cb947ef66523fa17aa3ff616c5719d9b61", + "matched_content_hash": "1b7185fb80bd4ae042a8de37da216e5f3c979ae606434c0b35ee7b474f07587c", "plugin_name": "IPAddressDetector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 808, "finding_type": "IP Address", - "matched_content_hash": "60b9673abd1aecb769a499d1c2a75df1f5976a0e5951621663c052d10cb70dc7", + "matched_content_hash": "2e8d922b332b47bc5e30c20c2956e1cb947ef66523fa17aa3ff616c5719d9b61", "plugin_name": "IPAddressDetector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 808, "finding_type": "IP Address", - "matched_content_hash": "8847dd86386a47986b28e9cc2a6975f510292e2f5a028634b6542164ff4bb6f8", + "matched_content_hash": "60b9673abd1aecb769a499d1c2a75df1f5976a0e5951621663c052d10cb70dc7", "plugin_name": "IPAddressDetector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/detector_tests.rs", "line_number": 871, "finding_type": "GCP Service Account Key", "matched_content_hash": "8b77dbdb569eb8b6189e0493fad34e25ced6a8ccbd8331ec36d5a80d2d84eb5f", "plugin_name": "GCPServiceAccountKeyDetector" }, { - "file_path": "./tests/exit_tests.rs", - "line_number": 32, + "file_path": "tests/detector_tests.rs", + "line_number": 910, "finding_type": "AWS Access Key", - "matched_content_hash": "3f733150de7916d4778298d7f90493889c38b76876b80c058e439851ce60cb2b", + "matched_content_hash": "865d995932d48bd4ccdc53238645ff6d5d43e060bbf692d66e3370f5ce1cf746", "plugin_name": "AWSKeyDetector" }, { - "file_path": "./tests/exit_tests.rs", - "line_number": 32, + "file_path": "tests/detector_tests.rs", + "line_number": 913, "finding_type": "Generic Key/Secret", - "matched_content_hash": "d6d60d3e50a63a67cc37ebfac022834f34a7ec0c74d9b5952b8b8ccd50b5f1ff", + "matched_content_hash": "8fdc6b643e52c153a747ab70a7f80c53e79f120c7b47904413d9e5b77ca972e1", "plugin_name": "GenericKeyValueDetector" }, { - "file_path": "./tests/fixtures/fp_corpus/README.md", - "line_number": 3, - "finding_type": "Email Address", - "matched_content_hash": "ebe162e5d3cc06b42201b0bfe39fde3379a3fe97c9836631f1750f21db142808", - "plugin_name": "EmailDetector" + "file_path": "tests/detector_tests.rs", + "line_number": 913, + "finding_type": "AWS Secret Access Key", + "matched_content_hash": "6b085daba2016507175f442843f08fe87148c879fb05e9c53cd6dc346ae9d75f", + "plugin_name": "AWSSecretKeyDetector" }, { - "file_path": "./tests/fixtures/fp_corpus/package.json", - "line_number": 3, + "file_path": "tests/detector_tests.rs", + "line_number": 913, "finding_type": "Base64 Encoded String", - "matched_content_hash": "097eda6585aa25d794c938beab55a00e7f2e7471a39375a3356535aa2e76efa6", + "matched_content_hash": "6c197abf076cfea6ed1ec1d1e35ff8f3930724213b0841bed6c2509b29784ff6", "plugin_name": "Base64Detector" }, { - "file_path": "./tests/hooks_tests.rs", - "line_number": 389, - "finding_type": "Email Address", - "matched_content_hash": "3fea8b798a88a2e9649a3ea443b8c944734f11128bbd451cd3dfde4c4eebe4b7", - "plugin_name": "EmailDetector" + "file_path": "tests/detector_tests.rs", + "line_number": 917, + "finding_type": "GitHub Token", + "matched_content_hash": "3e4f8cb3b94e0a1b7c86b4a50946e22263d19a40548afffc5354777ae3be0d2a", + "plugin_name": "GitHubTokenDetector" }, { - "file_path": "./tests/hooks_tests.rs", - "line_number": 418, - "finding_type": "Email Address", - "matched_content_hash": "a925ccefb3339d83f6d9d23811f6c4a878eabf6df2a389a1c98fa13db0d336a6", - "plugin_name": "EmailDetector" + "file_path": "tests/detector_tests.rs", + "line_number": 917, + "finding_type": "Generic Key/Secret", + "matched_content_hash": "3b11fd40f888000b57ad9c8722bc266e1806df159a61b3f6c4d29d4d20a67e59", + "plugin_name": "GenericKeyValueDetector" }, { - "file_path": "./tests/hooks_tests.rs", - "line_number": 444, - "finding_type": "Email Address", - "matched_content_hash": "79a3e36bd5010edb6d96aae4cbd22eced96e2991b2e1c1ae0bf2cdd5ab29c589", - "plugin_name": "EmailDetector" + "file_path": "tests/detector_tests.rs", + "line_number": 921, + "finding_type": "GitHub Token", + "matched_content_hash": "de2aa2561e7217217afb6937556a045ff3a6ee826f6d4aea799927194eabd5db", + "plugin_name": "GitHubTokenDetector" }, { - "file_path": "./tests/hooks_tests.rs", - "line_number": 642, - "finding_type": "Base64 Encoded String", - "matched_content_hash": "554736805d6e994bf786b21a30653266d29aa65775bbc17eb9f910d2556da91b", - "plugin_name": "Base64Detector" + "file_path": "tests/detector_tests.rs", + "line_number": 925, + "finding_type": "Random String", + "matched_content_hash": "8423d71d9a6fd5e09a6741c6bb3d01bc1d773a95513fa5447211f96da8a6d395", + "plugin_name": "RandomString" }, { - "file_path": "./tests/hooks_tests.rs", - "line_number": 794, - "finding_type": "AWS Access Key", - "matched_content_hash": "3f733150de7916d4778298d7f90493889c38b76876b80c058e439851ce60cb2b", - "plugin_name": "AWSKeyDetector" + "file_path": "tests/detector_tests.rs", + "line_number": 925, + "finding_type": "GitHub Fine-Grained PAT", + "matched_content_hash": "4c282b9c573df8daea4bfc25b4466c3106e1765396b102899ee7b48d4775dac5", + "plugin_name": "GitHubFineGrainedPATDetector" }, { - "file_path": "./tests/report_tests.rs", - "line_number": 100, + "file_path": "tests/detector_tests.rs", + "line_number": 929, + "finding_type": "Random String", + "matched_content_hash": "337a2f33f5738ea49abef3c1c3253f8909f924af9bc7337e0869b8795e79695d", + "plugin_name": "RandomString" + }, + { + "file_path": "tests/detector_tests.rs", + "line_number": 929, "finding_type": "Generic Key/Secret", - "matched_content_hash": "01c80fce098d3bb4634fe8110c31070d44fc509417b970a68733152f066a0089", + "matched_content_hash": "1512aba8af9492ea212748038b4868c715167a18d740e14ac82fb4ef910fb6d2", "plugin_name": "GenericKeyValueDetector" }, { - "file_path": "./tests/report_tests.rs", - "line_number": 329, - "finding_type": "AWS Access Key", - "matched_content_hash": "3f733150de7916d4778298d7f90493889c38b76876b80c058e439851ce60cb2b", - "plugin_name": "AWSKeyDetector" + "file_path": "tests/detector_tests.rs", + "line_number": 929, + "finding_type": "Slack Token", + "matched_content_hash": "ec24b1ae025c523258b45905e028da5592eb7378c0a756d00e6e95cae7c98c63", + "plugin_name": "SlackTokenDetector" }, { - "file_path": "./tests/run_cli_error_tests.rs", - "line_number": 9, - "finding_type": "AWS Access Key", - "matched_content_hash": "3f733150de7916d4778298d7f90493889c38b76876b80c058e439851ce60cb2b", - "plugin_name": "AWSKeyDetector" + "file_path": "tests/detector_tests.rs", + "line_number": 945, + "finding_type": "Random String", + "matched_content_hash": "2466e925ab7084a466f8cee95f8844a2212f11515d48a8053f8cb29dad5e205a", + "plugin_name": "RandomString" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 42, - "finding_type": "Email Address", - "matched_content_hash": "07976d47040b0974eaade10d0da9a9253abeaa82912a2c18e744f0590c90f637", - "plugin_name": "EmailDetector" + "file_path": "tests/detector_tests.rs", + "line_number": 945, + "finding_type": "Slack App Token", + "matched_content_hash": "a1fdb7135bb38d021cba98feaac017fd093e4a11b1c03d00420f016b56db26bb", + "plugin_name": "SlackAppTokenDetector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 109, - "finding_type": "AWS Access Key", - "matched_content_hash": "3f733150de7916d4778298d7f90493889c38b76876b80c058e439851ce60cb2b", - "plugin_name": "AWSKeyDetector" + "file_path": "tests/detector_tests.rs", + "line_number": 949, + "finding_type": "Slack Webhook URL", + "matched_content_hash": "f9dedf87592799bbc78d9a5a41856c71fb077483182f7ac6f1cdeb254188582b", + "plugin_name": "SlackWebhookDetector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 110, - "finding_type": "Password", - "matched_content_hash": "f6bd37622d846ac435a7b7dcbde2347d59494dfd3c3a787604e8b91491a39c95", - "plugin_name": "PasswordDetector" + "file_path": "tests/detector_tests.rs", + "line_number": 958, + "finding_type": "Random String", + "matched_content_hash": "dfed8fce3f43297f4774db0a5451c1f46a34b8085039e627e188b2267264c415", + "plugin_name": "RandomString" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 110, + "file_path": "tests/detector_tests.rs", + "line_number": 958, "finding_type": "Generic Key/Secret", - "matched_content_hash": "f6bd37622d846ac435a7b7dcbde2347d59494dfd3c3a787604e8b91491a39c95", + "matched_content_hash": "546029563145946161a1a36146c7ae5fd9b1a7c985b794dea7e2e681bbd6a388", "plugin_name": "GenericKeyValueDetector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 113, + "file_path": "tests/detector_tests.rs", + "line_number": 958, + "finding_type": "New Relic API Key", + "matched_content_hash": "6728d07e118225e1ed0379b523c096195f632bb98cc784eb9b82e3d01bc9ab32", + "plugin_name": "NewRelicAPIKeyDetector" + }, + { + "file_path": "tests/detector_tests.rs", + "line_number": 966, "finding_type": "Base64 Encoded String", - "matched_content_hash": "c281ba6691c2e2772aebdbd6a7a05c869f7627d7c69eab07edfa130cee7bda70", + "matched_content_hash": "a08c024ab29d4928fc16f9bb9234d63a1cca7c0db43575e5decbe3fca10a9e75", "plugin_name": "Base64Detector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 113, - "finding_type": "SendGrid API Key", - "matched_content_hash": "324af8a2810ec90cd74766d9fa88ddb6957d311ffa77a7a4f1e533f230e6745c", - "plugin_name": "SendGridAPIKeyDetector" + "file_path": "tests/detector_tests.rs", + "line_number": 966, + "finding_type": "OpenAI API Key", + "matched_content_hash": "7a83e11ca64ed2441c10eacfc2a9ece3683813e7cee863d22ce22a537b7439e8", + "plugin_name": "OpenAIProjectKeyDetector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 114, + "file_path": "tests/detector_tests.rs", + "line_number": 970, "finding_type": "Base64 Encoded String", - "matched_content_hash": "703296baa6f0ae75d7b4c6e41b9908603d1273c9db9a28d6fefd4e23d8f3c8b5", + "matched_content_hash": "a8e8235879316e24e151682d10003df635a18fb3bb706b07ce3589d8a8173ff0", "plugin_name": "Base64Detector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 114, - "finding_type": "OpenAI API Key", - "matched_content_hash": "7a0d70456feea263871762c537e5e6141866b456eadc938eb9840e59eb08d1a9", - "plugin_name": "OpenAIAPIKeyDetector" - }, - { - "file_path": "./tests/scanner_tests.rs", - "line_number": 114, + "file_path": "tests/detector_tests.rs", + "line_number": 970, "finding_type": "Kimi/Moonshot API Key", - "matched_content_hash": "7a0d70456feea263871762c537e5e6141866b456eadc938eb9840e59eb08d1a9", + "matched_content_hash": "f11819d7089a7701b2db1ae015c5c0a05762720502531dda40c008aeb391626d", "plugin_name": "KimiMoonshotAPIKeyDetector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 157, + "file_path": "tests/detector_tests.rs", + "line_number": 972, "finding_type": "Stripe API Key", - "matched_content_hash": "c371dd8bd98e42a547fdc2378597152357423ba782bbb8ecbbafd0508ec8b825", + "matched_content_hash": "3f312e5c13b12595f8f3b6f74a8ae6128c1b5a8fb99ca52ea1b4455aa9477331", "plugin_name": "StripeAPIKeyDetector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 187, - "finding_type": "Generic Key/Secret", - "matched_content_hash": "4c8b5530b17fef887a9b327f69a38f1958e4b656f2b1c54b1d426320ead690ff", - "plugin_name": "GenericKeyValueDetector" + "file_path": "tests/detector_tests.rs", + "line_number": 973, + "finding_type": "Stripe API Key", + "matched_content_hash": "c6be1124d243824046a8dfeea346c27527a971b5c6e35e88e95bb5ceed26e83e", + "plugin_name": "StripeAPIKeyDetector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 187, - "finding_type": "Base64 Encoded String", - "matched_content_hash": "332a14e95304a48a4ef671073cc98f0fc4046c61042ac20287bfa22b37c27d01", - "plugin_name": "Base64Detector" + "file_path": "tests/detector_tests.rs", + "line_number": 978, + "finding_type": "Aadhaar Card Number", + "matched_content_hash": "0476e6cf99db1c000b7e0a433ff83591ffe0472f3156c9ebac7b11d0862f3429", + "plugin_name": "AadhaarCardDetector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 188, - "finding_type": "Generic Key/Secret", - "matched_content_hash": "6c6d557cc63eda114745424f991b2019fdfde2844412a1f58fb5527f0e0bef9f", - "plugin_name": "GenericKeyValueDetector" + "file_path": "tests/detector_tests.rs", + "line_number": 979, + "finding_type": "PAN Card Number", + "matched_content_hash": "75d7a58ed9996980fee805fb623d81193cdb5e9efddf2fa12b595171ca16530e", + "plugin_name": "PANCardDetector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 227, - "finding_type": "SSH Private Key", - "matched_content_hash": "678a65e8968aabff441076ae306e13d4fc85b1d36d8036a10d2100c1dc40d251", - "plugin_name": "SSHPrivateKeyDetector" + "file_path": "tests/detector_tests.rs", + "line_number": 980, + "finding_type": "Voter ID (EPIC)", + "matched_content_hash": "e530110a549dd903837a0e2af06b406b01367b4572d07bffee9387334c027f20", + "plugin_name": "VoterIDDetector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 227, - "finding_type": "Base64 Encoded String", - "matched_content_hash": "4587ecda3342a38feff73eef527c2582add9f98a892b185b54b470bb91bc631e", - "plugin_name": "Base64Detector" + "file_path": "tests/detector_tests.rs", + "line_number": 981, + "finding_type": "Social Security Number", + "matched_content_hash": "f9b230216fb066be06e470cb3c0128af42871ef7c232e1359abbb8f28283a79a", + "plugin_name": "SSNDetector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 227, - "finding_type": "Private Key Content", - "matched_content_hash": "b94c156724c086556087773aad998c0791dc79172caa4b3184a7330cfa7c1d76", - "plugin_name": "PrivateKeyDetector" + "file_path": "tests/detector_tests.rs", + "line_number": 982, + "finding_type": "ABHA Health ID", + "matched_content_hash": "f18a39a3c0ab355e4e17257dc1e75985da5a8da0ff0992267750e6c005a32cdc", + "plugin_name": "ABHADetector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 222, - "finding_type": "Private Key Content", - "matched_content_hash": "b94c156724c086556087773aad998c0791dc79172caa4b3184a7330cfa7c1d76", - "plugin_name": "PrivateKeyContentDetector" + "file_path": "tests/detector_tests.rs", + "line_number": 989, + "finding_type": "JWT Token", + "matched_content_hash": "63fab2d473c9588a8eb97b746b1c9471a007965a7bcc984b50282214f6dfbca3", + "plugin_name": "JWTokenDetector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 229, - "finding_type": "SSH Private Key", - "matched_content_hash": "ca54604a9ed82ad96e5f5d68450002ef41112a7058469bbbdde94f83b267dca5", - "plugin_name": "SSHPrivateKeyDetector" + "file_path": "tests/detector_tests.rs", + "line_number": 992, + "finding_type": "Database URL", + "matched_content_hash": "92a764286dc65f3b07669e8a6cfaa88538b7a9ddb279e506df47abc31e6fc67f", + "plugin_name": "DatabaseURLDetector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 229, - "finding_type": "Private Key Content", - "matched_content_hash": "43531827dd6142886cfeb10207f046021a4eb6c575828583ad2cb20d9430c72f", - "plugin_name": "PrivateKeyDetector" + "file_path": "tests/detector_tests.rs", + "line_number": 995, + "finding_type": "Database URL", + "matched_content_hash": "aa01165935d3f8891e4beb2392f0c5cdd5963b5fbe041e4ec9a3fb65d01e098c", + "plugin_name": "DatabaseURLDetector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 230, - "finding_type": "Base64 Encoded String", - "matched_content_hash": "131407c23861d5a739223f303ce0b62808fc0dabe0301622d9836dc3c4999fcb", - "plugin_name": "Base64Detector" + "file_path": "tests/detector_tests.rs", + "line_number": 995, + "finding_type": "MongoDB Connection String", + "matched_content_hash": "86e05b03473347c72e1cbe549b27bea5396b50802162a4ecfc7ac2fcb8fb12f8", + "plugin_name": "MongoDBConnectionStringDetector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 268, - "finding_type": "Password", - "matched_content_hash": "4ba2d1c9c6db00e16d0b1dcead9e6fe60fc315c7b4a76cb2c07def4685dc8669", - "plugin_name": "PasswordDetector" - }, - { - "file_path": "./tests/scanner_tests.rs", - "line_number": 268, + "file_path": "tests/detector_tests.rs", + "line_number": 995, "finding_type": "Email Address", - "matched_content_hash": "48f63a76aa3c93efd693e0d5a960f5fe3ddd697e6a280f812bf678de80106a25", + "matched_content_hash": "6b49e15c059cfbe0fe9f4f9262a1ada9fd0e803098f284fd8b2f7df7a9ea7789", "plugin_name": "EmailDetector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 299, - "finding_type": "Password", - "matched_content_hash": "9f380d00b53e154b8421fb61924bbe35b6f01dccd608f5298f0e35764ee0b654", - "plugin_name": "PasswordDetector" + "file_path": "tests/detector_tests.rs", + "line_number": 999, + "finding_type": "SendGrid API Key", + "matched_content_hash": "9211accd29c5d5e26cbc040c59724ed4f59b2ab9a6fd5ef16ec518eb103f91ed", + "plugin_name": "SendGridAPIKeyDetector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 331, - "finding_type": "Password", - "matched_content_hash": "c505b74b9daf07fb40c38c619a4c0fdf5d807e85223142d6cd19923e7b84e15d", - "plugin_name": "PasswordDetector" + "file_path": "tests/detector_tests.rs", + "line_number": 999, + "finding_type": "Base64 Encoded String", + "matched_content_hash": "83c33a81e18a5ec4b40f7d9314cb8d63d94c0f324938630cd44ca64230bf0e49", + "plugin_name": "Base64Detector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 332, - "finding_type": "Password", - "matched_content_hash": "ca52bf35c9f7b4506aaee67e2aede5c5b09b9b258e850a74e7af0c078e932960", - "plugin_name": "PasswordDetector" + "file_path": "tests/detector_tests.rs", + "line_number": 1003, + "finding_type": "Random String", + "matched_content_hash": "a907b01629778ccd357a125e843211d716ec4d15c8a5d4a29643aa257beaea77", + "plugin_name": "RandomString" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 447, - "finding_type": "Password", - "matched_content_hash": "d1456485b2f315b81fcaffef101a4b398ea558b82bfe6ecee763ef7c327608e7", - "plugin_name": "PasswordDetector" + "file_path": "tests/detector_tests.rs", + "line_number": 1003, + "finding_type": "DigitalOcean API Token", + "matched_content_hash": "eac5db004534e626e7b61daf10ca90fb6fe258c812cd7845f4f75c03d496c2b2", + "plugin_name": "DigitalOceanTokenDetector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 454, - "finding_type": "Generic Key/Secret", - "matched_content_hash": "d1456485b2f315b81fcaffef101a4b398ea558b82bfe6ecee763ef7c327608e7", - "plugin_name": "GenericKeyValueDetector" + "file_path": "tests/detector_tests.rs", + "line_number": 1007, + "finding_type": "Random String", + "matched_content_hash": "c99d7da93fde37dd019d0cf73b366d4142c7e5af291ae011f627da6eef9283a2", + "plugin_name": "RandomString" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 479, - "finding_type": "Password", - "matched_content_hash": "795c0808e6128ceee90a9dada1ad2ad243d07534def7532d5adf7e82a7237374", - "plugin_name": "PasswordDetector" + "file_path": "tests/detector_tests.rs", + "line_number": 1007, + "finding_type": "NPM Token", + "matched_content_hash": "93fa4d52f8628507260c420eda9d4e5b8b53083eaa9c1650697f15ef6c1d4cda", + "plugin_name": "NPMTokenDetector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 490, + "file_path": "tests/detector_tests.rs", + "line_number": 1011, + "finding_type": "Heroku API Key", + "matched_content_hash": "e8cd71caa187d4d908480c35dabd5ac3eaad88e33174fac1229926b78b715a97", + "plugin_name": "HerokuAPIKeyDetector" + }, + { + "file_path": "tests/detector_tests.rs", + "line_number": 1011, "finding_type": "Generic Key/Secret", - "matched_content_hash": "795c0808e6128ceee90a9dada1ad2ad243d07534def7532d5adf7e82a7237374", + "matched_content_hash": "ad7c54874c2910b3ff65345d4bfba97c7aae5e95307bfa745ecf2c2c6c406b29", "plugin_name": "GenericKeyValueDetector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 518, - "finding_type": "Password", - "matched_content_hash": "ead01d09cbf0176f24f604a4a4f955b32c34b155fe614e81ecc52f2c6fe89a3f", - "plugin_name": "PasswordDetector" + "file_path": "tests/detector_tests.rs", + "line_number": 1015, + "finding_type": "Random String", + "matched_content_hash": "f48ffeb7e4c083b563be0cff8e4158476658cfc15dc493c14d127fecf31259ae", + "plugin_name": "RandomString" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 529, - "finding_type": "Generic Key/Secret", - "matched_content_hash": "ead01d09cbf0176f24f604a4a4f955b32c34b155fe614e81ecc52f2c6fe89a3f", - "plugin_name": "GenericKeyValueDetector" + "file_path": "tests/detector_tests.rs", + "line_number": 1015, + "finding_type": "Groq API Key", + "matched_content_hash": "659ba6bae01aab6d09327e7f2d2f808140fd6b990db40a35b1a9cb967ad4b6f4", + "plugin_name": "GroqAPIKeyDetector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 660, - "finding_type": "Aadhaar Card Number", - "matched_content_hash": "4714ac4f70659987acae4a4760aedecd3924449f855e3be8115a51eb1ad35f93", - "plugin_name": "AadhaarCardDetector" + "file_path": "tests/detector_tests.rs", + "line_number": 1019, + "finding_type": "Random String", + "matched_content_hash": "15ce329320873469fe3be8c5266a0d158b2b49a3903447e1d5e0cae1cd4b54b3", + "plugin_name": "RandomString" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 660, - "finding_type": "Aadhaar Card Number", - "matched_content_hash": "73e8a0879ef4b4acf94b2c188c0b620e4dd198bef454f6270118d63fd87ff4a3", - "plugin_name": "AadhaarCardDetector" + "file_path": "tests/detector_tests.rs", + "line_number": 1019, + "finding_type": "Hugging Face Token", + "matched_content_hash": "7e620527f0ee998f548f41283f1fd607497f176e8b801154231db33265b5046d", + "plugin_name": "HuggingFaceTokenDetector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 660, - "finding_type": "Aadhaar Card Number", - "matched_content_hash": "c941e88b8d0be7288dcc792a8ecfae22482b8a83ea4494f1ca0e36293009730b", - "plugin_name": "AadhaarCardDetector" + "file_path": "tests/detector_tests.rs", + "line_number": 1023, + "finding_type": "GitLab Personal Access Token", + "matched_content_hash": "1c920d68e02f0cf8f21a1be01c6e91256e4e7e60461406a4bb103af5a4e99539", + "plugin_name": "GitLabPersonalAccessTokenDetector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 687, - "finding_type": "Voter ID (EPIC)", - "matched_content_hash": "e530110a549dd903837a0e2af06b406b01367b4572d07bffee9387334c027f20", - "plugin_name": "VoterIDDetector" + "file_path": "tests/detector_tests.rs", + "line_number": 1027, + "finding_type": "HashiCorp Vault Token", + "matched_content_hash": "0e290623d9b5c162f39a3b894bc2a500c542cb879e2b295d321677485eb3315b", + "plugin_name": "HashicorpVaultTokenDetector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 687, - "finding_type": "Voter ID (EPIC)", - "matched_content_hash": "8d6bf65189e5bdf52955b4a1592eb9c2fb0560709152317a1dabc36971c38f30", - "plugin_name": "VoterIDDetector" + "file_path": "tests/detector_tests.rs", + "line_number": 1031, + "finding_type": "Google OAuth Token", + "matched_content_hash": "14bcf91874e68f421e946b8414c43fbe04f1d5ee1b97fd58d4d2bb10a08cb82b", + "plugin_name": "GoogleOAuthTokenDetector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 711, - "finding_type": "PAN Card Number", - "matched_content_hash": "75d7a58ed9996980fee805fb623d81193cdb5e9efddf2fa12b595171ca16530e", - "plugin_name": "PANCardDetector" + "file_path": "tests/detector_tests.rs", + "line_number": 1035, + "finding_type": "Random String", + "matched_content_hash": "0b71a8751aa19a3057b98d957c12b1d0f713b6fed41fb2c1eb244ff45c0942ae", + "plugin_name": "RandomString" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 711, - "finding_type": "PAN Card Number", - "matched_content_hash": "4dd22fad4bf96036ceea29ca253be8d72851cc289d7e694c9b208b7370812ee6", - "plugin_name": "PANCardDetector" + "file_path": "tests/detector_tests.rs", + "line_number": 1035, + "finding_type": "Shopify Access Token", + "matched_content_hash": "a954f6f8f04f0be943d4b794a5d1881ccab4704c42cc7f1032988e969c75e1c8", + "plugin_name": "ShopifyAccessTokenDetector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 735, - "finding_type": "ABHA Health ID", - "matched_content_hash": "25b618101c3bfdb4438894aa540e108cd150903bd24da57ac24f0d4174c0fe7e", - "plugin_name": "ABHADetector" + "file_path": "tests/detector_tests.rs", + "line_number": 1039, + "finding_type": "Base64 Encoded String", + "matched_content_hash": "554736805d6e994bf786b21a30653266d29aa65775bbc17eb9f910d2556da91b", + "plugin_name": "Base64Detector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 735, - "finding_type": "ABHA Health ID", - "matched_content_hash": "397d0bc36d77ccfc6f74c2eaa6615bb75c3fe3bdc3df26e6f53f413cfcdacdb3", - "plugin_name": "ABHADetector" + "file_path": "tests/exit_tests.rs", + "line_number": 32, + "finding_type": "AWS Access Key", + "matched_content_hash": "3f733150de7916d4778298d7f90493889c38b76876b80c058e439851ce60cb2b", + "plugin_name": "AWSKeyDetector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 760, - "finding_type": "Aadhaar Card Number", - "matched_content_hash": "8d7ab03162973f8bc2baf7c8556af862841d23c4d66f7f18f8cf5c5777f8b263", - "plugin_name": "AadhaarCardDetector" + "file_path": "tests/exit_tests.rs", + "line_number": 32, + "finding_type": "Generic Key/Secret", + "matched_content_hash": "d6d60d3e50a63a67cc37ebfac022834f34a7ec0c74d9b5952b8b8ccd50b5f1ff", + "plugin_name": "GenericKeyValueDetector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 760, - "finding_type": "PAN Card Number", - "matched_content_hash": "18fe123b5e00bbed7228c4ededc8a4e6e0bfd59169af97ec2e62b595eac11dde", - "plugin_name": "PANCardDetector" + "file_path": "tests/fixtures/fp_corpus/README.md", + "line_number": 3, + "finding_type": "Email Address", + "matched_content_hash": "ebe162e5d3cc06b42201b0bfe39fde3379a3fe97c9836631f1750f21db142808", + "plugin_name": "EmailDetector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 760, - "finding_type": "ABHA Health ID", - "matched_content_hash": "89deb2b58721d6303daa4a62f2dee30b9a388afb905fc4d3595ec88ca875fb15", - "plugin_name": "ABHADetector" + "file_path": "tests/fixtures/fp_corpus/package.json", + "line_number": 3, + "finding_type": "Base64 Encoded String", + "matched_content_hash": "097eda6585aa25d794c938beab55a00e7f2e7471a39375a3356535aa2e76efa6", + "plugin_name": "Base64Detector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 865, - "finding_type": "Google API Key", - "matched_content_hash": "aec6660855470791a5b4f5a6c1ac4b61e61d2b942b1cdec400fb7811743798d0", - "plugin_name": "GoogleAPIKeyDetector" + "file_path": "tests/hooks_tests.rs", + "line_number": 389, + "finding_type": "Email Address", + "matched_content_hash": "3fea8b798a88a2e9649a3ea443b8c944734f11128bbd451cd3dfde4c4eebe4b7", + "plugin_name": "EmailDetector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 865, - "finding_type": "Random String", - "matched_content_hash": "cbe1ce18b874bc08437699d863cd422c49e104462e7d5ac6bd390acc0d7c973a", - "plugin_name": "RandomString" + "file_path": "tests/hooks_tests.rs", + "line_number": 418, + "finding_type": "Email Address", + "matched_content_hash": "a925ccefb3339d83f6d9d23811f6c4a878eabf6df2a389a1c98fa13db0d336a6", + "plugin_name": "EmailDetector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 912, - "finding_type": "Password", - "matched_content_hash": "67ef748345ad7f183084a7449ec05906e648c882400b9d940f2fadec23a7b197", - "plugin_name": "PasswordDetector" + "file_path": "tests/hooks_tests.rs", + "line_number": 444, + "finding_type": "Email Address", + "matched_content_hash": "79a3e36bd5010edb6d96aae4cbd22eced96e2991b2e1c1ae0bf2cdd5ab29c589", + "plugin_name": "EmailDetector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 1007, + "file_path": "tests/hooks_tests.rs", + "line_number": 642, + "finding_type": "Base64 Encoded String", + "matched_content_hash": "554736805d6e994bf786b21a30653266d29aa65775bbc17eb9f910d2556da91b", + "plugin_name": "Base64Detector" + }, + { + "file_path": "tests/hooks_tests.rs", + "line_number": 794, "finding_type": "AWS Access Key", - "matched_content_hash": "05c0aace2b76ca255ed3a7a953016d981477226dccc3b0e709d00174c8bc48b5", + "matched_content_hash": "3f733150de7916d4778298d7f90493889c38b76876b80c058e439851ce60cb2b", "plugin_name": "AWSKeyDetector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 1650, + "file_path": "tests/report_tests.rs", + "line_number": 100, "finding_type": "Generic Key/Secret", - "matched_content_hash": "97894929682fc00219686473cbcfa3731d73b23e88ffa7c19a511c1bbfa18aa5", + "matched_content_hash": "01c80fce098d3bb4634fe8110c31070d44fc509417b970a68733152f066a0089", "plugin_name": "GenericKeyValueDetector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 1854, + "file_path": "tests/report_tests.rs", + "line_number": 329, "finding_type": "AWS Access Key", - "matched_content_hash": "357b7fb7890985d4c94a43012d1f7aefe25757f36d8810388357993bb38bd8e7", + "matched_content_hash": "3f733150de7916d4778298d7f90493889c38b76876b80c058e439851ce60cb2b", "plugin_name": "AWSKeyDetector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 2106, + "file_path": "tests/run_cli_error_tests.rs", + "line_number": 9, "finding_type": "AWS Access Key", - "matched_content_hash": "0cbae582394e61dc81d9946ed87ec44f4c83cf1167181f62cd1454eb5e2e5469", + "matched_content_hash": "3f733150de7916d4778298d7f90493889c38b76876b80c058e439851ce60cb2b", "plugin_name": "AWSKeyDetector" }, { - "file_path": "./tests/scanner_tests.rs", - "line_number": 2407, - "finding_type": "Password", - "matched_content_hash": "6121378fbc25183476235d474ee367f7dbd0bbe3d96642daaeb483b5e9108cdb", - "plugin_name": "PasswordDetector" + "file_path": "tests/run_cli_error_tests.rs", + "line_number": 9, + "finding_type": "Generic Key/Secret", + "matched_content_hash": "d6d60d3e50a63a67cc37ebfac022834f34a7ec0c74d9b5952b8b8ccd50b5f1ff", + "plugin_name": "GenericKeyValueDetector" }, { - "file_path": "./src/detector.rs", - "line_number": 293, - "finding_type": "Base64 Encoded String", - "matched_content_hash": "55aed33555bb9537c54581d477cb02670b2dc79458c39e02fd8796ccb3aa9cc2", - "plugin_name": "Base64Detector" + "file_path": "tests/scanner_tests.rs", + "line_number": 42, + "finding_type": "Email Address", + "matched_content_hash": "07976d47040b0974eaade10d0da9a9253abeaa82912a2c18e744f0590c90f637", + "plugin_name": "EmailDetector" }, { - "file_path": "./src/detector.rs", - "line_number": 293, - "finding_type": "Random String", - "matched_content_hash": "6bb761274b9fe9cb8eaad9e1c7a0a519c6aa21f619a88bf7c10b6ddc41476822", - "plugin_name": "RandomString" + "file_path": "tests/scanner_tests.rs", + "line_number": 109, + "finding_type": "AWS Access Key", + "matched_content_hash": "3f733150de7916d4778298d7f90493889c38b76876b80c058e439851ce60cb2b", + "plugin_name": "AWSKeyDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 615, - "finding_type": "Base64 Encoded String", - "matched_content_hash": "b5a2901b320d7344b1ed5676cf19aa3bc3d14ed2e513b5b086e4f01f9d85a0da", - "plugin_name": "Base64Detector" + "file_path": "tests/scanner_tests.rs", + "line_number": 110, + "finding_type": "Generic Key/Secret", + "matched_content_hash": "f6bd37622d846ac435a7b7dcbde2347d59494dfd3c3a787604e8b91491a39c95", + "plugin_name": "GenericKeyValueDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 615, - "finding_type": "Random String", - "matched_content_hash": "74b06d8603b542ac6581dcac272c221820e7dddb4710cd68ad2542892a6c8f2a", - "plugin_name": "RandomString" - }, - { - "file_path": "./tests/detector_tests.rs", - "line_number": 617, - "finding_type": "Base64 Encoded String", - "matched_content_hash": "764c955c280af7eb75cdd5ced467826bbec01bb7474379d1bbae74b91f107c97", - "plugin_name": "Base64Detector" - }, - { - "file_path": "./tests/detector_tests.rs", - "line_number": 617, - "finding_type": "Random String", - "matched_content_hash": "8f492c68c7d44324c4babb1ab7c115ba365aa9e702b85cb96b2432ed6a9967f2", - "plugin_name": "RandomString" + "file_path": "tests/scanner_tests.rs", + "line_number": 113, + "finding_type": "SendGrid API Key", + "matched_content_hash": "324af8a2810ec90cd74766d9fa88ddb6957d311ffa77a7a4f1e533f230e6745c", + "plugin_name": "SendGridAPIKeyDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 618, + "file_path": "tests/scanner_tests.rs", + "line_number": 113, "finding_type": "Base64 Encoded String", - "matched_content_hash": "9793e393aabc5b9fe76299897081c6f14e6393998549defea81667d04bf22de0", + "matched_content_hash": "c281ba6691c2e2772aebdbd6a7a05c869f7627d7c69eab07edfa130cee7bda70", "plugin_name": "Base64Detector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 618, - "finding_type": "Random String", - "matched_content_hash": "be963ea18a45cce7e6304bbbb555137f550f13d598e71b748057ce45b0dfe762", - "plugin_name": "RandomString" - }, - { - "file_path": "./tests/scanner_tests.rs", - "line_number": 2521, + "file_path": "tests/scanner_tests.rs", + "line_number": 114, "finding_type": "Base64 Encoded String", - "matched_content_hash": "37f93597692f90e64e009b94ce81237f0f5a6d03ffce8085e91814efe71e4431", + "matched_content_hash": "703296baa6f0ae75d7b4c6e41b9908603d1273c9db9a28d6fefd4e23d8f3c8b5", "plugin_name": "Base64Detector" }, { - "file_path": "./.github/workflows/ci.yml", - "line_number": 74, - "finding_type": "Generic Key/Secret", - "matched_content_hash": "f1b334a28e2052a9e8870fc7fd7383f477199e8e138f1a46f83ee39a2c80a341", - "plugin_name": "GenericKeyValueDetector" - }, - { - "file_path": "./tests/detector_tests.rs", - "line_number": 797, - "finding_type": "Generic Key/Secret", - "matched_content_hash": "062952b9995efce6d1c968542689fdd6d3c57e8e362c428f91acaf6450a79f21", - "plugin_name": "GenericKeyValueDetector" - }, - { - "file_path": "./tests/detector_tests.rs", - "line_number": 801, - "finding_type": "Generic Key/Secret", - "matched_content_hash": "cc716c48492ba96fbcd95232be522664f95b6d6b112af2919f1f9caae91825cf", - "plugin_name": "GenericKeyValueDetector" + "file_path": "tests/scanner_tests.rs", + "line_number": 114, + "finding_type": "OpenAI API Key", + "matched_content_hash": "7a0d70456feea263871762c537e5e6141866b456eadc938eb9840e59eb08d1a9", + "plugin_name": "OpenAIAPIKeyDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 910, - "finding_type": "AWS Access Key", - "matched_content_hash": "865d995932d48bd4ccdc53238645ff6d5d43e060bbf692d66e3370f5ce1cf746", - "plugin_name": "AWSKeyDetector" + "file_path": "tests/scanner_tests.rs", + "line_number": 157, + "finding_type": "Stripe API Key", + "matched_content_hash": "c371dd8bd98e42a547fdc2378597152357423ba782bbb8ecbbafd0508ec8b825", + "plugin_name": "StripeAPIKeyDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 913, + "file_path": "tests/scanner_tests.rs", + "line_number": 187, "finding_type": "Generic Key/Secret", - "matched_content_hash": "8fdc6b643e52c153a747ab70a7f80c53e79f120c7b47904413d9e5b77ca972e1", + "matched_content_hash": "4c8b5530b17fef887a9b327f69a38f1958e4b656f2b1c54b1d426320ead690ff", "plugin_name": "GenericKeyValueDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 913, + "file_path": "tests/scanner_tests.rs", + "line_number": 187, "finding_type": "AWS Secret Access Key", - "matched_content_hash": "6b085daba2016507175f442843f08fe87148c879fb05e9c53cd6dc346ae9d75f", + "matched_content_hash": "2c770dc5ac4de63cd2cb89e604080a34ce55dd946586ba7e0d961b31e321403f", "plugin_name": "AWSSecretKeyDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 913, + "file_path": "tests/scanner_tests.rs", + "line_number": 187, "finding_type": "Base64 Encoded String", - "matched_content_hash": "6c197abf076cfea6ed1ec1d1e35ff8f3930724213b0841bed6c2509b29784ff6", + "matched_content_hash": "332a14e95304a48a4ef671073cc98f0fc4046c61042ac20287bfa22b37c27d01", "plugin_name": "Base64Detector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 917, - "finding_type": "GitHub Token", - "matched_content_hash": "3e4f8cb3b94e0a1b7c86b4a50946e22263d19a40548afffc5354777ae3be0d2a", - "plugin_name": "GitHubTokenDetector" - }, - { - "file_path": "./tests/detector_tests.rs", - "line_number": 917, + "file_path": "tests/scanner_tests.rs", + "line_number": 188, "finding_type": "Generic Key/Secret", - "matched_content_hash": "3b11fd40f888000b57ad9c8722bc266e1806df159a61b3f6c4d29d4d20a67e59", + "matched_content_hash": "6c6d557cc63eda114745424f991b2019fdfde2844412a1f58fb5527f0e0bef9f", "plugin_name": "GenericKeyValueDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 921, - "finding_type": "GitHub Token", - "matched_content_hash": "de2aa2561e7217217afb6937556a045ff3a6ee826f6d4aea799927194eabd5db", - "plugin_name": "GitHubTokenDetector" - }, - { - "file_path": "./tests/detector_tests.rs", - "line_number": 925, - "finding_type": "Random String", - "matched_content_hash": "8423d71d9a6fd5e09a6741c6bb3d01bc1d773a95513fa5447211f96da8a6d395", - "plugin_name": "RandomString" - }, - { - "file_path": "./tests/detector_tests.rs", - "line_number": 925, - "finding_type": "GitHub Fine-Grained PAT", - "matched_content_hash": "4c282b9c573df8daea4bfc25b4466c3106e1765396b102899ee7b48d4775dac5", - "plugin_name": "GitHubFineGrainedPATDetector" - }, - { - "file_path": "./tests/detector_tests.rs", - "line_number": 929, - "finding_type": "Random String", - "matched_content_hash": "337a2f33f5738ea49abef3c1c3253f8909f924af9bc7337e0869b8795e79695d", - "plugin_name": "RandomString" + "file_path": "tests/scanner_tests.rs", + "line_number": 227, + "finding_type": "SSH Private Key", + "matched_content_hash": "678a65e8968aabff441076ae306e13d4fc85b1d36d8036a10d2100c1dc40d251", + "plugin_name": "SSHPrivateKeyDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 929, - "finding_type": "Generic Key/Secret", - "matched_content_hash": "1512aba8af9492ea212748038b4868c715167a18d740e14ac82fb4ef910fb6d2", - "plugin_name": "GenericKeyValueDetector" + "file_path": "tests/scanner_tests.rs", + "line_number": 227, + "finding_type": "Private Key Content", + "matched_content_hash": "b94c156724c086556087773aad998c0791dc79172caa4b3184a7330cfa7c1d76", + "plugin_name": "PrivateKeyDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 929, - "finding_type": "Slack Token", - "matched_content_hash": "ec24b1ae025c523258b45905e028da5592eb7378c0a756d00e6e95cae7c98c63", - "plugin_name": "SlackTokenDetector" + "file_path": "tests/scanner_tests.rs", + "line_number": 227, + "finding_type": "Base64 Encoded String", + "matched_content_hash": "4587ecda3342a38feff73eef527c2582add9f98a892b185b54b470bb91bc631e", + "plugin_name": "Base64Detector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 933, - "finding_type": "Slack Token", - "matched_content_hash": "74d119545fd7143794eaaaf8b9582b8f1ef60a5852ff0ccc567e4dcdcbfd17e6", - "plugin_name": "SlackTokenDetector" + "file_path": "tests/scanner_tests.rs", + "line_number": 229, + "finding_type": "SSH Private Key", + "matched_content_hash": "ca54604a9ed82ad96e5f5d68450002ef41112a7058469bbbdde94f83b267dca5", + "plugin_name": "SSHPrivateKeyDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 937, - "finding_type": "Random String", - "matched_content_hash": "1432c8582e4f9c1e5201b465a34b770e854320150645cc9177d23b61e28fbc39", - "plugin_name": "RandomString" + "file_path": "tests/scanner_tests.rs", + "line_number": 229, + "finding_type": "Private Key Content", + "matched_content_hash": "43531827dd6142886cfeb10207f046021a4eb6c575828583ad2cb20d9430c72f", + "plugin_name": "PrivateKeyDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 937, - "finding_type": "Slack Token", - "matched_content_hash": "bff7d29efee46d801b4ae196b418028e9faa8dd0eef6b7eaf61e4db602e2043b", - "plugin_name": "SlackTokenDetector" + "file_path": "tests/scanner_tests.rs", + "line_number": 230, + "finding_type": "Base64 Encoded String", + "matched_content_hash": "131407c23861d5a739223f303ce0b62808fc0dabe0301622d9836dc3c4999fcb", + "plugin_name": "Base64Detector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 941, - "finding_type": "Slack Token", - "matched_content_hash": "b1f3c367f42b3d1567236f334f5760d1ea678fa4f828c346c825084ce9b79bbf", - "plugin_name": "SlackTokenDetector" + "file_path": "tests/scanner_tests.rs", + "line_number": 268, + "finding_type": "Password", + "matched_content_hash": "4ba2d1c9c6db00e16d0b1dcead9e6fe60fc315c7b4a76cb2c07def4685dc8669", + "plugin_name": "PasswordDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 945, - "finding_type": "Random String", - "matched_content_hash": "2466e925ab7084a466f8cee95f8844a2212f11515d48a8053f8cb29dad5e205a", - "plugin_name": "RandomString" + "file_path": "tests/scanner_tests.rs", + "line_number": 268, + "finding_type": "Email Address", + "matched_content_hash": "48f63a76aa3c93efd693e0d5a960f5fe3ddd697e6a280f812bf678de80106a25", + "plugin_name": "EmailDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 945, - "finding_type": "Slack App Token", - "matched_content_hash": "a1fdb7135bb38d021cba98feaac017fd093e4a11b1c03d00420f016b56db26bb", - "plugin_name": "SlackAppTokenDetector" + "file_path": "tests/scanner_tests.rs", + "line_number": 299, + "finding_type": "Password", + "matched_content_hash": "9f380d00b53e154b8421fb61924bbe35b6f01dccd608f5298f0e35764ee0b654", + "plugin_name": "PasswordDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 949, - "finding_type": "Slack Webhook URL", - "matched_content_hash": "f9dedf87592799bbc78d9a5a41856c71fb077483182f7ac6f1cdeb254188582b", - "plugin_name": "SlackWebhookDetector" + "file_path": "tests/scanner_tests.rs", + "line_number": 331, + "finding_type": "Password", + "matched_content_hash": "c505b74b9daf07fb40c38c619a4c0fdf5d807e85223142d6cd19923e7b84e15d", + "plugin_name": "PasswordDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 958, - "finding_type": "Random String", - "matched_content_hash": "dfed8fce3f43297f4774db0a5451c1f46a34b8085039e627e188b2267264c415", - "plugin_name": "RandomString" + "file_path": "tests/scanner_tests.rs", + "line_number": 332, + "finding_type": "Password", + "matched_content_hash": "ca52bf35c9f7b4506aaee67e2aede5c5b09b9b258e850a74e7af0c078e932960", + "plugin_name": "PasswordDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 958, + "file_path": "tests/scanner_tests.rs", + "line_number": 453, "finding_type": "Generic Key/Secret", - "matched_content_hash": "546029563145946161a1a36146c7ae5fd9b1a7c985b794dea7e2e681bbd6a388", + "matched_content_hash": "bbc84628b4a0a5db38b2d8ed22fb8b5f4a880a6b0037ba055f9007c6192d8f05", "plugin_name": "GenericKeyValueDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 958, - "finding_type": "New Relic API Key", - "matched_content_hash": "6728d07e118225e1ed0379b523c096195f632bb98cc784eb9b82e3d01bc9ab32", - "plugin_name": "NewRelicAPIKeyDetector" - }, - { - "file_path": "./tests/detector_tests.rs", - "line_number": 962, - "finding_type": "Random String", - "matched_content_hash": "137ed02c2e891b2c42af3b1d18ff0ec3f5276db7da25899292da4b54fda38e3e", - "plugin_name": "RandomString" - }, - { - "file_path": "./tests/detector_tests.rs", - "line_number": 962, - "finding_type": "Base64 Encoded String", - "matched_content_hash": "57f370ecd1c4cb9edfd1eb097ef7778dc0505195a5091f4f55a29495a0f5e67c", - "plugin_name": "Base64Detector" - }, - { - "file_path": "./tests/detector_tests.rs", - "line_number": 962, + "file_path": "tests/scanner_tests.rs", + "line_number": 454, "finding_type": "Generic Key/Secret", - "matched_content_hash": "5eb864b5ab65b0cb4e822fd180592dc92d0390623ab7afc5190bd6d9e4cfba50", + "matched_content_hash": "d1456485b2f315b81fcaffef101a4b398ea558b82bfe6ecee763ef7c327608e7", "plugin_name": "GenericKeyValueDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 962, - "finding_type": "OpenAI API Key", - "matched_content_hash": "e5b0e854196cc9e27d873d8782220d5fc08f82cd8560f701e8ee7375c3c9695d", - "plugin_name": "OpenAIAPIKeyDetector" - }, - { - "file_path": "./tests/detector_tests.rs", - "line_number": 966, - "finding_type": "Base64 Encoded String", - "matched_content_hash": "a08c024ab29d4928fc16f9bb9234d63a1cca7c0db43575e5decbe3fca10a9e75", - "plugin_name": "Base64Detector" - }, - { - "file_path": "./tests/detector_tests.rs", - "line_number": 966, - "finding_type": "OpenAI API Key", - "matched_content_hash": "7a83e11ca64ed2441c10eacfc2a9ece3683813e7cee863d22ce22a537b7439e8", - "plugin_name": "OpenAIProjectKeyDetector" - }, - { - "file_path": "./tests/detector_tests.rs", - "line_number": 970, - "finding_type": "Base64 Encoded String", - "matched_content_hash": "a8e8235879316e24e151682d10003df635a18fb3bb706b07ce3589d8a8173ff0", - "plugin_name": "Base64Detector" - }, - { - "file_path": "./tests/detector_tests.rs", - "line_number": 970, - "finding_type": "Kimi/Moonshot API Key", - "matched_content_hash": "f11819d7089a7701b2db1ae015c5c0a05762720502531dda40c008aeb391626d", - "plugin_name": "KimiMoonshotAPIKeyDetector" - }, - { - "file_path": "./tests/detector_tests.rs", - "line_number": 972, - "finding_type": "Stripe API Key", - "matched_content_hash": "3f312e5c13b12595f8f3b6f74a8ae6128c1b5a8fb99ca52ea1b4455aa9477331", - "plugin_name": "StripeAPIKeyDetector" + "file_path": "tests/scanner_tests.rs", + "line_number": 490, + "finding_type": "Generic Key/Secret", + "matched_content_hash": "795c0808e6128ceee90a9dada1ad2ad243d07534def7532d5adf7e82a7237374", + "plugin_name": "GenericKeyValueDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 973, - "finding_type": "Stripe API Key", - "matched_content_hash": "c6be1124d243824046a8dfeea346c27527a971b5c6e35e88e95bb5ceed26e83e", - "plugin_name": "StripeAPIKeyDetector" + "file_path": "tests/scanner_tests.rs", + "line_number": 529, + "finding_type": "Generic Key/Secret", + "matched_content_hash": "ead01d09cbf0176f24f604a4a4f955b32c34b155fe614e81ecc52f2c6fe89a3f", + "plugin_name": "GenericKeyValueDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 976, - "finding_type": "Stripe Publishable Key", - "matched_content_hash": "14c960319d6e91cf667693e6a6e5be5f8c3042b63c05e9ffb6bc01add95fa2d0", - "plugin_name": "StripePublishableKeyDetector" + "file_path": "tests/scanner_tests.rs", + "line_number": 660, + "finding_type": "Aadhaar Card Number", + "matched_content_hash": "73e8a0879ef4b4acf94b2c188c0b620e4dd198bef454f6270118d63fd87ff4a3", + "plugin_name": "AadhaarCardDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 978, + "file_path": "tests/scanner_tests.rs", + "line_number": 660, "finding_type": "Aadhaar Card Number", - "matched_content_hash": "0476e6cf99db1c000b7e0a433ff83591ffe0472f3156c9ebac7b11d0862f3429", + "matched_content_hash": "4714ac4f70659987acae4a4760aedecd3924449f855e3be8115a51eb1ad35f93", "plugin_name": "AadhaarCardDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 979, - "finding_type": "PAN Card Number", - "matched_content_hash": "75d7a58ed9996980fee805fb623d81193cdb5e9efddf2fa12b595171ca16530e", - "plugin_name": "PANCardDetector" + "file_path": "tests/scanner_tests.rs", + "line_number": 660, + "finding_type": "Aadhaar Card Number", + "matched_content_hash": "c941e88b8d0be7288dcc792a8ecfae22482b8a83ea4494f1ca0e36293009730b", + "plugin_name": "AadhaarCardDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 980, + "file_path": "tests/scanner_tests.rs", + "line_number": 687, "finding_type": "Voter ID (EPIC)", "matched_content_hash": "e530110a549dd903837a0e2af06b406b01367b4572d07bffee9387334c027f20", "plugin_name": "VoterIDDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 981, - "finding_type": "Social Security Number", - "matched_content_hash": "f9b230216fb066be06e470cb3c0128af42871ef7c232e1359abbb8f28283a79a", - "plugin_name": "SSNDetector" - }, - { - "file_path": "./tests/detector_tests.rs", - "line_number": 982, - "finding_type": "ABHA Health ID", - "matched_content_hash": "f18a39a3c0ab355e4e17257dc1e75985da5a8da0ff0992267750e6c005a32cdc", - "plugin_name": "ABHADetector" - }, - { - "file_path": "./tests/detector_tests.rs", - "line_number": 985, - "finding_type": "Random String", - "matched_content_hash": "131ecedfcb73d35cbab4a5ab397ccccdc2fe8d928911582f0c6dfb94028e1d4a", - "plugin_name": "RandomString" - }, - { - "file_path": "./tests/detector_tests.rs", - "line_number": 985, - "finding_type": "Google API Key", - "matched_content_hash": "aad5ee06394623d9b0df91c7a9f4bdff62b35dad9369aad8ba4e27d72a92720c", - "plugin_name": "GoogleAPIKeyDetector" + "file_path": "tests/scanner_tests.rs", + "line_number": 687, + "finding_type": "Voter ID (EPIC)", + "matched_content_hash": "8d6bf65189e5bdf52955b4a1592eb9c2fb0560709152317a1dabc36971c38f30", + "plugin_name": "VoterIDDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 989, - "finding_type": "JWT Token", - "matched_content_hash": "63fab2d473c9588a8eb97b746b1c9471a007965a7bcc984b50282214f6dfbca3", - "plugin_name": "JWTokenDetector" + "file_path": "tests/scanner_tests.rs", + "line_number": 711, + "finding_type": "PAN Card Number", + "matched_content_hash": "75d7a58ed9996980fee805fb623d81193cdb5e9efddf2fa12b595171ca16530e", + "plugin_name": "PANCardDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 992, - "finding_type": "Database URL", - "matched_content_hash": "92a764286dc65f3b07669e8a6cfaa88538b7a9ddb279e506df47abc31e6fc67f", - "plugin_name": "DatabaseURLDetector" + "file_path": "tests/scanner_tests.rs", + "line_number": 711, + "finding_type": "PAN Card Number", + "matched_content_hash": "4dd22fad4bf96036ceea29ca253be8d72851cc289d7e694c9b208b7370812ee6", + "plugin_name": "PANCardDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 995, - "finding_type": "Database URL", - "matched_content_hash": "aa01165935d3f8891e4beb2392f0c5cdd5963b5fbe041e4ec9a3fb65d01e098c", - "plugin_name": "DatabaseURLDetector" + "file_path": "tests/scanner_tests.rs", + "line_number": 735, + "finding_type": "ABHA Health ID", + "matched_content_hash": "25b618101c3bfdb4438894aa540e108cd150903bd24da57ac24f0d4174c0fe7e", + "plugin_name": "ABHADetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 995, - "finding_type": "MongoDB Connection String", - "matched_content_hash": "86e05b03473347c72e1cbe549b27bea5396b50802162a4ecfc7ac2fcb8fb12f8", - "plugin_name": "MongoDBConnectionStringDetector" + "file_path": "tests/scanner_tests.rs", + "line_number": 735, + "finding_type": "ABHA Health ID", + "matched_content_hash": "397d0bc36d77ccfc6f74c2eaa6615bb75c3fe3bdc3df26e6f53f413cfcdacdb3", + "plugin_name": "ABHADetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 995, - "finding_type": "Email Address", - "matched_content_hash": "6b49e15c059cfbe0fe9f4f9262a1ada9fd0e803098f284fd8b2f7df7a9ea7789", - "plugin_name": "EmailDetector" + "file_path": "tests/scanner_tests.rs", + "line_number": 760, + "finding_type": "Aadhaar Card Number", + "matched_content_hash": "8d7ab03162973f8bc2baf7c8556af862841d23c4d66f7f18f8cf5c5777f8b263", + "plugin_name": "AadhaarCardDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 999, - "finding_type": "SendGrid API Key", - "matched_content_hash": "9211accd29c5d5e26cbc040c59724ed4f59b2ab9a6fd5ef16ec518eb103f91ed", - "plugin_name": "SendGridAPIKeyDetector" + "file_path": "tests/scanner_tests.rs", + "line_number": 760, + "finding_type": "ABHA Health ID", + "matched_content_hash": "89deb2b58721d6303daa4a62f2dee30b9a388afb905fc4d3595ec88ca875fb15", + "plugin_name": "ABHADetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 999, - "finding_type": "Base64 Encoded String", - "matched_content_hash": "83c33a81e18a5ec4b40f7d9314cb8d63d94c0f324938630cd44ca64230bf0e49", - "plugin_name": "Base64Detector" + "file_path": "tests/scanner_tests.rs", + "line_number": 760, + "finding_type": "PAN Card Number", + "matched_content_hash": "18fe123b5e00bbed7228c4ededc8a4e6e0bfd59169af97ec2e62b595eac11dde", + "plugin_name": "PANCardDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 1003, + "file_path": "tests/scanner_tests.rs", + "line_number": 865, "finding_type": "Random String", - "matched_content_hash": "a907b01629778ccd357a125e843211d716ec4d15c8a5d4a29643aa257beaea77", + "matched_content_hash": "cbe1ce18b874bc08437699d863cd422c49e104462e7d5ac6bd390acc0d7c973a", "plugin_name": "RandomString" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 1003, - "finding_type": "DigitalOcean API Token", - "matched_content_hash": "eac5db004534e626e7b61daf10ca90fb6fe258c812cd7845f4f75c03d496c2b2", - "plugin_name": "DigitalOceanTokenDetector" + "file_path": "tests/scanner_tests.rs", + "line_number": 865, + "finding_type": "Google API Key", + "matched_content_hash": "aec6660855470791a5b4f5a6c1ac4b61e61d2b942b1cdec400fb7811743798d0", + "plugin_name": "GoogleAPIKeyDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 1007, - "finding_type": "Random String", - "matched_content_hash": "c99d7da93fde37dd019d0cf73b366d4142c7e5af291ae011f627da6eef9283a2", - "plugin_name": "RandomString" + "file_path": "tests/scanner_tests.rs", + "line_number": 912, + "finding_type": "Password", + "matched_content_hash": "67ef748345ad7f183084a7449ec05906e648c882400b9d940f2fadec23a7b197", + "plugin_name": "PasswordDetector" }, { - "file_path": "./tests/detector_tests.rs", + "file_path": "tests/scanner_tests.rs", "line_number": 1007, - "finding_type": "NPM Token", - "matched_content_hash": "93fa4d52f8628507260c420eda9d4e5b8b53083eaa9c1650697f15ef6c1d4cda", - "plugin_name": "NPMTokenDetector" - }, - { - "file_path": "./tests/detector_tests.rs", - "line_number": 1011, - "finding_type": "Heroku API Key", - "matched_content_hash": "e8cd71caa187d4d908480c35dabd5ac3eaad88e33174fac1229926b78b715a97", - "plugin_name": "HerokuAPIKeyDetector" + "finding_type": "AWS Access Key", + "matched_content_hash": "05c0aace2b76ca255ed3a7a953016d981477226dccc3b0e709d00174c8bc48b5", + "plugin_name": "AWSKeyDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 1011, + "file_path": "tests/scanner_tests.rs", + "line_number": 1650, "finding_type": "Generic Key/Secret", - "matched_content_hash": "ad7c54874c2910b3ff65345d4bfba97c7aae5e95307bfa745ecf2c2c6c406b29", + "matched_content_hash": "97894929682fc00219686473cbcfa3731d73b23e88ffa7c19a511c1bbfa18aa5", "plugin_name": "GenericKeyValueDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 1015, - "finding_type": "Random String", - "matched_content_hash": "f48ffeb7e4c083b563be0cff8e4158476658cfc15dc493c14d127fecf31259ae", - "plugin_name": "RandomString" - }, - { - "file_path": "./tests/detector_tests.rs", - "line_number": 1015, - "finding_type": "Groq API Key", - "matched_content_hash": "659ba6bae01aab6d09327e7f2d2f808140fd6b990db40a35b1a9cb967ad4b6f4", - "plugin_name": "GroqAPIKeyDetector" - }, - { - "file_path": "./tests/detector_tests.rs", - "line_number": 1019, - "finding_type": "Random String", - "matched_content_hash": "15ce329320873469fe3be8c5266a0d158b2b49a3903447e1d5e0cae1cd4b54b3", - "plugin_name": "RandomString" - }, - { - "file_path": "./tests/detector_tests.rs", - "line_number": 1019, - "finding_type": "Hugging Face Token", - "matched_content_hash": "7e620527f0ee998f548f41283f1fd607497f176e8b801154231db33265b5046d", - "plugin_name": "HuggingFaceTokenDetector" - }, - { - "file_path": "./tests/detector_tests.rs", - "line_number": 1023, - "finding_type": "GitLab Personal Access Token", - "matched_content_hash": "1c920d68e02f0cf8f21a1be01c6e91256e4e7e60461406a4bb103af5a4e99539", - "plugin_name": "GitLabPersonalAccessTokenDetector" - }, - { - "file_path": "./tests/detector_tests.rs", - "line_number": 1027, - "finding_type": "HashiCorp Vault Token", - "matched_content_hash": "0e290623d9b5c162f39a3b894bc2a500c542cb879e2b295d321677485eb3315b", - "plugin_name": "HashicorpVaultTokenDetector" + "file_path": "tests/scanner_tests.rs", + "line_number": 1650, + "finding_type": "AWS Secret Access Key", + "matched_content_hash": "58db90a4f2acf80492ed15e73ad77de6c84b9aace839d821931aa0474c898386", + "plugin_name": "AWSSecretKeyDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 1031, - "finding_type": "Google OAuth Token", - "matched_content_hash": "14bcf91874e68f421e946b8414c43fbe04f1d5ee1b97fd58d4d2bb10a08cb82b", - "plugin_name": "GoogleOAuthTokenDetector" + "file_path": "tests/scanner_tests.rs", + "line_number": 1854, + "finding_type": "AWS Access Key", + "matched_content_hash": "357b7fb7890985d4c94a43012d1f7aefe25757f36d8810388357993bb38bd8e7", + "plugin_name": "AWSKeyDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 1035, - "finding_type": "Random String", - "matched_content_hash": "0b71a8751aa19a3057b98d957c12b1d0f713b6fed41fb2c1eb244ff45c0942ae", - "plugin_name": "RandomString" + "file_path": "tests/scanner_tests.rs", + "line_number": 2106, + "finding_type": "AWS Access Key", + "matched_content_hash": "0cbae582394e61dc81d9946ed87ec44f4c83cf1167181f62cd1454eb5e2e5469", + "plugin_name": "AWSKeyDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 1035, - "finding_type": "Shopify Access Token", - "matched_content_hash": "a954f6f8f04f0be943d4b794a5d1881ccab4704c42cc7f1032988e969c75e1c8", - "plugin_name": "ShopifyAccessTokenDetector" + "file_path": "tests/scanner_tests.rs", + "line_number": 2407, + "finding_type": "Password", + "matched_content_hash": "6121378fbc25183476235d474ee367f7dbd0bbe3d96642daaeb483b5e9108cdb", + "plugin_name": "PasswordDetector" }, { - "file_path": "./tests/detector_tests.rs", - "line_number": 1039, + "file_path": "tests/scanner_tests.rs", + "line_number": 2521, "finding_type": "Base64 Encoded String", - "matched_content_hash": "554736805d6e994bf786b21a30653266d29aa65775bbc17eb9f910d2556da91b", + "matched_content_hash": "37f93597692f90e64e009b94ce81237f0f5a6d03ffce8085e91814efe71e4431", "plugin_name": "Base64Detector" - }, - { - "file_path": "./tests/run_cli_error_tests.rs", - "line_number": 9, - "finding_type": "Generic Key/Secret", - "matched_content_hash": "d6d60d3e50a63a67cc37ebfac022834f34a7ec0c74d9b5952b8b8ccd50b5f1ff", - "plugin_name": "GenericKeyValueDetector" - }, - { - "file_path": "./tests/scanner_tests.rs", - "line_number": 187, - "finding_type": "AWS Secret Access Key", - "matched_content_hash": "2c770dc5ac4de63cd2cb89e604080a34ce55dd946586ba7e0d961b31e321403f", - "plugin_name": "AWSSecretKeyDetector" - }, - { - "file_path": "./tests/scanner_tests.rs", - "line_number": 453, - "finding_type": "Generic Key/Secret", - "matched_content_hash": "bbc84628b4a0a5db38b2d8ed22fb8b5f4a880a6b0037ba055f9007c6192d8f05", - "plugin_name": "GenericKeyValueDetector" - }, - { - "file_path": "./tests/scanner_tests.rs", - "line_number": 1650, - "finding_type": "AWS Secret Access Key", - "matched_content_hash": "58db90a4f2acf80492ed15e73ad77de6c84b9aace839d821931aa0474c898386", - "plugin_name": "AWSSecretKeyDetector" } ] } diff --git a/CHANGELOG.md b/CHANGELOG.md index f1896dc..fec3134 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,24 +10,33 @@ All notable changes to this project will be documented in this file. - Baselines are auto-discovered from `.keywatch-baseline.json`; `--no-baseline-discovery` opts out - `update-baseline` workflow regenerates the baseline via a pull request - `scan --fail-on-unscannable` fails a strict scan when a file could not be read; the pre-commit hook passes it so an unscannable staged file cannot pass silently +- CI scans this repository with KeyWatch and fails if the committed baseline has drifted +- `--prune-baseline` rewrites the baseline from current findings, dropping entries for deleted files and rotated credentials; requires `--update-baseline` and a whole-tree scan, and prints what it dropped +- `scan --git-history --rev-range ` restricts a history scan to a revision range; the pre-push hook uses it to scan exactly the pushed commits +- Detectors for GitHub fine-grained PATs (`github_pat_`), GitHub refresh tokens (`ghr_`), AWS temporary keys (`ASIA`/`ABIA`/`ACCA`), AWS secret access keys (context-gated), modern Slack bot tokens, Slack app tokens (`xapp-`), Slack webhook URLs, and modern OpenAI project keys (`sk-proj-`/`sk-svcacct-`/`sk-admin-`) +- Non-verbose scans print the location, type and redacted match of every finding instead of only a count ### Changed - Pre-commit hooks scan the staged diff instead of whole files +- Pre-push hooks scan the pushed revision ranges from the hook's stdin instead of the worktree, so uncommitted files no longer block a push and removed-but-pushed secrets are caught +- `scan --git-history` walks every ref (`git log --all`), so secrets on side branches are found; pass `--rev-range` to narrow the walk - Config discovery searches parent directories up to the repository root - Hook messages abbreviate the home directory as `~` - Findings for the same file, line and matched text collapse to the highest severity across all scan modes, so overlapping detectors report a secret once - -### Added - -- CI scans this repository with KeyWatch and fails if the committed baseline has drifted -- `--prune-baseline` rewrites the baseline from current findings, dropping entries for deleted files and rotated credentials; requires `--update-baseline` and a whole-tree scan, and prints what it dropped - -### Changed - - Reports redact matched text by default; `--show-secrets` opts into raw values, and matches shorter than 8 characters are always described by length only - Reports summarise exclusions as a count plus a sample instead of listing every path, and report git-rendered binary files as `unscannable` rather than `excluded` -- Lockfiles (`Cargo.lock`, `package-lock.json`, `yarn.lock`, `go.sum`, and other generated manifests) are excluded from scans by default +- Lockfiles (`Cargo.lock`, `package-lock.json`, `pnpm-lock.yaml`, `yarn.lock`, `bun.lock`, `npm-shrinkwrap.json`, `go.sum`, and other generated manifests) are excluded from scans by default +- A nonexistent scan path, a symlink operand, or an operand that is not a regular file or directory is a hard error (exit 2) instead of a silent clean pass +- A directory that cannot be listed is reported as unscannable, so `--fail-on-unscannable` catches it +- Baseline fingerprints anchor paths to the repository root, so a baseline created in a subdirectory suppresses the same finding in staged and history scans +- Baselines written from a subdirectory by earlier releases record cwd-relative paths and stop suppressing until `key-watch scan . --update-baseline` refreshes them to repository-root paths +- Unknown keys in `.keywatch.toml` and detector files are rejected instead of silently ignored +- KeyWatch warns on stderr when an external detector file replaces the embedded set, when config overrides disable detectors, and when `KEYWATCH_CONFIG_PATH` is set but ignored +- Stripe publishable keys (`pk_`) report as LOW under their own detector; `rk_` restricted keys are detected as secrets +- Identity-number detectors (SSN, Aadhaar, PAN, Voter ID, ABHA) require the line to name the document, matching the context gate `HighEntropyDetector` already used; bare number dumps without a label on the same line are no longer flagged +- Upgrade note: baseline entries record the detector name and finding type, so entries created by the renamed detectors (`pk_` keys moved to `StripePublishableKeyDetector`; 48+ character `sk-` keys moved from the Kimi label to `OpenAIAPIKeyDetector`) re-fire once after upgrading; run `key-watch scan . --update-baseline` to refresh them +- SARIF reports no longer claim `precision: very-high` for every rule and omit `semanticVersion` when unknown ### Fixed @@ -58,9 +67,18 @@ All notable changes to this project will be documented in this file. - Custom rules in `.keywatch.toml` support `allowlist`, `keywords`, `entropy` and `validate`, matching built-in detector definitions - Pre-push repository filters fail closed on Windows drive-path remotes instead of misparsing the drive letter as a host - Chunked streaming scans no longer duplicate multiline matches that land inside the window overlap +- `GenericKeyValueDetector` reaches its `auth` and `_key` pattern branches; the keyword prefilter previously never let `auth = ...` or `encryption_key = ...` lines reach the regex +- `NewRelicAPIKeyDetector` matches real uppercase NRAK keys; the lowercase-only class could never fire +- `SlackTokenDetector` keyword and pattern prefixes agree; `xoxa-` tokens were unreachable and `xoxr-` was inert +- 48+ character `sk-` tokens report as OpenAI keys instead of being mislabeled Kimi/Moonshot +- The same file passed under two spellings (`dup.txt ./dup.txt`) reports each finding once +- Errors from failed `git diff`/`git log` include one summarized stderr line instead of letting git dump pages of usage text +- `--fail-on-unscannable` names the unscannable files in its summary instead of printing "No secrets found." next to exit code 1 +- The AWS documentation example secret in `.env.example` files is no longer flagged by `GenericKeyValueDetector` +- The composite Action publishes its effective exit code on report failures instead of a stale `0`, and `findings-count` stays numeric (`-1` when unknown) - Files with invalid UTF-8 are decoded lossily and scanned instead of silently skipped; NUL-containing files are reported as `unscannable` - `Finding`'s `plugin_name` field is now `detector_name` in the code; the JSON report and baseline schema still emit/accept `plugin_name` -- `CustomRule.description` was parsed but never surfaced and has been dropped (configs carrying it keep parsing) +- `CustomRule.description` is accepted and ignored so configuration files written for earlier releases keep parsing (the text was never surfaced) - False-positive reductions in the built-in detectors: AWS's documentation example key, placeholder values (`changeme`, `your-api-key-here`, `replace-me-please`), RFC 2606 example-domain emails and noreply conventions, fictional 555 phone numbers, npm/shield checksum prefixes, and non-Verhoeff 12-digit runs no longer report as Aadhaar - `--baseline` naming a missing file is an error instead of silently scanning with an empty baseline - Baseline files with an unknown format version are rejected instead of silently accepted diff --git a/Dockerfile b/Dockerfile index fa063d2..b0b6674 100644 --- a/Dockerfile +++ b/Dockerfile @@ -37,5 +37,7 @@ USER keywatch ENV KEYWATCH_CONFIG_PATH=/etc/keywatch/detectors.toml +WORKDIR /workspace + ENTRYPOINT ["key-watch"] CMD ["--help"] diff --git a/README.md b/README.md index 56ba116..8f302bd 100644 --- a/README.md +++ b/README.md @@ -1,296 +1,255 @@ # KeyWatch -A fast secret scanner for files and directories. +KeyWatch scans files, directories, and git repositories for secrets such as API keys, tokens, passwords, and private keys. +It runs as a command-line tool, as a git hook, as a GitHub Action, and as a container image. ## Install -### Recommended: cargo install +Install with cargo: ```sh cargo install key-watch key-watch --version - -# Enable aliases for your current shell session -eval "$(key-watch init bash)" -``` - -To make aliases persistent, add the init line to your shell config file: - -```sh -# bash -echo 'eval "$(key-watch init bash)"' >> ~/.bashrc - -# zsh -echo 'eval "$(key-watch init zsh)"' >> ~/.zshrc ``` -### Manual install from GitHub Releases - -1. Download the correct binary for your OS/architecture from GitHub Releases. -2. Move it to a directory on your `PATH`, for example `~/.local/bin`. -3. Make it executable. -4. Verify it runs. -5. Enable aliases with `init`. +Or download a binary from GitHub Releases, place it on your `PATH`, and make it executable: ```sh mkdir -p ~/.local/bin mv ~/Downloads/key-watch ~/.local/bin/key-watch chmod +x ~/.local/bin/key-watch ~/.local/bin/key-watch --version - -# Enable aliases for current shell session -eval "$(~/.local/bin/key-watch init bash)" ``` -Requires Rust 1.85+ (edition 2024) when building from source. - -The canonical command is `key-watch`. -`keywatch` and `kw` are optional shell aliases exposed via `key-watch init ...`. - -## GitHub Action - -Use the root Action from a public workflow. The major tag follows compatible `2.x` releases; pin an exact release tag or commit SHA when immutable dependencies are required. +Building from source requires Rust 1.85 or later. -```yaml -name: Secret scan - -on: - pull_request: - push: +The command is `key-watch`. +To use the shorter aliases `keywatch` and `kw`, add this line to your shell configuration file: -permissions: - contents: read - -jobs: - keywatch: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v7 - - id: keywatch - uses: pixincreate/KeyWatch@v2 - with: - paths: "." - exit-mode: strict +```sh +eval "$(key-watch init bash)" # or: zsh, fish, posix ``` -The Action installs the synchronized KeyWatch release, verifies SHA-256 checksums for the binary and `detectors.toml`, disables repository detector discovery, and writes a JSON report. It supports Linux x64 and macOS x64/arm64 runners; Windows runners are not supported. - -| Input | Default | Purpose | -| ----------- | ---------------------- | ------------------------------------------------------------------------ | -| `version` | Action release version | Exact KeyWatch release to install | -| `paths` | `.` | Space-separated paths or globs to scan | -| `args` | empty | Additional scanner arguments that do not override Action-managed options | -| `exit-mode` | `strict` | `strict`, `critical`, or `always` | -| `output` | temporary report | JSON report path | -| `config` | empty | Explicit trusted `.keywatch.toml` path | -| `verbose` | `false` | Deprecated; enabling it is rejected to prevent secret disclosure in logs | +## Scan from the command line -The `findings-count` and `exit-code` outputs are available as `${{ steps.keywatch.outputs['findings-count'] }}` and `${{ steps.keywatch.outputs['exit-code'] }}`. - -## Container Image - -The GitHub Container Registry image is a separate distribution channel for Linux x64 environments: +Scan a file, a directory, or standard input: ```sh -docker pull ghcr.io/pixincreate/keywatch:2 -docker run --rm \ - --volume "$PWD:/workspace:ro" \ - --workdir /workspace \ - ghcr.io/pixincreate/keywatch:2 scan . +key-watch scan secrets.txt # one file +key-watch scan . # a directory tree +cat secrets.txt | key-watch scan --stdin ``` -Images are published as `x.y.z`, `x.y`, `x`, and `latest`, with build provenance attached. Exact semver tags are the reproducible choice. After the first publication, a repository owner must make the GHCR package public in the package settings to allow anonymous pulls; no separate GHCR account is required. The image runs as a non-root user and uses the image-owned detector configuration at `/etc/keywatch/detectors.toml`. - -## Uninstall - -### If installed with `cargo install` +Scan a git repository: ```sh -cargo uninstall key-watch +key-watch scan --staged # only the lines staged for commit +key-watch scan --git-history # every commit on every branch +key-watch scan --git-history --rev-range abc123..def456 # a commit range ``` -If you added aliases to your shell config, remove the init line you added earlier, for example: +Control the output: ```sh -# bash -sed -i.bak '/key-watch init bash/d' ~/.bashrc - -# zsh -sed -i.bak '/key-watch init zsh/d' ~/.zshrc +key-watch scan . --verbose # print the full JSON report +key-watch scan . --output report.json # write the report to a file +key-watch scan . --format sarif # write SARIF instead of JSON ``` -### If installed manually from GitHub Releases +By default, KeyWatch prints one line per finding with the file, line number, and a redacted preview. +Reports never contain the full matched text unless you pass `--show-secrets`. -1. Remove the `key-watch` binary from your `PATH` directory. -2. Remove any shell init line you added for aliases. -3. Restart your shell or reload your shell config. +### Scan options -```sh -rm -f ~/.local/bin/key-watch +| Option | Purpose | +| ------ | ------- | +| `--exclude ` | Skip paths that match these comma-separated glob patterns | +| `--exit-mode ` | `strict` fails on any finding (default), `critical` fails only on HIGH or CRITICAL findings, `always` never fails | +| `--fail-on-unscannable` | Fail when a file or directory could not be read | +| `--baseline ` | Use a specific baseline file | +| `--no-baseline-discovery` | Do not look for a baseline file automatically | +| `--update-baseline` | Record the current findings in the baseline instead of reporting them | +| `--prune-baseline` | With `--update-baseline`, also remove baseline entries that no longer match anything | +| `--config ` | Use a specific `.keywatch.toml` configuration file | +| `--no-config-discovery` | Ignore configuration and detector files found in the scanned repository | +| `--show-secrets` | Include the full matched text in reports | -# If you added aliases for the current shell config, remove that line manually -# then reload your shell config, for example: -source ~/.bashrc -``` +Notes: -## Usage +- Lock files such as `Cargo.lock`, `package-lock.json`, `pnpm-lock.yaml`, and `yarn.lock` are always skipped. + They contain checksums, not credentials. +- `--staged` reads the content you staged with `git add`, not the files on disk. + A secret that is staged but already removed from the working copy is still found. +- `--git-history` scans every branch and tag. + Use `--rev-range` to scan only a range of commits. +- A scan path that does not exist, is a symbolic link, or cannot be read is an error. + The scan never reports a clean result for input it could not read. -```sh -# Scan a file -key-watch scan secrets.txt +### Exit codes -# Scan a directory -key-watch scan . +| Code | Meaning | +| ---- | ------- | +| 0 | No secrets found, or `--exit-mode always` | +| 1 | Secrets found, or an unreadable file with `--fail-on-unscannable` | +| 2 | Invalid input, configuration error, or runtime error | -# Scan from stdin -cat secrets.txt | key-watch scan --stdin +## Git hooks -# Scan git history for committed secrets -key-watch scan --git-history +KeyWatch installs two git hooks: -# Scan only the lines staged for commit -key-watch scan --staged +- The **pre-commit** hook scans the lines you staged. + A secret in staged content blocks the commit. + Findings in lines you did not change never block a commit. +- The **pre-push** hook scans the commits you are about to push. + A secret in those commits blocks the push. + Uncommitted files never block a push. -# Verbose output (JSON) -key-watch scan secrets.txt --verbose +Install and remove hooks inside a repository: -# Install git hook +```sh key-watch hook install pre-commit key-watch hook install pre-push - -# Remove git hook key-watch hook uninstall pre-commit key-watch hook uninstall pre-push +``` -# Install git hook globally via core.hooksPath -key-watch hook install pre-commit --global -key-watch hook install pre-push --global +Add `--global` to install or remove a hook for every repository on the machine: -# Remove global hook +```sh +key-watch hook install pre-commit --global key-watch hook uninstall pre-commit --global -key-watch hook uninstall pre-push --global +``` -# Print shell aliases -eval "$(key-watch init bash)" +### Hook options -# Verify binary integrity -key-watch verify-integrity -``` +| Option | Applies to | Purpose | +| ------ | ---------- | ------- | +| `--exclude ` | pre-commit | Skip staged paths that match these patterns | +| `--allowed-repos ` | pre-push | Allow pushes only to these repositories | +| `--blocked-repos ` | pre-push | Block pushes to these repositories | + +### How hooks behave -## Options - -- `scan ...` - Scan one or more files or directories -- `scan --config ` - Load configuration from an explicit `.keywatch.toml` path -- `scan --no-config-discovery` - Ignore discovered repository config unless `--config` is explicit -- `scan --format ` - Choose the report format written to stdout or the output file -- `scan --stdin` - Read content from stdin instead of files -- `scan --git-history` - Scan git history (`git log -p`) for committed secrets; findings carry real file paths, and `--exclude` and baselines apply -- `scan --staged [path...]` - Scan only the added lines of the staged diff (run from inside the repository; paths narrow the diff as git pathspecs); findings keep real file paths and line numbers, so `--baseline` and `--exclude` compose. Files git renders as binary (e.g. `-diff` in `.gitattributes`) are read from the index in staged scans and reported under `unscannable` when they cannot be read at all. Note: a multi-line secret added across separate commits can span hunks the diff scan never sees together — the pre-push whole-tree scan remains the backstop for that case -- `scan --fail-on-unscannable` - Treat files that could not be read (git-rendered binaries, permission errors) as a failure in `strict` mode; the installed pre-commit hook passes this flag so an unscannable staged file fails the commit instead of passing silently. `--update-baseline` writes a baseline instead of reporting, so the flag does not apply to that mode, and directories that cannot be listed are not counted -- `scan --output ` - Save report to file -- `scan --verbose` - Print full JSON output (matched text is redacted; see `--show-secrets`) -- `scan --show-secrets` - Include raw matched text in reports. Off by default: reports are routinely written to files or uploaded as CI artifacts, and `--output` files are created with owner-only permissions -- `scan --exclude ` - Comma-separated glob patterns to exclude; lockfiles (`Cargo.lock`, `package-lock.json`, `yarn.lock`, `go.sum`, and other generated manifests) are always excluded by basename -- `scan --exit-mode ` - Exit behavior: `always` (always pass), `critical` (fail on HIGH/CRITICAL only), `strict` (fail on any finding, default) -- `scan --baseline ` - Suppress known findings from a previous scan. Without this flag, a `.keywatch-baseline.json` is discovered automatically by walking up from the scan target (bounded at the repository root or home directory), so hook scans pick up a committed repo baseline with no configuration -- `scan --no-baseline-discovery` - Ignore a discovered baseline (an explicit `--baseline` still loads) -- `scan --prune-baseline` - With `--update-baseline`, rebuild the baseline from current findings instead of merging, dropping stale entries; requires a whole-tree scan (`--staged`, `--stdin` and `--git-history` are refused, narrowed paths draw a warning), and the dropped count is always printed -- `scan --update-baseline` - Update the baseline with current findings; creates `.keywatch-baseline.json` when no baseline exists. The baseline stores fingerprints (path + finding type + SHA-256 of the match + detector), never secrets, and is meant to be committed. The `update-baseline` workflow can regenerate it via a reviewable pull request -- `hook install [--global]` - Install a git hook -- `hook uninstall [--global]` - Remove a git hook -- `hook install pre-push --allowed-repos ` - Whitelist repos for pre-push hooks -- `hook install pre-push --blocked-repos ` - Block repos for pre-push hooks -- `hook install pre-commit --exclude ` - Exclude patterns for pre-commit scans -- `init ` - Print shell aliases for `keywatch` and `kw` -- `verify-integrity` - Check the running binary's file permissions (fails when it is world-writable on unix); this is a permission check, not a cryptographic checksum - -## Aliases - -- `key-watch` is the only shipped binary. -- `keywatch` and `kw` are optional aliases. -- `key-watch init bash|zsh|fish|posix` prints shell aliases you can eval in your shell. -- `watch` is intentionally not used, to avoid colliding with the standard Unix `watch` command. - -## Baseline - -Use baselines to suppress known findings on subsequent scans: +- Hooks always use the built-in detector rules. + A repository cannot weaken its own scan by committing a modified detector file. +- Hooks respect a committed baseline file and `keywatch:ignore` markers. +- KeyWatch refuses to overwrite or remove a hook file it did not install. +- The first push of a branch scans the full history of that branch, because every commit on it is new to the remote. + If that push reports old findings, record them in the baseline first. +- A global install sets `core.hooksPath` in your git configuration. + Git then ignores each repository's own `.git/hooks` scripts. + To keep a repository's own hooks instead, run `git config core.hooksPath .git/hooks` inside that repository. + The KeyWatch hook then no longer runs there. + +## Baselines + +A baseline records findings you have reviewed and accepted, so later scans report only new findings. +The baseline file stores fingerprints of the findings, never the secrets themselves, and is safe to commit. ```sh -# First scan: create a baseline -key-watch scan . --baseline .keywatch.baseline --update-baseline +# Record the current findings +key-watch scan . --update-baseline -# Future scans: only report NEW findings -key-watch scan . --baseline .keywatch.baseline +# Later scans report only new findings +key-watch scan . ``` -## Inline Suppression +KeyWatch finds a committed `.keywatch-baseline.json` automatically. +You do not need to pass `--baseline` on every scan. -Add `keywatch:ignore` to suppress a finding on a specific line: +## Ignore a single line + +Add `keywatch:ignore` to a line to suppress findings on that line: ```sh password = 'known-test-password' # keywatch:ignore ``` -## Exit Codes +## Configuration -| Code | Meaning | -| ---- | ----------------------------------------------- | -| 0 | No secrets found (or `scan --exit-mode always`) | -| 1 | Secret found (strict/critical mode), or an unscannable file with `scan --fail-on-unscannable` | -| 2 | Runtime/configuration error | +Place a `.keywatch.toml` file in the repository root to add rules, disable detectors, or exclude paths: -## Default Behavior +```toml +exclude = ["target/**"] -- **Repos**: All allowed (no restrictions) -- **Exit mode**: strict (fail on any finding) +[[rules]] +name = "InternalToken" +pattern = "INT_[A-Za-z0-9]{32}" +finding_type = "Internal Token" +severity = "HIGH" -## Git Hooks +[overrides.EmailDetector] +enabled = false +``` -- `hook install pre-commit|pre-push` installs a repo-local hook into `.git/hooks/` -- `hook uninstall pre-commit|pre-push` removes a KeyWatch hook from the same target -- `hook install ... --global` installs into Git's global hooks directory -- `hook uninstall ... --global` removes the hook from Git's global hooks directory -- Pre-commit hooks run `key-watch scan --staged`, so only the lines a commit adds are scanned and findings on unchanged lines never block a commit -- Pre-commit `--exclude` patterns are forwarded to `scan --staged --exclude` and matched against staged file paths -- Local hook paths are resolved via `git rev-parse --git-path hooks`, so installs work in worktrees and submodules too -- If `core.hooksPath` is already configured, KeyWatch installs into that directory -- Otherwise KeyWatch creates a managed hooks directory and configures `git config --global core.hooksPath` -- KeyWatch refuses to overwrite a non-KeyWatch global hook file -- KeyWatch also refuses to remove a non-KeyWatch global hook file -- A global `core.hooksPath` makes Git ignore every repository's own `.git/hooks/` scripts (husky, lefthook, plain hook files). To restore a repository's local hooks, run `git config core.hooksPath .git/hooks` inside it — the repo-local setting overrides the global one, and the KeyWatch hook then no longer runs in that repository +Unknown keys in the configuration file are rejected, so a misspelled key cannot silently weaken a scan. -## Architecture +## GitHub Action -KeyWatch is a single Rust CLI organized as a modular monolith. `main.rs` owns startup and maps validation, configuration, or runtime failures to exit code `2`. `run_cli()` validates and routes commands, while the scan coordinator currently terminates successful scan execution with code `0` or `1`. Focused modules own detector loading, repository policy, scanning, baselines, reports, hooks, and filesystem or process adapters. +```yaml +name: Secret scan -### CLI Modules and Adapters +on: + pull_request: + push: -![KeyWatch CLI module and adapter architecture](docs/architecture/cli-modules.svg) +permissions: + contents: read -The green boxes are internal modules, blue boxes mark entry or output boundaries, and yellow boxes are external runtime or distribution adapters. Rust hook management renders and installs scripts; the shell templates are separate runtime adapters that invoke `key-watch scan`. +jobs: + keywatch: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + - id: keywatch + uses: pixincreate/KeyWatch@v2 + with: + paths: "." + exit-mode: strict +``` -### Scan Pipeline +The Action installs a released KeyWatch binary, verifies its checksum, and writes a JSON report. +It supports Linux x64 and macOS runners. +Pin an exact release tag or commit SHA when you need a fixed version. -![KeyWatch scan pipeline](docs/architecture/scan-pipeline.svg) +| Input | Default | Purpose | +| ----- | ------- | ------- | +| `version` | Action release version | Exact KeyWatch release to install | +| `paths` | `.` | Space-separated paths or globs to scan | +| `args` | empty | Extra scanner arguments; Action-managed options cannot be overridden | +| `exit-mode` | `strict` | `strict`, `critical`, or `always` | +| `output` | temporary file | Path for the JSON report | +| `config` | empty | Path to a trusted `.keywatch.toml` | +| `verbose` | `false` | Deprecated; enabling it is rejected to keep secrets out of logs | -Path scans collect and process files in parallel, while stdin and git history use overlapping stream chunks. Baseline updates short-circuit normal report generation. Scan results exit with code `0` or `1`; validation, configuration, and runtime failures are mapped to code `2` at the process boundary. +The Action exposes `findings-count` and `exit-code` as step outputs. -### Detector and Configuration Trust Boundaries +## Container image -![KeyWatch detector and configuration trust boundaries](docs/architecture/detector-config-trust.svg) +```sh +docker pull ghcr.io/pixincreate/keywatch:2 +docker run --rm --volume "$PWD:/workspace:ro" ghcr.io/pixincreate/keywatch:2 scan . +``` -Detector definitions and repository policy are separate configuration systems. External detector sources retain precedence, with compiled-in rules as the final fallback. Trusted scans skip repository-owned discovery but still honor explicit configuration and non-repository detector sources. +Images are tagged `x.y.z`, `x.y`, `x`, and `latest`. +Use an exact version tag for reproducible results. +The image runs as a non-root user. -### Core Data Types +## Uninstall + +If you installed with cargo: -- **Detector** — a named rule: regex, finding type, severity, optional keywords for pre-filtering, an entropy threshold, and an allowlist. -- **Finding** — one detected secret: file path, line number, finding type, severity, matched content, and the detector that produced it. -- **Severity** — `Critical`, `High`, `Medium`, `Low`. -- **KeywatchConfig** — parsed `.keywatch.toml`: custom rules, per-detector overrides, and exclude patterns. -- **Baseline** — versioned collection of fingerprint entries; filters out already-known findings. -- **ScanMetadata** — files scanned, total lines, and excluded files, reported alongside findings. +```sh +cargo uninstall key-watch +``` -The canonical diagram sources are in `docs/architecture/*.d2`. Run `scripts/render-diagrams.sh render` with D2 v0.7.1 after editing them, or `scripts/render-diagrams.sh check` to detect stale SVGs. +If you installed a binary manually, delete it from your `PATH` directory: + +```sh +rm -f ~/.local/bin/key-watch +``` + +In both cases, remove the `key-watch init` line from your shell configuration file if you added one. ## Development @@ -301,6 +260,10 @@ cargo fmt cargo clippy ``` -# LICENSE - GPLv3 +Architecture diagrams live in `docs/architecture/`. +Edit the `.d2` sources and run `scripts/render-diagrams.sh render` to update the rendered images. + +## License -[LICENSE](LICENSE) +KeyWatch is licensed under the GPL-3.0-only license. +See [LICENSE](LICENSE). diff --git a/action.yml b/action.yml index 26bb5d0..4955ef5 100644 --- a/action.yml +++ b/action.yml @@ -293,8 +293,11 @@ runs: action_status=2 fi + if [ "$findings_count" = "unknown" ]; then + findings_count=-1 + fi { - echo "exit_code=$scan_status" + echo "exit_code=$action_status" echo "findings_count=$findings_count" } >> "$GITHUB_OUTPUT" diff --git a/justfile b/justfile index fc1dcfa..4ff2030 100644 --- a/justfile +++ b/justfile @@ -40,13 +40,9 @@ run-release: cargo run --release # Full check pipeline -check: fmt clippy test +check: fmt clippy-strict test @echo "✓ All checks passed" -# Run benchmarks (requires criterion) -bench: - cargo bench - # Generate docs doc: cargo doc --no-deps --open diff --git a/scripts/action_validation/keywatch_action_scenarios.py b/scripts/action_validation/keywatch_action_scenarios.py index ae56705..c02fe4c 100644 --- a/scripts/action_validation/keywatch_action_scenarios.py +++ b/scripts/action_validation/keywatch_action_scenarios.py @@ -183,7 +183,7 @@ def run_scan_scenarios(scan_block: str) -> None: 0, "missing", 2, - ("exit_code=0", "findings_count=unknown"), + ("exit_code=2", "findings_count=-1"), expected_stderr=("JSON report is missing",), expected_summary=("| Report | missing |",), ), @@ -194,7 +194,7 @@ def run_scan_scenarios(scan_block: str) -> None: 0, "missing", 2, - ("exit_code=0", "findings_count=unknown"), + ("exit_code=2", "findings_count=-1"), expected_stderr=("JSON report is missing",), expected_summary=("| Report | missing |",), preseed_report=True, diff --git a/scripts/action_validation/validate.py b/scripts/action_validation/validate.py index efd91a5..5465287 100644 --- a/scripts/action_validation/validate.py +++ b/scripts/action_validation/validate.py @@ -149,7 +149,7 @@ def main() -> int: require("keywatch_args+=(--output \"$report_path\")" in shell, "scan must always request a JSON report") require("rm -f -- \"$report_path\"" in shell, "stale reports must be removed before scanning") require("scan_status=$?" in shell, "scanner exit status must be captured") - require("echo \"exit_code=$scan_status\"" in shell, "scanner status must be written to outputs") + require("echo \"exit_code=$action_status\"" in shell, "the effective action status must be written to outputs") require("findings_count=\"unknown\"" in shell, "missing/malformed reports must not default to zero findings") require("jq -e '.findings | type == \"array\"'" in shell, "findings count must validate JSON report shape") require("action_status=$scan_status" in shell, "action status must preserve scanner status by default") diff --git a/scripts/release.sh b/scripts/release.sh index fcc7e0c..edcabd4 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -69,7 +69,7 @@ validate_changelog_for_pr() { exit 1 fi - if grep -q "\[$VERSION\]" CHANGELOG.md; then + if grep -Fq "## [$VERSION]" CHANGELOG.md; then echo "Error: Version $VERSION already exists in CHANGELOG.md" echo "This release appears to already be documented" exit 1 @@ -82,7 +82,7 @@ validate_changelog_for_tag() { exit 1 fi - if ! grep -q "\[$VERSION\]" CHANGELOG.md; then + if ! grep -Fq "## [$VERSION]" CHANGELOG.md; then echo "Error: Version $VERSION not found in CHANGELOG.md" echo "Please merge the release PR before tagging" exit 1 @@ -192,11 +192,7 @@ create_pr() { } create_tag() { - if [[ "$PUBLISH_CRATES" == "true" ]]; then - ensure_clean_master - else - ensure_clean_master - fi + ensure_clean_master validate_changelog_for_tag echo "This will create and push tag v$VERSION, triggering the release workflow." @@ -245,4 +241,4 @@ if [[ "$FUNCTION" != "create_pr" && "$FUNCTION" != "create_tag" && "$FUNCTION" ! exit 1 fi -eval "$FUNCTION" +"$FUNCTION"