Compare commits
188 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d1cbc54fc6 | |||
| 5a86c18302 | |||
| 622700b6ec | |||
| 15ed428e28 | |||
| 6f801f64c7 | |||
| 3485a6dab1 | |||
| 34f5db64ae | |||
| 91bd843ba7 | |||
| 584ab043a2 | |||
| 7578a3a56e | |||
| 800ac30ea0 | |||
| abdff53d5d | |||
| a002ba9a75 | |||
| cec1543894 | |||
| e217e2fbfd | |||
| 4116a24b1c | |||
| a6902ae9cb | |||
| 6dd24d17d4 | |||
| 5b2b434a8a | |||
| 1c1f034468 | |||
| 661e62f006 | |||
| 92244019a9 | |||
| dfc5a9f5db | |||
| f5ecbc857b | |||
| 42975c6d1e | |||
| 0507f0eb87 | |||
| 531e3ef6c3 | |||
| 97ce27153a | |||
| 1c89e79c2d | |||
| 461f1a631e | |||
| 2fbf86a6ab | |||
| 458c79165a | |||
| 1db22599af | |||
| 562f3aaa2a | |||
| 2c1d8fbba4 | |||
| f1cb933a5a | |||
| 256ae20079 | |||
| 5fce8f9f18 | |||
| 304abb9ca9 | |||
| a8c27b9510 | |||
| c451f9daf8 | |||
| f107e1b497 | |||
| b3d917f9c7 | |||
| 20d5683199 | |||
| 58222610ff | |||
| 3932486ea9 | |||
| 8f10938bf7 | |||
| 90737fe377 | |||
| c8646bdbbc | |||
| ab86c120a4 | |||
| 9b941efa1a | |||
| 12127b0598 | |||
| 9ca53d7b08 | |||
| 605238382f | |||
| 9356b3572b | |||
| 762641d970 | |||
| 2cf6f831d4 | |||
| dfc38a135a | |||
| 0052f60090 | |||
| 66eb87f414 | |||
| fc740f5f55 | |||
| c4f08e3f17 | |||
| 4d46c9a9dc | |||
| c78d10149b | |||
| cb454bfc05 | |||
| fb9ae75661 | |||
| c06dd8a928 | |||
| ac19de75bf | |||
| b8467ee17e | |||
| 03a534d59f | |||
| 3861eaad33 | |||
| 05eed21b65 | |||
| 31d5655308 | |||
| 87c9e0db07 | |||
| ffbd9c1ead | |||
| 62d44f59f5 | |||
| 1f24889fdd | |||
| 54a36e333a | |||
| bf36567243 | |||
| 992b8d242d | |||
| 73029c500c | |||
| 3e4496156c | |||
| d382d5cb1c | |||
| c617bd7a4e | |||
| 6193509098 | |||
| 3c1bb45bfb | |||
| 0fe9bf0868 | |||
| f0b6b5d0d9 | |||
| ef9488c77d | |||
| e105126227 | |||
| a7abd6231d | |||
| 17e8d7030e | |||
| af24d36ce8 | |||
| 597b618fd9 | |||
| 8076067b30 | |||
| 585bd82d47 | |||
| 2b1c42ceb1 | |||
| 2f61e4f5aa | |||
| cbf299aa77 | |||
| 3fdef756f2 | |||
| 638ff804f1 | |||
| d5cbd7b999 | |||
| c8077145d5 | |||
| 5c99a1e754 | |||
| e6846ede54 | |||
| 4500ac3b10 | |||
| 4777b77ec6 | |||
| c72840de67 | |||
| aa47e5e248 | |||
| 0cf9139df6 | |||
| 86370333ec | |||
| 64c163cd90 | |||
| 3870be256c | |||
| 2315192fda | |||
| 6209a80ce1 | |||
| 4efe5313f4 | |||
| 7373954ddf | |||
| d2d03426ed | |||
| dd39848709 | |||
| c5b4d6f28b | |||
| ae2d510ced | |||
| 05f6bd369f | |||
| d151c1363e | |||
| ee5b028c67 | |||
| 38562df0f6 | |||
| 4f0e66f064 | |||
| 0b4e3a66b1 | |||
| a293033386 | |||
| d20f43b5c6 | |||
| 9ef9e9870d | |||
| f1582aafa9 | |||
| 9158dcaa80 | |||
| 012fdfe3a2 | |||
| ea71756e20 | |||
| ea40c0f306 | |||
| bcecbcd3d4 | |||
| 926f490c9f | |||
| bd17aa91e3 | |||
| 161e499142 | |||
| c6826c4574 | |||
| f2139a7615 | |||
| 26c455d302 | |||
| 57983aed4e | |||
| 4f13090c01 | |||
| ae14e4506f | |||
| 0c66d30c1f | |||
| 67784f6928 | |||
| c5c8d10d28 | |||
| d317ddb51a | |||
| 29be679370 | |||
| 0ce72ccda3 | |||
| 58e8c1e4ac | |||
| 114f4b6989 | |||
| e47cc2451f | |||
| 1f0fd91205 | |||
| 0d73dbe638 | |||
| 7dd2b74f1f | |||
| b37080e6a5 | |||
| 3f30216356 | |||
| af6e3f8fdf | |||
| 2d35edfb23 | |||
| 8dedd08d89 | |||
| 8be89a593b | |||
| 80a68b84c2 | |||
| 58b78b6a5a | |||
| a53758c4c4 | |||
| 1d3206ed36 | |||
| 26afa76e7c | |||
| 8df9db6ecc | |||
| e85411b59f | |||
| 6e58eb4bbb | |||
| b29b78c10d | |||
| d4f4b1c73e | |||
| 539be34752 | |||
| 00ebb2ed64 | |||
| 4ef546a06b | |||
| ac1dd23d37 | |||
| 2088f030f9 | |||
| 2060ae1c47 | |||
| 86f80fc5a8 | |||
| c62eb18e6d | |||
| 8acd9fdd3b | |||
| 1621403e11 | |||
| 319ae64a02 | |||
| bc27fef7bc | |||
| 45b02f46d9 | |||
| 0aa8e1cd98 | |||
| 477e2a1332 |
@@ -0,0 +1,19 @@
|
||||
# Testing
|
||||
|
||||
Most testing is handled automatically by our GitHub Actions workflows.
|
||||
|
||||
## Local GitHub Action Testing
|
||||
|
||||
In some cases you may wish to submit changes to the Trufflehog GitHub Action. Unfortunately GitHub does not provide a 1st-party testing environment for testing actions outside of GitHub Actions.
|
||||
|
||||
Fortunately [nektos/act](https://github.com/nektos/act) enables local testing of GitHub Actions.
|
||||
|
||||
### Instructions
|
||||
|
||||
1. Please follow [the installation instructions](http://https://github.com/nektos/act#installation) for your OS.
|
||||
2. The first run of `act` will ask you to specify an image. `Medium` should suffice.
|
||||
3. You'll need to configure a personal-access-token(PAT) with: `repo:status`, `repo_deployment`, and `public_repo` permissions.
|
||||
4. Set an environment variable named `GITHUB_TOKEN` with the PAT from the previous step as the value: `$ export GITHUB_TOKEN=<your_PAT>`
|
||||
5. Run the following command from the repository root: `act pull_request -j test -W .github/workflows/secrets.yml -s GITHUB_TOKEN --defaultbranch main`
|
||||
6. If the job was successful, you should expect to see output from the scanner showing several detected secrets.
|
||||
7. If you want to omit the context of a pull request event and just test that the action starts successfully, run: `act -j test -W .github/workflows/secrets.yml -s GITHUB_TOKEN --defaultbranch main`
|
||||
@@ -4,8 +4,6 @@ on:
|
||||
push:
|
||||
tags:
|
||||
- v*
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
|
||||
permissions:
|
||||
@@ -17,9 +15,9 @@ jobs:
|
||||
name: lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/setup-go@v3
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.18'
|
||||
go-version: '1.20'
|
||||
- uses: actions/checkout@v3
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v3
|
||||
@@ -30,13 +28,10 @@ jobs:
|
||||
# working-directory: somedir
|
||||
|
||||
# Optional: golangci-lint command line arguments.
|
||||
args: --enable bodyclose --timeout 10m
|
||||
|
||||
# Optional: show only new issues if it's a pull request. The default value is `false`.
|
||||
only-new-issues: true
|
||||
args: --enable bodyclose --enable exportloopref --timeout 10m
|
||||
|
||||
# Optional: if set to true then the action don't cache or restore ~/go/pkg.
|
||||
# skip-pkg-cache: true
|
||||
|
||||
# Optional: if set to true then the action don't cache or restore ~/.cache/go-build.
|
||||
# skip-build-cache: true
|
||||
# skip-build-cache: true
|
||||
|
||||
@@ -1,16 +1,9 @@
|
||||
name: Release
|
||||
|
||||
# on:
|
||||
# push:
|
||||
# tags:
|
||||
# - 'v*'
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- v*
|
||||
branches:
|
||||
- main
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
@@ -40,9 +33,9 @@ jobs:
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v3
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.18'
|
||||
go-version: '1.20'
|
||||
- name: Run GoReleaser
|
||||
uses: goreleaser/goreleaser-action@v4
|
||||
with:
|
||||
|
||||
@@ -7,15 +7,16 @@ on:
|
||||
- v*
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v3
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.18'
|
||||
go-version: '1.20'
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
@@ -27,4 +28,4 @@ jobs:
|
||||
with:
|
||||
path: ./
|
||||
base: ${{ github.event.repository.default_branch }}
|
||||
head: HEAD
|
||||
head: HEAD
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
|
||||
name: Smoke
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
smoke:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.18'
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ github.head_ref }}
|
||||
- name: Smoke
|
||||
run: |
|
||||
set -e
|
||||
go run . git https://github.com/dustin-decker/secretsandstuff.git
|
||||
go run . github --repo https://github.com/dustin-decker/secretsandstuff.git
|
||||
@@ -16,9 +16,9 @@ jobs:
|
||||
name: Run Snifftest
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/setup-go@v3
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.18'
|
||||
go-version: '1.20'
|
||||
- uses: actions/checkout@v3
|
||||
- name: Run Snifftest
|
||||
run: make snifftest
|
||||
@@ -17,9 +17,9 @@ jobs:
|
||||
id-token: 'write'
|
||||
steps:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v3
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.18'
|
||||
go-version: '1.20'
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
- id: 'auth'
|
||||
@@ -36,9 +36,9 @@ jobs:
|
||||
id-token: 'write'
|
||||
steps:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v3
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.18'
|
||||
go-version: '1.20'
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
- id: 'auth'
|
||||
|
||||
+4
-1
@@ -1,4 +1,7 @@
|
||||
.idea
|
||||
dist
|
||||
.env
|
||||
*.test
|
||||
*.test
|
||||
|
||||
# binary
|
||||
trufflehog
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
- id: trufflehog
|
||||
name: TruffleHog
|
||||
description: Detect secrets in your data with TruffleHog.
|
||||
entry: trufflehog git file://. --since-commit HEAD --only-verified --fail
|
||||
language: golang
|
||||
pass_filenames: false
|
||||
+1
-1
@@ -9,7 +9,7 @@ RUN --mount=type=cache,target=/go/pkg/mod \
|
||||
GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -o trufflehog .
|
||||
|
||||
FROM alpine:3.15
|
||||
RUN apk add --no-cache git ca-certificates \
|
||||
RUN apk add --no-cache bash git openssh-client ca-certificates \
|
||||
&& rm -rf /var/cache/apk/* && \
|
||||
update-ca-certificates
|
||||
COPY --from=builder /build/trufflehog /usr/bin/trufflehog
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
FROM alpine:3.15
|
||||
|
||||
RUN apk add --no-cache git ca-certificates \
|
||||
RUN apk add --no-cache bash git openssh-client ca-certificates \
|
||||
&& rm -rf /var/cache/apk/* && \
|
||||
update-ca-certificates
|
||||
WORKDIR /usr/bin/
|
||||
|
||||
@@ -22,7 +22,7 @@ check:
|
||||
go vet $(shell go list ./... | grep -v /vendor/)
|
||||
|
||||
lint:
|
||||
golangci-lint run --out-format=colored-line-number --timeout 10m
|
||||
golangci-lint run --enable bodyclose --enable exportloopref --out-format=colored-line-number --timeout 10m
|
||||
|
||||
test-failing:
|
||||
CGO_ENABLED=0 go test -timeout=5m $(shell go list ./... | grep -v /vendor/) | grep FAIL
|
||||
@@ -62,4 +62,4 @@ snifftest:
|
||||
./hack/snifftest/snifftest.sh
|
||||
|
||||
test-release:
|
||||
goreleaser release --rm-dist --skip-publish --snapshot
|
||||
goreleaser release --rm-dist --skip-publish --snapshot
|
||||
|
||||
@@ -17,26 +17,58 @@
|
||||
|
||||
---
|
||||
|
||||
## Join The Slack
|
||||
# :mag_right: _Now Scanning_
|
||||
|
||||
<div align="center">
|
||||
|
||||
<img src="assets/scanning_logos.svg">
|
||||
|
||||
**...and more**
|
||||
|
||||
</div>
|
||||
|
||||
# :loudspeaker: Join Our Community
|
||||
Have questions? Feedback? Jump in slack and hang out with us
|
||||
|
||||
https://join.slack.com/t/trufflehog-community/shared_invite/zt-pw2qbi43-Aa86hkiimstfdKH9UCpPzQ
|
||||
|
||||
|
||||
## Demo
|
||||
# :tv: Demo
|
||||
|
||||

|
||||
|
||||
```bash
|
||||
docker run -it -v "$PWD:/pwd" trufflesecurity/trufflehog:latest github --org=trufflesecurity
|
||||
docker run --rm -it -v "$PWD:/pwd" trufflesecurity/trufflehog:latest github --org=trufflesecurity
|
||||
```
|
||||
|
||||
## Examples
|
||||
# :floppy_disk: Installation
|
||||
|
||||
### Example 1: Scan a repo for only verified secrets
|
||||
Several options available for you:
|
||||
```bash
|
||||
# MacOS users
|
||||
brew install trufflesecurity/trufflehog/trufflehog
|
||||
|
||||
# Docker
|
||||
docker run --rm -it -v "$PWD:/pwd" trufflesecurity/trufflehog:latest github --repo https://github.com/trufflesecurity/test_keys
|
||||
|
||||
# Docker for M1 and M2 Mac
|
||||
docker run --platform linux/arm64 --rm -it -v "$PWD:/pwd" trufflesecurity/trufflehog:latest github --repo https://github.com/trufflesecurity/test_keys
|
||||
|
||||
# Binary releases
|
||||
Download and unpack from https://github.com/trufflesecurity/trufflehog/releases
|
||||
|
||||
# Compile from source
|
||||
git clone https://github.com/trufflesecurity/trufflehog.git
|
||||
cd trufflehog; go install
|
||||
```
|
||||
|
||||
# :rocket: Quick Start
|
||||
|
||||
## 1: Scan a repo for only verified secrets
|
||||
|
||||
Command:
|
||||
```
|
||||
|
||||
```bash
|
||||
trufflehog git https://github.com/trufflesecurity/test_keys --only-verified
|
||||
```
|
||||
|
||||
@@ -57,16 +89,17 @@ Timestamp: 2022-06-16 10:17:40 -0700 PDT
|
||||
...
|
||||
```
|
||||
|
||||
### Example 2: Scan a GitHub Org for only verified secrets
|
||||
## 2: Scan a GitHub Org for only verified secrets
|
||||
|
||||
```
|
||||
```bash
|
||||
trufflehog github --org=trufflesecurity --only-verified
|
||||
```
|
||||
|
||||
### Example 3: Scan a GitHub Repo for only verified keys and get JSON output
|
||||
## 3: Scan a GitHub Repo for only verified keys and get JSON output
|
||||
|
||||
Command:
|
||||
```
|
||||
|
||||
```bash
|
||||
trufflehog git https://github.com/trufflesecurity/test_keys --only-verified --json
|
||||
```
|
||||
|
||||
@@ -76,81 +109,55 @@ Expected output:
|
||||
...
|
||||
```
|
||||
|
||||
### Example 4: Scan an S3 bucket for verified keys
|
||||
```
|
||||
## 4: Scan an S3 bucket for verified keys
|
||||
|
||||
```bash
|
||||
trufflehog s3 --bucket=<bucket name> --only-verified
|
||||
```
|
||||
|
||||
### FAQ
|
||||
## 5: Scan a Github Repo using SSH authentication in docker
|
||||
|
||||
```bash
|
||||
docker run --rm -v "$HOME/.ssh:/root/.ssh:ro" trufflesecurity/trufflehog:latest git ssh://github.com/trufflesecurity/test_keys
|
||||
```
|
||||
|
||||
## 6: Scan individual files or directories
|
||||
|
||||
```bash
|
||||
trufflehog filesystem path/to/file1.txt path/to/file2.txt path/to/dir
|
||||
```
|
||||
|
||||
## 7: Scan GCS buckets for verified secrets.
|
||||
|
||||
```bash
|
||||
trufflehog gcs --project-id=<project-ID> --cloud-environment --only-verified
|
||||
```
|
||||
|
||||
# :question: FAQ
|
||||
|
||||
+ All I see is `🐷🔑🐷 TruffleHog. Unearth your secrets. 🐷🔑🐷` and the program exits, what gives?
|
||||
+ That means no secrets were detected
|
||||
+ Why is the scan is taking a long time when I scan a GitHub org
|
||||
+ Unauthenticated GitHub scans have rate limits. To improve your rate limits, include the `--token` flag with a personal access token
|
||||
+ It says a private key was verified, what does that mean?
|
||||
+ Check out our Driftwood blog post to learn how to do this, in short we've confirmed the key can be used live for SSH or SSL [Blog post](https://trufflesecurity.com/blog/driftwood-know-if-private-keys-are-sensitive/)
|
||||
+ Check out our Driftwood blog post to learn how to do this, in short we've confirmed the key can be used live for SSH or SSL [Blog post](https://trufflesecurity.com/blog/driftwood-know-if-private-keys-are-sensitive/)
|
||||
|
||||
|
||||
# What's new in v3?
|
||||
# :newspaper: What's new in v3?
|
||||
|
||||
TruffleHog v3 is a complete rewrite in Go with many new powerful features.
|
||||
|
||||
- We've **added over 700 credential detectors that support active verification against their respective APIs**.
|
||||
- We've also added native **support for scanning GitHub, GitLab, filesystems, S3, and Circle CI**.
|
||||
- We've also added native **support for scanning GitHub, GitLab, filesystems, S3, GCS and Circle CI**.
|
||||
- **Instantly verify private keys** against millions of github users and **billions** of TLS certificates using our [Driftwood](https://trufflesecurity.com/blog/driftwood) technology.
|
||||
- Scan binaries and other file formats
|
||||
- Available as a GitHub Action and a pre-commit hook
|
||||
|
||||
|
||||
## What is credential verification?
|
||||
For every potential credential that is detected, we've painstakingly implemented programatic verification against the API that we think it belongs to. Verification eliminates false positives. For example, the [AWS credential detector](pkg/detectors/aws/aws.go) performs a `GetCallerIdentity` API call against the AWS API to verify if an AWS credential is active.
|
||||
For every potential credential that is detected, we've painstakingly implemented programmatic verification against the API that we think it belongs to. Verification eliminates false positives. For example, the [AWS credential detector](pkg/detectors/aws/aws.go) performs a `GetCallerIdentity` API call against the AWS API to verify if an AWS credential is active.
|
||||
|
||||
## Installation
|
||||
|
||||
Several options:
|
||||
|
||||
### 1. Go
|
||||
```
|
||||
git clone https://github.com/trufflesecurity/trufflehog.git
|
||||
|
||||
cd trufflehog; go install
|
||||
```
|
||||
|
||||
### 2. [Release binaries](https://github.com/trufflesecurity/trufflehog/releases)
|
||||
|
||||
### 3. Docker
|
||||
|
||||
|
||||
> Note: Apple M1 hardware users should run with `docker run --platform linux/arm64` for better performance.
|
||||
|
||||
#### **Most users**
|
||||
|
||||
```bash
|
||||
docker run -it -v "$PWD:/pwd" trufflesecurity/trufflehog:latest github --repo https://github.com/trufflesecurity/test_keys
|
||||
```
|
||||
|
||||
#### **Apple M1 users**
|
||||
|
||||
The `linux/arm64` image is better to run on the M1 than the amd64 image.
|
||||
Even better is running the native darwin binary available, but there is no container image for that.
|
||||
|
||||
```bash
|
||||
docker run --platform linux/arm64 -it -v "$PWD:/pwd" trufflesecurity/trufflehog:latest github --repo https://github.com/trufflesecurity/test_keys
|
||||
```
|
||||
|
||||
### 4. Pip (help wanted)
|
||||
|
||||
It's possible to distribute binaries in pip wheels.
|
||||
|
||||
Here is an example of a [project that does it](https://github.com/Yelp/dumb-init).
|
||||
|
||||
Help with setting up this packaging would be appreciated!
|
||||
|
||||
### 5. Brew
|
||||
|
||||
```bash
|
||||
brew install trufflesecurity/trufflehog/trufflehog
|
||||
```
|
||||
|
||||
## Usage
|
||||
# :memo: Usage
|
||||
|
||||
TruffleHog has a sub-command for each source of data that you may want to scan:
|
||||
|
||||
@@ -158,10 +165,11 @@ TruffleHog has a sub-command for each source of data that you may want to scan:
|
||||
- github
|
||||
- gitlab
|
||||
- S3
|
||||
- filesystem
|
||||
- filesystem (files and directories)
|
||||
- syslog
|
||||
- circleci
|
||||
- file and stdin (coming soon)
|
||||
- GCS (Google Cloud Storage)
|
||||
- stdin (coming soon)
|
||||
|
||||
Each subcommand can have options that you can see with the `--help` flag provided to the sub command:
|
||||
|
||||
@@ -175,6 +183,7 @@ Flags:
|
||||
--help Show context-sensitive help (also try --help-long and --help-man).
|
||||
--debug Run in debug mode.
|
||||
--trace Run in trace mode.
|
||||
--profile Enables profiling and sets a pprof and fgprof server on :18066.
|
||||
-j, --json Output in JSON format.
|
||||
--json-legacy Use the pre-v3.0 JSON format. Only works with git, gitlab, and github sources.
|
||||
--concurrency=10 Number of concurrent workers.
|
||||
@@ -202,24 +211,16 @@ Exit Codes:
|
||||
- 1: An error was encountered. Sources may not have completed scans.
|
||||
- 183: No errors were encountered, but results were found. Will only be returned if `--fail` flag is used.
|
||||
|
||||
#### Scanning an organization
|
||||
|
||||
Try scanning an entire GitHub organization with the following:
|
||||
|
||||
```bash
|
||||
docker run -it -v "$PWD:/pwd" trufflesecurity/trufflehog:latest github --org=trufflesecurity
|
||||
```
|
||||
|
||||
### TruffleHog OSS Github Action
|
||||
# :octocat: TruffleHog Github Action
|
||||
|
||||
```yaml
|
||||
- name: TruffleHog OSS
|
||||
- name: TruffleHog
|
||||
uses: trufflesecurity/trufflehog@main
|
||||
with:
|
||||
# Repository path
|
||||
path:
|
||||
path:
|
||||
# Start scanning from here (usually main branch).
|
||||
base:
|
||||
base:
|
||||
# Scan commits until here (usually dev branch).
|
||||
head: # optional
|
||||
# Extra args to be passed to the trufflehog cli.
|
||||
@@ -231,7 +232,7 @@ any results are found.
|
||||
|
||||
For example, to scan the contents of pull requests you could use the following workflow:
|
||||
```yaml
|
||||
name: Leaked Secrets Scan
|
||||
name: TruffleHog Secrets Scan
|
||||
on: [pull_request]
|
||||
jobs:
|
||||
TruffleHog:
|
||||
@@ -250,7 +251,7 @@ jobs:
|
||||
extra_args: --debug --only-verified
|
||||
```
|
||||
|
||||
### Precommit Hook
|
||||
# Precommit Hook
|
||||
|
||||
Trufflehog can be used in a precommit hook to prevent credentials from leaking before they ever leave your computer.
|
||||
An example `.pre-commit-config.yaml` is provided (see [pre-commit.com](https://pre-commit.com/) for installation).
|
||||
@@ -264,12 +265,12 @@ repos:
|
||||
description: Detect secrets in your data.
|
||||
entry: bash -c 'trufflehog git file://. --since-commit HEAD --only-verified --fail'
|
||||
# For running trufflehog in docker, use the following entry instead:
|
||||
# entry: bash -c 'docker run -v "$(pwd):/workdir" -i --rm trufflesecurity/trufflehog:latest git file:///workdir --since-commit HEAD --only-verified --fail'
|
||||
# entry: bash -c 'docker run --rm -v "$(pwd):/workdir" -i --rm trufflesecurity/trufflehog:latest git file:///workdir --since-commit HEAD --only-verified --fail'
|
||||
language: system
|
||||
stages: ["commit", "push"]
|
||||
```
|
||||
|
||||
## Regex Detector (alpha)
|
||||
# Regex Detector (alpha)
|
||||
|
||||
Trufflehog supports detection and verification of custom regular expressions.
|
||||
For detection, at least one **regular expression** and **keyword** is required.
|
||||
@@ -283,7 +284,7 @@ status code, the secret is considered verified.
|
||||
|
||||
**NB:** This feature is alpha and subject to change.
|
||||
|
||||
### Regex Detector Example
|
||||
## Regex Detector Example
|
||||
|
||||
```yaml
|
||||
# config.yaml
|
||||
@@ -302,7 +303,7 @@ detectors:
|
||||
```
|
||||
|
||||
```
|
||||
» trufflehog filesystem --directory /tmp --config config.yaml --only-verified
|
||||
$ trufflehog filesystem /tmp --config config.yaml --only-verified
|
||||
🐷🔑🐷 TruffleHog. Unearth your secrets. 🐷🔑🐷
|
||||
|
||||
Found verified result 🐷🔑
|
||||
@@ -312,7 +313,7 @@ Raw result: hogs are cool
|
||||
File: /tmp/hog-facts.txt
|
||||
```
|
||||
|
||||
#### Verification Server Example (Python)
|
||||
## Verification Server Example (Python)
|
||||
|
||||
Unless you run a verification server, secrets found by the custom regex
|
||||
detector will be unverified. Here is an example Python implementation of a
|
||||
@@ -362,12 +363,7 @@ with HTTPServer(('', 8000), Verifier) as server:
|
||||
pass
|
||||
```
|
||||
|
||||
## Use as a library
|
||||
|
||||
Currently, trufflehog is in heavy development and no guarantees can be made on
|
||||
the stability of the public APIs at this time.
|
||||
|
||||
## Contributors
|
||||
# :heart: Contributors
|
||||
|
||||
This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].
|
||||
|
||||
@@ -377,22 +373,28 @@ This project exists thanks to all the people who contribute. [[Contribute](CONTR
|
||||
</a>
|
||||
|
||||
|
||||
## Contributing
|
||||
# :computer: Contributing
|
||||
|
||||
Contributions are very welcome! Please see our [contribution guidelines first](CONTRIBUTING.md).
|
||||
|
||||
We no longer accept contributions to TruffleHog v2, but that code is available in the `v2` branch.
|
||||
|
||||
### Adding new secret detectors
|
||||
|
||||
## Adding new secret detectors
|
||||
|
||||
We have published some [documentation and tooling to get started on adding new secret detectors](hack/docs/Adding_Detectors_external.md). Let's improve detection together!
|
||||
|
||||
## License Change
|
||||
|
||||
# Use as a library
|
||||
|
||||
Currently, trufflehog is in heavy development and no guarantees can be made on
|
||||
the stability of the public APIs at this time.
|
||||
# License Change
|
||||
|
||||
Since v3.0, TruffleHog is released under a AGPL 3 license, included in [`LICENSE`](LICENSE). TruffleHog v3.0 uses none of the previous codebase, but care was taken to preserve backwards compatibility on the command line interface. The work previous to this release is still available licensed under GPL 2.0 in the history of this repository and the previous package releases and tags. A completed CLA is required for us to accept contributions going forward.
|
||||
|
||||
|
||||
## Enterprise product
|
||||
# :money_with_wings: Enterprise product
|
||||
|
||||
Are you interested in continously monitoring your Git, Jira, Slack, Confluence, etc.. for credentials? We have an enterprise product that can help. Reach out here to learn more https://trufflesecurity.com/contact/
|
||||
|
||||
|
||||
@@ -32,4 +32,5 @@ runs:
|
||||
- ${{ inputs.head }}
|
||||
- --fail
|
||||
- --no-update
|
||||
- --github-actions
|
||||
- ${{ inputs.extra_args }}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/></svg>
|
||||
|
After Width: | Height: | Size: 814 B |
@@ -0,0 +1,167 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="173.78879mm"
|
||||
height="26.198219mm"
|
||||
viewBox="0 0 173.78879 26.198219"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
xml:space="preserve"
|
||||
inkscape:version="1.2.2 (b0a84865, 2022-12-01)"
|
||||
sodipodi:docname="scanning_logos.svg"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
|
||||
id="namedview7"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#999999"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.67348485"
|
||||
inkscape:cx="376.40045"
|
||||
inkscape:cy="538.98763"
|
||||
inkscape:window-width="1250"
|
||||
inkscape:window-height="906"
|
||||
inkscape:window-x="1226"
|
||||
inkscape:window-y="265"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="layer1" /><defs
|
||||
id="defs2"><style
|
||||
id="style344">.cls-1{fill:#e24329;}.cls-2{fill:#fc6d26;}.cls-3{fill:#fca326;}</style><style
|
||||
id="style433">
|
||||
.cls-1 {
|
||||
fill: #e25444;
|
||||
}
|
||||
|
||||
.cls-1, .cls-2, .cls-3 {
|
||||
fill-rule: evenodd;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
fill: #7b1d13;
|
||||
}
|
||||
|
||||
.cls-3 {
|
||||
fill: #58150d;
|
||||
}
|
||||
</style><path
|
||||
d="M 27.791,115.217 1.541,69.749 a 11.499,11.499 0 0 1 0,-11.499 l 26.25,-45.467 a 11.499,11.499 0 0 1 9.959,-5.75 h 52.5 a 11.5,11.5 0 0 1 9.96,5.75 l 26.25,45.467 a 11.499,11.499 0 0 1 0,11.5 l -26.25,45.466 a 11.499,11.499 0 0 1 -9.96,5.75 h -52.5 a 11.499,11.499 0 0 1 -9.959,-5.75 z"
|
||||
id="b" /></defs><g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-5.467857,-5.738096)"><g
|
||||
id="g706"><path
|
||||
fill="#f05133"
|
||||
d="M 88.304634,18.167061 77.689818,7.5527709 c -0.611187,-0.611452 -1.602581,-0.611452 -2.214298,0 l -2.203979,2.204508 2.795852,2.7958521 c 0.649817,-0.219604 1.394883,-0.07223 1.912673,0.445823 0.520965,0.521229 0.667015,1.272646 0.441854,1.924844 l 2.695045,2.694781 c 0.652198,-0.224895 1.404144,-0.07938 1.924844,0.442119 0.727604,0.727604 0.727604,1.906588 0,2.634721 -0.728134,0.727869 -1.907117,0.727869 -2.635515,0 -0.547157,-0.547688 -0.682624,-1.352021 -0.405077,-2.026179 l -2.513541,-2.513277 v 6.613789 c 0.177271,0.08784 0.344753,0.204788 0.49239,0.352425 0.727604,0.727604 0.727604,1.906588 0,2.634986 -0.727604,0.727339 -1.907381,0.727339 -2.634456,0 -0.727604,-0.728663 -0.727604,-1.907646 0,-2.634986 0.179916,-0.179652 0.388144,-0.315648 0.610394,-0.406664 v -6.675438 c -0.22225,-0.09102 -0.429948,-0.225689 -0.610394,-0.406664 -0.551127,-0.550863 -0.683684,-1.359959 -0.401109,-2.036763 l -2.756164,-2.756694 -7.278688,7.277894 c -0.611452,0.611981 -0.611452,1.603375 0,2.214827 l 10.615348,10.614554 c 0.611188,0.611452 1.602317,0.611452 2.214298,0 L 88.304634,20.381888 c 0.61145,-0.611452 0.61145,-1.603375 0,-2.214827 z"
|
||||
id="path79"
|
||||
style="stroke-width:0.264583" /><path
|
||||
d="m 17.874996,7.9032889 c -6.850808,0 -12.407139,5.3892601 -12.407139,12.0363631 0,5.318065 3.554648,9.829669 8.485453,11.421504 0.619321,0.111453 0.819902,-0.261967 0.819902,-0.578771 v -2.240776 c -3.451252,0.728214 -4.169831,-1.420293 -4.169831,-1.420293 -0.564526,-1.391177 -1.378228,-1.76129 -1.378228,-1.76129 -1.125947,-0.747278 0.08582,-0.731237 0.08582,-0.731237 1.245884,0.08414 1.901392,1.240753 1.901392,1.240753 1.106307,1.83957 2.902239,1.307954 3.610476,1.000022 0.110631,-0.777343 0.432184,-1.308957 0.787857,-1.608858 -2.75542,-0.305935 -5.652486,-1.338031 -5.652486,-5.948955 0,-1.314982 0.484911,-2.38821 1.277936,-3.230747 -0.128214,-0.304036 -0.553152,-1.528637 0.120985,-3.185643 0,0 1.0422,-0.322993 3.412995,1.233734 0.989472,-0.266877 2.050281,-0.400211 3.104887,-0.405253 1.054607,0.0033 2.116454,0.138376 3.107992,0.405253 2.368727,-1.556727 3.408859,-1.233734 3.408859,-1.233734 0.675156,1.657988 0.250214,2.882698 0.122,3.185643 0.796124,0.842537 1.276903,1.916758 1.276903,3.230747 0,4.62295 -2.902238,5.641012 -5.664896,5.938948 0.444591,0.373028 0.850923,1.105332 0.850923,2.228716 v 3.30297 c 0,0.319958 0.198515,0.696095 0.828178,0.577744 4.926667,-1.593809 8.477177,-6.104433 8.477177,-11.420477 0,-6.647103 -5.555295,-12.0363631 -12.407141,-12.0363631 z"
|
||||
id="path286"
|
||||
style="stroke-width:1.01836" /><g
|
||||
id="LOGO"
|
||||
transform="matrix(0.12753077,0,0,0.12866528,23.501297,-4.4119714)"><path
|
||||
class="cls-1"
|
||||
d="m 282.83,170.73 -0.27,-0.69 -26.14,-68.22 a 6.81,6.81 0 0 0 -2.69,-3.24 7,7 0 0 0 -8,0.43 7,7 0 0 0 -2.32,3.52 l -17.65,54 h -71.47 l -17.65,-54 a 6.86,6.86 0 0 0 -2.32,-3.53 7,7 0 0 0 -8,-0.43 6.87,6.87 0 0 0 -2.69,3.24 L 97.44,170 l -0.26,0.69 a 48.54,48.54 0 0 0 16.1,56.1 l 0.09,0.07 0.24,0.17 39.82,29.82 19.7,14.91 12,9.06 a 8.07,8.07 0 0 0 9.76,0 l 12,-9.06 19.7,-14.91 40.06,-30 0.1,-0.08 a 48.56,48.56 0 0 0 16.08,-56.04 z"
|
||||
id="path348" /><path
|
||||
class="cls-2"
|
||||
d="m 282.83,170.73 -0.27,-0.69 a 88.3,88.3 0 0 0 -35.15,15.8 L 190,229.25 c 19.55,14.79 36.57,27.64 36.57,27.64 l 40.06,-30 0.1,-0.08 a 48.56,48.56 0 0 0 16.1,-56.08 z"
|
||||
id="path350" /><path
|
||||
class="cls-3"
|
||||
d="m 153.43,256.89 19.7,14.91 12,9.06 a 8.07,8.07 0 0 0 9.76,0 l 12,-9.06 19.7,-14.91 c 0,0 -17.04,-12.89 -36.59,-27.64 -19.55,14.75 -36.57,27.64 -36.57,27.64 z"
|
||||
id="path352" /><path
|
||||
class="cls-2"
|
||||
d="M 132.58,185.84 A 88.19,88.19 0 0 0 97.44,170 l -0.26,0.69 a 48.54,48.54 0 0 0 16.1,56.1 l 0.09,0.07 0.24,0.17 39.82,29.82 c 0,0 17,-12.85 36.57,-27.64 z"
|
||||
id="path354" /></g><g
|
||||
id="g481"
|
||||
transform="matrix(0.06220237,0,0,0.05342262,92.880356,5.1809529)"><path
|
||||
class="cls-1"
|
||||
d="m 378,99 -83,158 83,158 34,-19 V 118 Z"
|
||||
id="path437" /><path
|
||||
class="cls-2"
|
||||
d="M 378,99 212,118 127.5,257 212,396 378,415 Z"
|
||||
id="path439" /><path
|
||||
class="cls-3"
|
||||
d="M 43,99 16,111 V 403 L 43,415 212,257 Z"
|
||||
id="path441" /><path
|
||||
class="cls-1"
|
||||
d="m 42.637,98.667 169.587,47.111 V 372.444 L 42.637,415.111 Z"
|
||||
id="path443" /><path
|
||||
class="cls-3"
|
||||
d="m 212.313,170.667 -72.008,-11.556 72.008,-81.778 71.83,81.778 z"
|
||||
id="path445" /><path
|
||||
class="cls-3"
|
||||
d="m 284.143,159.111 -71.919,11.733 -71.919,-11.733 V 77.333"
|
||||
id="path447" /><path
|
||||
class="cls-3"
|
||||
d="m 212.313,342.222 -72.008,13.334 72.008,70.222 71.83,-70.222 z"
|
||||
id="path449" /><path
|
||||
class="cls-2"
|
||||
d="m 212,16 -72,38 v 105 l 72.224,-20.333 z"
|
||||
id="path451" /><path
|
||||
class="cls-2"
|
||||
d="m 212.224,196.444 -71.919,7.823 v 104.838 l 71.919,8.228 z"
|
||||
id="path453" /><path
|
||||
class="cls-2"
|
||||
d="M 212.224,373.333 140.305,355.3 V 458.363 L 212.224,496 Z"
|
||||
id="path455" /><path
|
||||
class="cls-1"
|
||||
d="m 284.143,355.3 -71.919,18.038 V 496 l 71.919,-37.637 z"
|
||||
id="path457" /><path
|
||||
class="cls-1"
|
||||
d="m 212.224,196.444 71.919,7.823 v 104.838 l -71.919,8.228 z"
|
||||
id="path459" /><path
|
||||
class="cls-1"
|
||||
d="m 212,16 72,38 v 105 l -72,-20 z"
|
||||
id="path461" /></g><g
|
||||
id="g583"
|
||||
transform="matrix(0.20423993,0,0,0.21790562,123.68704,6.5803506)"><g
|
||||
transform="translate(0,-7.034)"
|
||||
id="g549"><linearGradient
|
||||
y2="120.789"
|
||||
x2="64"
|
||||
y1="7.0339999"
|
||||
x1="64"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="a"><stop
|
||||
offset="0"
|
||||
stop-color="#4387fd"
|
||||
id="stop542" /><stop
|
||||
offset="1"
|
||||
stop-color="#4683ea"
|
||||
id="stop544" /></linearGradient><path
|
||||
d="M 27.79,115.217 1.54,69.749 a 11.499,11.499 0 0 1 0,-11.499 L 27.79,12.783 a 11.5,11.5 0 0 1 9.96,-5.75 h 52.5 a 11.5,11.5 0 0 1 9.959,5.75 l 26.25,45.467 a 11.499,11.499 0 0 1 0,11.5 l -26.25,45.466 a 11.5,11.5 0 0 1 -9.959,5.75 h -52.5 a 11.499,11.499 0 0 1 -9.96,-5.75 z"
|
||||
fill="url(#a)"
|
||||
id="path547"
|
||||
style="fill:url(#a)" /></g><g
|
||||
transform="translate(0,-7.034)"
|
||||
id="g559"><defs
|
||||
id="defs552"><path
|
||||
d="M 27.791,115.217 1.541,69.749 a 11.499,11.499 0 0 1 0,-11.499 l 26.25,-45.467 a 11.499,11.499 0 0 1 9.959,-5.75 h 52.5 a 11.5,11.5 0 0 1 9.96,5.75 l 26.25,45.467 a 11.499,11.499 0 0 1 0,11.5 l -26.25,45.466 a 11.499,11.499 0 0 1 -9.96,5.75 h -52.5 a 11.499,11.499 0 0 1 -9.959,-5.75 z"
|
||||
id="path575" /></defs><clipPath
|
||||
id="c"><use
|
||||
height="100%"
|
||||
width="100%"
|
||||
xlink:href="#b"
|
||||
overflow="visible"
|
||||
id="use554" /></clipPath><path
|
||||
clip-path="url(#c)"
|
||||
opacity="0.07"
|
||||
d="m 49.313,53.875 -7.01,6.99 5.957,5.958 -5.898,10.476 44.635,44.636 10.816,0.002 L 118.936,84 85.489,50.55 Z"
|
||||
id="path557" /></g><path
|
||||
d="M 84.7,43.236 H 43.264 c -0.667,0 -1.212,0.546 -1.212,1.214 v 8.566 c 0,0.666 0.546,1.212 1.212,1.212 H 84.7 c 0.667,0 1.213,-0.546 1.213,-1.212 v -8.568 c 0,-0.666 -0.545,-1.213 -1.212,-1.213 m -6.416,7.976 a 2.484,2.484 0 0 1 -2.477,-2.48 2.475,2.475 0 0 1 2.477,-2.477 c 1.37,0 2.48,1.103 2.48,2.477 a 2.48,2.48 0 0 1 -2.48,2.48 m 6.415,8.491 -41.436,0.002 c -0.667,0 -1.212,0.546 -1.212,1.214 v 8.565 c 0,0.666 0.546,1.213 1.212,1.213 H 84.7 c 0.667,0 1.213,-0.547 1.213,-1.213 v -8.567 c 0,-0.666 -0.545,-1.214 -1.212,-1.214 m -6.416,7.976 a 2.483,2.483 0 0 1 -2.477,-2.48 2.475,2.475 0 0 1 2.477,-2.477 2.48,2.48 0 1 1 0,4.956"
|
||||
fill="#ffffff"
|
||||
id="path561" /></g><g
|
||||
style="fill:#000000"
|
||||
id="g668"
|
||||
transform="matrix(1.0414114,0,0,1.0768849,154.45231,5.738096)"><path
|
||||
d="m 8.963,12 c 0,-1.584 1.284,-2.855 2.855,-2.855 1.572,0 2.856,1.284 2.856,2.855 0,1.572 -1.284,2.856 -2.856,2.856 -1.57,0 -2.855,-1.284 -2.855,-2.856 z M 11.818,0 C 6.215,0 1.522,3.84 0.19,9.025 0.18,9.061 0.18,9.095 0.18,9.145 c 0,0.313 0.252,0.576 0.575,0.576 H 5.59 c 0.23,0 0.433,-0.13 0.517,-0.333 0.997,-2.16 3.18,-3.672 5.712,-3.672 3.466,0 6.286,2.82 6.286,6.287 0,3.47 -2.82,6.29 -6.29,6.29 -2.53,0 -4.714,-1.5 -5.71,-3.673 C 6.008,14.43 5.815,14.284 5.588,14.284 H 0.755 c -0.312,0 -0.575,0.253 -0.575,0.576 0,0.037 0.014,0.072 0.014,0.12 1.32,5.18 6.02,9.02 11.624,9.02 6.624,0 12,-5.375 12,-12 0,-6.623 -5.376,-12 -12,-12 z"
|
||||
id="path659" /></g></g></g></svg>
|
||||
|
After Width: | Height: | Size: 11 KiB |
+5
-4
@@ -1,5 +1,6 @@
|
||||
#!/usr/bin/env ash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# `$*` expands the `args` supplied in an `array` individually
|
||||
# or splits `args` in a string separated by whitespace.
|
||||
/usr/bin/trufflehog $*
|
||||
# Parse the last argument into an array of extra_args.
|
||||
mapfile -t extra_args < <(bash -c "for arg in ${*: -1}; do echo \$arg; done")
|
||||
|
||||
/usr/bin/trufflehog "${@: 1: $#-1}" "${extra_args[@]}"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module github.com/trufflesecurity/trufflehog/v3
|
||||
|
||||
go 1.18
|
||||
go 1.20
|
||||
|
||||
replace github.com/jpillora/overseer => github.com/trufflesecurity/overseer v1.1.7-custom5
|
||||
|
||||
@@ -10,23 +10,24 @@ replace github.com/gitleaks/go-gitdiff => github.com/trufflesecurity/go-gitdiff
|
||||
|
||||
require (
|
||||
cloud.google.com/go/secretmanager v1.10.0
|
||||
cloud.google.com/go/storage v1.30.1
|
||||
github.com/Azure/go-autorest/autorest/azure/auth v0.5.11
|
||||
github.com/TheZeroSlave/zapsentry v1.12.0
|
||||
github.com/TheZeroSlave/zapsentry v1.15.0
|
||||
github.com/aws/aws-sdk-go v1.44.83
|
||||
github.com/bill-rich/disk-buffer-reader v0.1.7
|
||||
github.com/bill-rich/go-syslog v0.0.0-20220413021637-49edb52a574c
|
||||
github.com/bitfinexcom/bitfinex-api-go v0.0.0-20210608095005-9e0b26f200fb
|
||||
github.com/bradleyfalzon/ghinstallation/v2 v2.1.0
|
||||
github.com/bradleyfalzon/ghinstallation/v2 v2.3.0
|
||||
github.com/crewjam/rfc5424 v0.1.0
|
||||
github.com/denisenkom/go-mssqldb v0.12.3
|
||||
github.com/envoyproxy/protoc-gen-validate v0.9.1
|
||||
github.com/fatih/color v1.13.0
|
||||
github.com/envoyproxy/protoc-gen-validate v1.0.0
|
||||
github.com/fatih/color v1.15.0
|
||||
github.com/felixge/fgprof v0.9.3
|
||||
github.com/getsentry/sentry-go v0.16.0
|
||||
github.com/getsentry/sentry-go v0.20.0
|
||||
github.com/go-errors/errors v1.4.2
|
||||
github.com/go-git/go-git/v5 v5.5.2
|
||||
github.com/go-git/go-git/v5 v5.6.1
|
||||
github.com/go-ldap/ldap/v3 v3.4.4
|
||||
github.com/go-logr/logr v1.2.3
|
||||
github.com/go-logr/logr v1.2.4
|
||||
github.com/go-logr/zapr v1.2.3
|
||||
github.com/go-redis/redis v6.15.9+incompatible
|
||||
github.com/go-sql-driver/mysql v1.7.0
|
||||
@@ -34,41 +35,44 @@ require (
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible
|
||||
github.com/google/go-cmp v0.5.9
|
||||
github.com/google/go-github/v42 v42.0.0
|
||||
github.com/googleapis/gax-go/v2 v2.7.1
|
||||
github.com/gorilla/mux v1.8.0
|
||||
github.com/hashicorp/go-retryablehttp v0.7.2
|
||||
github.com/jlaffaye/ftp v0.1.0
|
||||
github.com/joho/godotenv v1.4.0
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/jpillora/overseer v1.1.6
|
||||
github.com/kylelemons/godebug v1.1.0
|
||||
github.com/lib/pq v1.10.7
|
||||
github.com/mattn/go-colorable v0.1.13
|
||||
github.com/lib/pq v1.10.8
|
||||
github.com/mattn/go-sqlite3 v1.14.16
|
||||
github.com/mholt/archiver/v4 v4.0.0-alpha.7
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||
github.com/paulbellamy/ratecounter v0.2.0
|
||||
github.com/petar-dambovaliev/aho-corasick v0.0.0-20211021192214-5ab2d9280aa9
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/rabbitmq/amqp091-go v1.5.0
|
||||
github.com/sergi/go-diff v1.2.0
|
||||
github.com/sirupsen/logrus v1.9.0
|
||||
github.com/stretchr/testify v1.8.1
|
||||
github.com/rabbitmq/amqp091-go v1.8.0
|
||||
github.com/sergi/go-diff v1.3.1
|
||||
github.com/stretchr/testify v1.8.2
|
||||
github.com/tailscale/depaware v0.0.0-20210622194025-720c4b409502
|
||||
github.com/xanzy/go-gitlab v0.77.0
|
||||
go.mongodb.org/mongo-driver v1.11.1
|
||||
github.com/xanzy/go-gitlab v0.83.0
|
||||
go.mongodb.org/mongo-driver v1.11.4
|
||||
go.uber.org/zap v1.24.0
|
||||
golang.org/x/crypto v0.5.0
|
||||
golang.org/x/crypto v0.8.0
|
||||
golang.org/x/exp v0.0.0-20221018205818-5c77f4b2bbd7
|
||||
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783
|
||||
golang.org/x/oauth2 v0.7.0
|
||||
golang.org/x/sync v0.1.0
|
||||
google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c
|
||||
google.golang.org/protobuf v1.28.1
|
||||
golang.org/x/text v0.9.0
|
||||
google.golang.org/api v0.114.0
|
||||
google.golang.org/protobuf v1.30.0
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6
|
||||
gopkg.in/h2non/gock.v1 v1.1.2
|
||||
sigs.k8s.io/yaml v1.3.0
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go/compute v1.12.1 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.2.1 // indirect
|
||||
cloud.google.com/go/iam v0.8.0 // indirect
|
||||
cloud.google.com/go v0.110.0 // indirect
|
||||
cloud.google.com/go/compute v1.18.0 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
||||
cloud.google.com/go/iam v0.12.0 // indirect
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
||||
github.com/Azure/go-autorest/autorest v0.11.24 // indirect
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.18 // indirect
|
||||
@@ -78,11 +82,11 @@ require (
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20220621081337-cb9428e4ac1e // indirect
|
||||
github.com/Microsoft/go-winio v0.5.2 // indirect
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20221026131551-cf6655e29de4 // indirect
|
||||
github.com/acomagu/bufpipe v1.0.3 // indirect
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 // indirect
|
||||
github.com/acomagu/bufpipe v1.0.4 // indirect
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect
|
||||
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
|
||||
github.com/andybalholm/brotli v1.0.4 // indirect
|
||||
github.com/andybalholm/brotli v1.0.5 // indirect
|
||||
github.com/benbjohnson/clock v1.1.0 // indirect
|
||||
github.com/cloudflare/circl v1.1.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
@@ -91,19 +95,19 @@ require (
|
||||
github.com/emirpasic/gods v1.18.1 // indirect
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.4 // indirect
|
||||
github.com/go-git/gcfg v1.5.0 // indirect
|
||||
github.com/go-git/go-billy/v5 v5.4.0 // indirect
|
||||
github.com/go-git/go-billy/v5 v5.4.1 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.4.1 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe // indirect
|
||||
github.com/golang-sql/sqlexp v0.1.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/go-github/v45 v45.2.0 // indirect
|
||||
github.com/google/go-github/v50 v50.2.0 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20211214055906-6f57359322fd // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.7.0 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect
|
||||
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
@@ -113,16 +117,17 @@ require (
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/jpillora/s3 v1.1.4 // indirect
|
||||
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||
github.com/klauspost/compress v1.15.11 // indirect
|
||||
github.com/klauspost/compress v1.16.0 // indirect
|
||||
github.com/klauspost/pgzip v1.2.5 // indirect
|
||||
github.com/mattn/go-isatty v0.0.16 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.17 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
|
||||
github.com/nwaples/rardecode/v2 v2.0.0-beta.2 // indirect
|
||||
github.com/onsi/ginkgo v1.16.5 // indirect
|
||||
github.com/onsi/gomega v1.23.0 // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.14 // indirect
|
||||
github.com/pjbgf/sha1cd v0.2.3 // indirect
|
||||
github.com/pjbgf/sha1cd v0.3.0 // indirect
|
||||
github.com/pkg/diff v0.0.0-20200914180035-5b29258ca4f7 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/skeema/knownhosts v1.1.0 // indirect
|
||||
@@ -137,15 +142,15 @@ require (
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.uber.org/atomic v1.7.0 // indirect
|
||||
go.uber.org/multierr v1.6.0 // indirect
|
||||
golang.org/x/mod v0.7.0 // indirect
|
||||
golang.org/x/net v0.5.0 // indirect
|
||||
golang.org/x/sys v0.4.0 // indirect
|
||||
golang.org/x/text v0.6.0 // indirect
|
||||
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
|
||||
golang.org/x/tools v0.3.0 // indirect
|
||||
google.golang.org/api v0.103.0 // indirect
|
||||
golang.org/x/mod v0.10.0 // indirect
|
||||
golang.org/x/net v0.9.0 // indirect
|
||||
golang.org/x/sys v0.7.0 // indirect
|
||||
golang.org/x/time v0.3.0 // indirect
|
||||
golang.org/x/tools v0.8.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/grpc v1.51.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230320184635-7606e756e683 // indirect
|
||||
google.golang.org/grpc v1.53.0 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.105.0 h1:DNtEKRBAAzeS4KyIory52wWHuClNaXJ5x1F7xa4q+5Y=
|
||||
cloud.google.com/go/compute v1.12.1 h1:gKVJMEyqV5c/UnpzjjQbo3Rjvvqpr9B1DFSbJC4OXr0=
|
||||
cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU=
|
||||
cloud.google.com/go/compute/metadata v0.2.1 h1:efOwf5ymceDhK6PKMnnrTHP4pppY5L22mle96M1yP48=
|
||||
cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM=
|
||||
cloud.google.com/go/iam v0.8.0 h1:E2osAkZzxI/+8pZcxVLcDtAQx/u+hZXVryUaYQ5O0Kk=
|
||||
cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE=
|
||||
cloud.google.com/go/longrunning v0.3.0 h1:NjljC+FYPV3uh5/OwWT6pVU+doBqMg2x/rZlE+CamDs=
|
||||
cloud.google.com/go v0.110.0 h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys=
|
||||
cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY=
|
||||
cloud.google.com/go/compute v1.18.0 h1:FEigFqoDbys2cvFkZ9Fjq4gnHBP55anJ0yQyau2f9oY=
|
||||
cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs=
|
||||
cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
|
||||
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
|
||||
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
|
||||
cloud.google.com/go/iam v0.12.0 h1:DRtTY29b75ciH6Ov1PHb4/iat2CLCvrOm40Q0a6DFpE=
|
||||
cloud.google.com/go/iam v0.12.0/go.mod h1:knyHGviacl11zrtZUoDuYpDgLjvr28sLQaG0YB2GYAY=
|
||||
cloud.google.com/go/longrunning v0.4.1 h1:v+yFJOfKC3yZdY6ZUI933pIYdhyhV8S3NpWrXWmg7jM=
|
||||
cloud.google.com/go/secretmanager v1.10.0 h1:pu03bha7ukxF8otyPKTFdDz+rr9sE3YauS5PliDXK60=
|
||||
cloud.google.com/go/secretmanager v1.10.0/go.mod h1:MfnrdvKMPNra9aZtQFvBcvRU54hbPD8/HayQdlUgJpU=
|
||||
cloud.google.com/go/storage v1.30.1 h1:uOdMxAs8HExqBlnLtnQyP0YkvbiDpdGShGKtx6U/oNM=
|
||||
cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0/go.mod h1:h6H6c8enJmmocHUbLiiGY6sx7f9i+X3m1CHdd5c6Rdw=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0/go.mod h1:HcM1YX14R7CJcghJGOYCgdezslRSVzqwLf/q+4Y2r/0=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8=
|
||||
@@ -35,18 +39,18 @@ github.com/Azure/go-ntlmssp v0.0.0-20220621081337-cb9428e4ac1e/go.mod h1:chxPXzS
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA=
|
||||
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20221026131551-cf6655e29de4 h1:ra2OtmuW0AE5csawV4YXMNGNQQXvLRps3z2Z59OPO+I=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20221026131551-cf6655e29de4/go.mod h1:UBYPn8k0D56RtnR8RFQMjmh4KrZzWJ5o7Z9SYjossQ8=
|
||||
github.com/TheZeroSlave/zapsentry v1.12.0 h1:hhfwvD7pQbnCIOvAEGM4NXLiaX4b6W6ZWNtL6awSBGc=
|
||||
github.com/TheZeroSlave/zapsentry v1.12.0/go.mod h1:00uO/VpPrSJG/XigAfTi0F4WMFIw2DmP/IDVUhPBvNw=
|
||||
github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk=
|
||||
github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 h1:wPbRQzjjwFc0ih8puEVAOFGELsn1zoIIYdxvML7mDxA=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g=
|
||||
github.com/TheZeroSlave/zapsentry v1.15.0 h1:w/YglG4Hc2L2VoEH6JKC+3YzhUL18/OZRjJRSvyXZp4=
|
||||
github.com/TheZeroSlave/zapsentry v1.15.0/go.mod h1:D1YMfSuu6xnkhwFXxrronesmsiyDhIqo+86I3Ok+r64=
|
||||
github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ=
|
||||
github.com/acomagu/bufpipe v1.0.4/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc=
|
||||
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
|
||||
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
|
||||
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
|
||||
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
@@ -61,8 +65,8 @@ github.com/bill-rich/go-syslog v0.0.0-20220413021637-49edb52a574c h1:tSME5FDS02q
|
||||
github.com/bill-rich/go-syslog v0.0.0-20220413021637-49edb52a574c/go.mod h1:+sCc6hztur+oZCLOsNk6wCCy+GLrnSNHSRmTnnL+8iQ=
|
||||
github.com/bitfinexcom/bitfinex-api-go v0.0.0-20210608095005-9e0b26f200fb h1:9v7Bzlg+1EBYi2IYcUmOwHReBEfqBbYIj3ZCi9cIe1Q=
|
||||
github.com/bitfinexcom/bitfinex-api-go v0.0.0-20210608095005-9e0b26f200fb/go.mod h1:EkOqCuelvo7DY8vCOoZ09p7pHvAK9B1PHI9GeM4Rdxc=
|
||||
github.com/bradleyfalzon/ghinstallation/v2 v2.1.0 h1:5+NghM1Zred9Z078QEZtm28G/kfDfZN/92gkDlLwGVA=
|
||||
github.com/bradleyfalzon/ghinstallation/v2 v2.1.0/go.mod h1:Xg3xPRN5Mcq6GDqeUVhFbjEWMb4JHCyWEeeBGEYQoTU=
|
||||
github.com/bradleyfalzon/ghinstallation/v2 v2.3.0 h1:RRGTqFWOe++1YmvYmO0PvMGzYTaZ6f8X3Su8WKmM+Ds=
|
||||
github.com/bradleyfalzon/ghinstallation/v2 v2.3.0/go.mod h1:8rdGt82ERhM7sjY5FLx2gV4aPhxn6YUE8XlDMKG1z/Y=
|
||||
github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
@@ -92,17 +96,17 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.9.1 h1:PS7VIOgmSVhWUEeZwTe7z7zouA22Cr590PzXKbZHOVY=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w=
|
||||
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
|
||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.0.0 h1:FPFO7LWZ2pfphahSUMX8L5p/6FqSzRYRxq6V74eG8ZI=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.0.0/go.mod h1:0vj8bNkYbSTNS2PIyH87KZaeN4x9zpL9Qt8fQC7d+vs=
|
||||
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
|
||||
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
|
||||
github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g=
|
||||
github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/getsentry/sentry-go v0.16.0 h1:owk+S+5XcgJLlGR/3+3s6N4d+uKwqYvh/eS0AIMjPWo=
|
||||
github.com/getsentry/sentry-go v0.16.0/go.mod h1:ZXCloQLj0pG7mja5NK6NPf2V4A88YJ4pNlc2mOHwh6Y=
|
||||
github.com/getsentry/sentry-go v0.20.0 h1:bwXW98iMRIWxn+4FgPW7vMrjmbym6HblXALmhjHmQaQ=
|
||||
github.com/getsentry/sentry-go v0.20.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
|
||||
github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY=
|
||||
github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.4 h1:vXT6d/FNDiELJnLb6hGNa309LMsrCoYFvpwHDF0+Y1A=
|
||||
@@ -112,17 +116,17 @@ github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3Bop
|
||||
github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
|
||||
github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
|
||||
github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
|
||||
github.com/go-git/go-billy/v5 v5.4.0 h1:Vaw7LaSTRJOUric7pe4vnzBSgyuf2KrLsu2Y4ZpQBDE=
|
||||
github.com/go-git/go-billy/v5 v5.4.0/go.mod h1:vjbugF6Fz7JIflbVpl1hJsGjSHNltrSw45YK/ukIvQg=
|
||||
github.com/go-git/go-billy/v5 v5.4.1 h1:Uwp5tDRkPr+l/TnbHOQzp+tmJfLceOlbVucgpTz8ix4=
|
||||
github.com/go-git/go-billy/v5 v5.4.1/go.mod h1:vjbugF6Fz7JIflbVpl1hJsGjSHNltrSw45YK/ukIvQg=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.1 h1:y5z6dd3qi8Hl+stezc8p3JxDkoTRqMAlKnXHuzrfjTQ=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.1/go.mod h1:8LHG1a3SRW71ettAD/jW13h8c6AqjVSeL11RAdgaqpo=
|
||||
github.com/go-git/go-git/v5 v5.5.2 h1:v8lgZa5k9ylUw+OR/roJHTxR4QItsNFI5nKtAXFuynw=
|
||||
github.com/go-git/go-git/v5 v5.5.2/go.mod h1:BE5hUJ5yaV2YMxhmaP4l6RBQ08kMxKSPD4BlxtH7OjI=
|
||||
github.com/go-git/go-git/v5 v5.6.1 h1:q4ZRqQl4pR/ZJHc1L5CFjGA1a10u76aV1iC+nh+bHsk=
|
||||
github.com/go-git/go-git/v5 v5.6.1/go.mod h1:mvyoL6Unz0PiTQrGQfSfiLFhBH1c1e84ylC2MDs4ee8=
|
||||
github.com/go-ldap/ldap/v3 v3.4.4 h1:qPjipEpt+qDa6SI/h1fzuGWoRUY+qqQ9sOZq67/PYUs=
|
||||
github.com/go-ldap/ldap/v3 v3.4.4/go.mod h1:fe1MsuN5eJJ1FeLT/LEBVdWfNWKh459R7aXgXtJC+aI=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
|
||||
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
||||
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A=
|
||||
github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
@@ -141,8 +145,8 @@ github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keL
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||
github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
|
||||
github.com/golang-jwt/jwt/v4 v4.4.1 h1:pC5DB52sCeK48Wlb9oPcdhnjkz1TKt1D/P7WKJ0kUcQ=
|
||||
github.com/golang-jwt/jwt/v4 v4.4.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
|
||||
@@ -163,8 +167,9 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
@@ -181,17 +186,20 @@ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-github/v42 v42.0.0 h1:YNT0FwjPrEysRkLIiKuEfSvBPCGKphW5aS5PxwaoLec=
|
||||
github.com/google/go-github/v42 v42.0.0/go.mod h1:jgg/jvyI0YlDOM1/ps6XYh04HNQ3vKf0CVko62/EhRg=
|
||||
github.com/google/go-github/v45 v45.2.0 h1:5oRLszbrkvxDDqBCNj2hjDZMKmvexaZ1xw/FCD+K3FI=
|
||||
github.com/google/go-github/v45 v45.2.0/go.mod h1:FObaZJEDSTa/WGCzZ2Z3eoCDXWJKMenWWTrd8jrta28=
|
||||
github.com/google/go-github/v50 v50.2.0 h1:j2FyongEHlO9nxXLc+LP3wuBSVU9mVxfpdYUexMpIfk=
|
||||
github.com/google/go-github/v50 v50.2.0/go.mod h1:VBY8FB6yPIjrtKhozXv4FQupxKLS6H4m6xFZlT43q8Q=
|
||||
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||
github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw=
|
||||
github.com/google/pprof v0.0.0-20211214055906-6f57359322fd h1:1FjCyPC+syAzJ5/2S8fqdZK1R22vvA0J7JZKcuOIQ7Y=
|
||||
github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.0 h1:y8Yozv7SZtlU//QXbezB6QkpuE6jMD2/gfzk4AftXjs=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg=
|
||||
github.com/googleapis/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1YupQSSQ=
|
||||
github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k=
|
||||
github.com/googleapis/gax-go/v2 v2.7.1 h1:gF4c0zjUP2H/s/hEGyLA3I0fA2ZWjzYiONAD6cvPr8A=
|
||||
github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI=
|
||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
@@ -220,16 +228,16 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y
|
||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
||||
github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg=
|
||||
github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||
github.com/jpillora/s3 v1.1.4 h1:YCCKDWzb/Ye9EBNd83ATRF/8wPEy0xd43Rezb6u6fzc=
|
||||
github.com/jpillora/s3 v1.1.4/go.mod h1:yedE603V+crlFi1Kl/5vZJaBu9pUzE9wvKegU/lF2zs=
|
||||
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
|
||||
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.15.11 h1:Lcadnb3RKGin4FYM/orgq0qde+nc15E5Cbqg4B9Sx9c=
|
||||
github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
|
||||
github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4=
|
||||
github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
|
||||
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
||||
@@ -242,23 +250,22 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw=
|
||||
github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lib/pq v1.10.8 h1:3fdt97i/cwSU83+E0hZTC/Xpc9mTZxc6UWSCRcSbxiE=
|
||||
github.com/lib/pq v1.10.8/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A=
|
||||
github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
|
||||
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
|
||||
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/mholt/archiver/v4 v4.0.0-alpha.7 h1:xzByj8G8tj0Oq7ZYYU4+ixL/CVb5ruWCm0EZQ1PjOkE=
|
||||
github.com/mholt/archiver/v4 v4.0.0-alpha.7/go.mod h1:Fs8qUkO74HHaidabihzYephJH8qmGD/nCP6tE5xC9BM=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mmcloughlin/avo v0.5.0/go.mod h1:ChHFdoV7ql95Wi7vuq2YT1bwCJqiWdZrQ1im3VujLYM=
|
||||
github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0=
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
||||
@@ -279,13 +286,17 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y
|
||||
github.com/onsi/gomega v1.23.0 h1:/oxKu9c2HVap+F3PfKort2Hw5DEU+HGlW8n+tguWsys=
|
||||
github.com/onsi/gomega v1.23.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg=
|
||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||
github.com/paulbellamy/ratecounter v0.2.0 h1:2L/RhJq+HA8gBQImDXtLPrDXK5qAj6ozWVK/zFXVJGs=
|
||||
github.com/paulbellamy/ratecounter v0.2.0/go.mod h1:Hfx1hDpSGoqxkVVpBi/IlYD7kChlfo5C6hzIHwPqfFE=
|
||||
github.com/petar-dambovaliev/aho-corasick v0.0.0-20211021192214-5ab2d9280aa9 h1:lL+y4Xv20pVlCGyLzNHRC0I0rIHhIL1lTvHizoS/dU8=
|
||||
github.com/petar-dambovaliev/aho-corasick v0.0.0-20211021192214-5ab2d9280aa9/go.mod h1:EHPiTAKtiFmrMldLUNswFwfZ2eJIYBHktdaUTZxYWRw=
|
||||
github.com/pierrec/lz4/v4 v4.1.14 h1:+fL8AQEZtz/ijeNnpduH0bROTu0O3NZAlPjQxGn8LwE=
|
||||
github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
|
||||
github.com/pjbgf/sha1cd v0.2.3 h1:uKQP/7QOzNtKYH7UTohZLcjF5/55EnTw0jO/Ru4jZwI=
|
||||
github.com/pjbgf/sha1cd v0.2.3/go.mod h1:HOK9QrgzdHpbc2Kzip0Q1yi3M2MFGPADtR6HjG65m5M=
|
||||
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
|
||||
github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI=
|
||||
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
|
||||
github.com/pkg/diff v0.0.0-20200914180035-5b29258ca4f7 h1:+/+DxvQaYifJ+grD4klzrS5y+KJXldn/2YTl5JG+vZ8=
|
||||
github.com/pkg/diff v0.0.0-20200914180035-5b29258ca4f7/go.mod h1:zO8QMzTeZd5cpnIkz/Gn6iK0jDfGicM1nynOkkPIl28=
|
||||
@@ -295,15 +306,13 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/rabbitmq/amqp091-go v1.5.0 h1:VouyHPBu1CrKyJVfteGknGOGCzmOz0zcv/tONLkb7rg=
|
||||
github.com/rabbitmq/amqp091-go v1.5.0/go.mod h1:JsV0ofX5f1nwOGafb8L5rBItt9GyhfQfcJj+oyz0dGg=
|
||||
github.com/rabbitmq/amqp091-go v1.8.0 h1:GBFy5PpLQ5jSVVSYv8ecHGqeX7UTLYR4ItQbDCss9MM=
|
||||
github.com/rabbitmq/amqp091-go v1.8.0/go.mod h1:+jPrT9iY2eLjRaMSRHUhc3z14E/l85kv/f+6luSD3pc=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
|
||||
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
|
||||
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/skeema/knownhosts v1.1.0 h1:Wvr9V0MxhjRbl3f9nMnKnFfiWTJmtECJ9Njkea3ysW0=
|
||||
github.com/skeema/knownhosts v1.1.0/go.mod h1:sKFq3RD6/TKZkSWn8boUbDC7Qkgcv+8XXijpFO6roag=
|
||||
github.com/smartystreets/assertions v1.0.1 h1:voD4ITNjPL5jjBfgR/r8fPIIBrliWrWHeiJApdr3r4w=
|
||||
@@ -322,8 +331,9 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/tailscale/depaware v0.0.0-20210622194025-720c4b409502 h1:34icjjmqJ2HPjrSuJYEkdZ+0ItmGQAQ75cRHIiftIyE=
|
||||
github.com/tailscale/depaware v0.0.0-20210622194025-720c4b409502/go.mod h1:p9lPsd+cx33L3H9nNoecRRxPssFKUwwI50I3pZ0yT+8=
|
||||
github.com/therootcompany/xz v1.0.1 h1:CmOtsn1CbtmyYiusbfmhmkpAAETj0wBIH6kCYaX+xzw=
|
||||
@@ -335,8 +345,8 @@ github.com/trufflesecurity/overseer v1.1.7-custom5/go.mod h1:nT9w37AiO1Nop2VhVhN
|
||||
github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
|
||||
github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8=
|
||||
github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||
github.com/xanzy/go-gitlab v0.77.0 h1:UrbGlxkWVCbkpa6Fk6cM8ARh+rLACWemkJnsawT7t98=
|
||||
github.com/xanzy/go-gitlab v0.77.0/go.mod h1:d/a0vswScO7Agg1CZNz15Ic6SSvBG9vfw8egL99t4kA=
|
||||
github.com/xanzy/go-gitlab v0.83.0 h1:37p0MpTPNbsTMKX/JnmJtY8Ch1sFiJzVF342+RvZEGw=
|
||||
github.com/xanzy/go-gitlab v0.83.0/go.mod h1:5ryv+MnpZStBH8I/77HuQBsMbBGANtVpLWC15qOjWAw=
|
||||
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
|
||||
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
||||
@@ -348,37 +358,38 @@ github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgk
|
||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
|
||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
|
||||
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
go.mongodb.org/mongo-driver v1.11.1 h1:QP0znIRTuL0jf1oBQoAoM0C6ZJfBK4kx0Uumtv1A7w8=
|
||||
go.mongodb.org/mongo-driver v1.11.1/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8=
|
||||
go.mongodb.org/mongo-driver v1.11.4 h1:4ayjakA013OdpGyL2K3ZqylTac/rMjrJOMZ1EHizXas=
|
||||
go.mongodb.org/mongo-driver v1.11.4/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g=
|
||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
|
||||
go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA=
|
||||
go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||
go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
|
||||
go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4=
|
||||
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
|
||||
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
|
||||
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
|
||||
golang.org/x/arch v0.1.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
|
||||
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
|
||||
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
||||
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||
golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ=
|
||||
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20221018205818-5c77f4b2bbd7 h1:lhh9BuEmjIBOdOhMIGSQzdW5LbTtFbUV1k9O/Rlq3SE=
|
||||
golang.org/x/exp v0.0.0-20221018205818-5c77f4b2bbd7/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
|
||||
@@ -388,10 +399,11 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA=
|
||||
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
|
||||
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -404,18 +416,21 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw=
|
||||
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
|
||||
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
|
||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 h1:nt+Q6cXKz4MosCSpnbMtqiQ8Oz0pxTef2B4Vca2lvfk=
|
||||
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
|
||||
golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw=
|
||||
golang.org/x/oauth2 v0.7.0 h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g=
|
||||
golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -433,8 +448,6 @@ golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -443,11 +456,8 @@ golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@@ -456,24 +466,31 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
|
||||
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
|
||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
golang.org/x/term v0.4.0 h1:O7UWfv5+A2qiuulQk30kVinPoMtoIPeVaKLEgLpVkvg=
|
||||
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||
golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k=
|
||||
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af h1:Yx9k8YCG3dvF87UAn2tu2HQLf2dt/eR1bXxpLMWeH+Y=
|
||||
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
@@ -483,16 +500,19 @@ golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtn
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20201211185031-d93e913c1a58/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.3.0 h1:SrNbZl6ECOS1qFzgTdQfWXZM9XBkiA6tkFrH9YSTPHM=
|
||||
golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k=
|
||||
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.8.0 h1:vSDcovVPld282ceKgDimkRSC8kpaH1dgyc9UMzlt84Y=
|
||||
golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.103.0 h1:9yuVqlu2JCvcLg9p8S3fcFLZij8EPSyvODIY1rkMizQ=
|
||||
google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4qU9w0=
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
||||
google.golang.org/api v0.114.0 h1:1xQPji6cO2E2vLiI+C/XiFAnsn1WV3mjaEwGLhi3grE=
|
||||
google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
||||
@@ -500,15 +520,15 @@ google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCID
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c h1:S34D59DS2GWOEwWNt4fYmTcFrtlOgukG2k9WsomZ7tg=
|
||||
google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg=
|
||||
google.golang.org/genproto v0.0.0-20230320184635-7606e756e683 h1:khxVcsk/FhnzxMKOyD+TDGwjbEOpcPuIpmafPGFmhMA=
|
||||
google.golang.org/genproto v0.0.0-20230320184635-7606e756e683/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U=
|
||||
google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww=
|
||||
google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc=
|
||||
google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
@@ -520,8 +540,9 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
||||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
|
||||
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
@@ -550,5 +571,6 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
|
||||
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
|
||||
|
||||
@@ -9,6 +9,8 @@ import (
|
||||
"text/template"
|
||||
|
||||
"github.com/go-errors/errors"
|
||||
"golang.org/x/text/cases"
|
||||
"golang.org/x/text/language"
|
||||
"gopkg.in/alecthomas/kingpin.v2"
|
||||
)
|
||||
|
||||
@@ -24,7 +26,7 @@ func main() {
|
||||
log.SetPrefix("😲 [generate] ")
|
||||
|
||||
kingpin.MustParse(app.Parse(os.Args[1:]))
|
||||
nameTitle = strings.Title(*name)
|
||||
nameTitle = cases.Title(language.AmericanEnglish).String(*name)
|
||||
nameLower = strings.ToLower(*name)
|
||||
nameUpper = strings.ToUpper(*name)
|
||||
|
||||
@@ -65,7 +67,7 @@ type templateJob struct {
|
||||
}
|
||||
|
||||
func mustWriteTemplates(jobs []templateJob) {
|
||||
log.Printf("Generating %s %s\n", strings.Title(*kind), nameTitle)
|
||||
log.Printf("Generating %s %s\n", cases.Title(language.AmericanEnglish).String(*kind), nameTitle)
|
||||
|
||||
// Make the folder.
|
||||
log.Printf("Creating folder %s\n", folderPath())
|
||||
@@ -84,7 +86,7 @@ func mustWriteTemplates(jobs []templateJob) {
|
||||
|
||||
for _, rplString := range job.ReplaceString {
|
||||
tmplRaw = strings.ReplaceAll(tmplRaw, strings.ToLower(rplString), "<<.NameLower>>")
|
||||
tmplRaw = strings.ReplaceAll(tmplRaw, strings.Title(rplString), "<<.NameTitle>>")
|
||||
tmplRaw = strings.ReplaceAll(tmplRaw, cases.Title(language.AmericanEnglish).String(rplString), "<<.NameTitle>>")
|
||||
tmplRaw = strings.ReplaceAll(tmplRaw, strings.ToUpper(rplString), "<<.NameUpper>>")
|
||||
}
|
||||
|
||||
|
||||
+37
-18
@@ -11,7 +11,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/paulbellamy/ratecounter"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.org/x/sync/semaphore"
|
||||
"gopkg.in/alecthomas/kingpin.v2"
|
||||
|
||||
@@ -19,6 +18,7 @@ import (
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/decoders"
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/engine"
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/log"
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/source_metadatapb"
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/sourcespb"
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/sources"
|
||||
@@ -42,6 +42,20 @@ var (
|
||||
)
|
||||
|
||||
func main() {
|
||||
// setup logger
|
||||
logger, flush := log.New("trufflehog", log.WithConsoleSink(os.Stderr))
|
||||
// make it the default logger for contexts
|
||||
context.SetDefaultLogger(logger)
|
||||
defer func() { _ = flush() }()
|
||||
logFatal := func(err error, message string, keyAndVals ...any) {
|
||||
logger.Error(err, message, keyAndVals...)
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
return
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Hour*2)
|
||||
var cancelOnce sync.Once
|
||||
defer cancelOnce.Do(cancel)
|
||||
@@ -68,19 +82,19 @@ func main() {
|
||||
} else {
|
||||
_, ok := allScanners[input]
|
||||
if !ok {
|
||||
log.Fatal("could not find scanner by that name")
|
||||
logFatal(fmt.Errorf("invalid input"), "could not find scanner by that name")
|
||||
}
|
||||
selectedScanners[input] = allScanners[input]
|
||||
}
|
||||
if len(selectedScanners) == 0 {
|
||||
log.Fatal("no detectors selected")
|
||||
logFatal(fmt.Errorf("invalid input"), "no detectors selected")
|
||||
}
|
||||
|
||||
for _, excluded := range *scanCmdExclude {
|
||||
delete(selectedScanners, excluded)
|
||||
}
|
||||
|
||||
log.Infof("loaded %d secret detectors", len(selectedScanners)+3)
|
||||
logger.Info("loaded secret detectors", "count", len(selectedScanners)+3)
|
||||
|
||||
var wgScanners sync.WaitGroup
|
||||
|
||||
@@ -92,7 +106,7 @@ func main() {
|
||||
time.Sleep(60 * time.Second)
|
||||
counter.Incr(int64(chunkCounter - prev))
|
||||
prev = chunkCounter
|
||||
log.Infof("chunk scan rate: %d/sec", counter.Rate()/60)
|
||||
logger.Info("chunk scan rate per second", "rate", counter.Rate()/60)
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -122,7 +136,7 @@ func main() {
|
||||
|
||||
res, err := scanner.FromData(ctx, *scanVerify, decoded.Data)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
logFatal(err, "error scanning chunk")
|
||||
}
|
||||
if len(res) > 0 {
|
||||
if resCounter[name] == nil {
|
||||
@@ -131,16 +145,19 @@ func main() {
|
||||
}
|
||||
atomic.AddUint64(resCounter[name], uint64(len(res)))
|
||||
if *scanThreshold != 0 && int(*resCounter[name]) > *scanThreshold {
|
||||
log.WithField("scanner", name).Errorf("exceeded result threshold of %d", *scanThreshold)
|
||||
logger.Error(
|
||||
fmt.Errorf("exceeded result threshold"), "snifftest failed",
|
||||
"scanner", name, "threshold", *scanThreshold,
|
||||
)
|
||||
failed = true
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if *scanPrintRes {
|
||||
for _, r := range res {
|
||||
logger := log.WithField("secret", name).WithField("meta", chunk.SourceMetadata).WithField("result", string(r.Raw))
|
||||
logger := logger.WithValues("secret", name, "meta", chunk.SourceMetadata, "result", string(r.Raw))
|
||||
if *scanPrintChunkRes {
|
||||
logger = logger.WithField("chunk", string(decoded.Data))
|
||||
logger = logger.WithValues("chunk", string(decoded.Data))
|
||||
}
|
||||
logger.Info("result")
|
||||
}
|
||||
@@ -156,18 +173,20 @@ func main() {
|
||||
}
|
||||
|
||||
for _, repo := range strings.Split(*scanCmdRepo, ",") {
|
||||
sem.Acquire(ctx, 1)
|
||||
if err := sem.Acquire(ctx, 1); err != nil {
|
||||
logFatal(err, "timed out waiting for semaphore")
|
||||
}
|
||||
wgChunkers.Add(1)
|
||||
go func(r string) {
|
||||
defer sem.Release(1)
|
||||
defer wgChunkers.Done()
|
||||
log.Infof("cloning %s", r)
|
||||
logger.Info("cloning repo", "repo", r)
|
||||
path, repo, err := git.CloneRepoUsingUnauthenticated(ctx, r)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
logFatal(err, "error cloning repo", "repo", r)
|
||||
}
|
||||
|
||||
log.Infof("cloned %s", r)
|
||||
logger.Info("cloned repo", "repo", r)
|
||||
|
||||
s := git.NewGit(sourcespb.SourceType_SOURCE_TYPE_GIT, 0, 0, "snifftest", false, runtime.NumCPU(),
|
||||
func(file, email, commit, timestamp, repository string, line int64) *source_metadatapb.MetaData {
|
||||
@@ -184,12 +203,12 @@ func main() {
|
||||
}
|
||||
})
|
||||
|
||||
log.Infof("scanning %s", r)
|
||||
logger.Info("scanning repo", "repo", r)
|
||||
err = s.ScanRepo(ctx, repo, path, git.NewScanOptions(), chunksChan)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
logFatal(err, "error scanning repo")
|
||||
}
|
||||
log.Infof("scanned %s", r)
|
||||
logger.Info("scanned repo", "repo", r)
|
||||
defer os.RemoveAll(path)
|
||||
}(repo)
|
||||
}
|
||||
@@ -201,9 +220,9 @@ func main() {
|
||||
|
||||
wgScanners.Wait()
|
||||
|
||||
log.WithField("chunks", chunkCounter).Info("completed")
|
||||
logger.Info("completed snifftest", "chunks", chunkCounter)
|
||||
for scanner, resultsCount := range resCounter {
|
||||
log.WithField("results", *resultsCount).Info(scanner)
|
||||
logger.Info(scanner, "results", *resultsCount)
|
||||
}
|
||||
|
||||
if failed {
|
||||
|
||||
@@ -12,16 +12,18 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/felixge/fgprof"
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/jpillora/overseer"
|
||||
"github.com/sirupsen/logrus"
|
||||
"gopkg.in/alecthomas/kingpin.v2"
|
||||
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/common"
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/config"
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/context"
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/decoders"
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/engine"
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/handlers"
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/log"
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/output"
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/sources"
|
||||
@@ -31,26 +33,35 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
cli = kingpin.New("TruffleHog", "TruffleHog is a tool for finding credentials.")
|
||||
cmd string
|
||||
debug = cli.Flag("debug", "Run in debug mode.").Bool()
|
||||
trace = cli.Flag("trace", "Run in trace mode.").Bool()
|
||||
jsonOut = cli.Flag("json", "Output in JSON format.").Short('j').Bool()
|
||||
jsonLegacy = cli.Flag("json-legacy", "Use the pre-v3.0 JSON format. Only works with git, gitlab, and github sources.").Bool()
|
||||
concurrency = cli.Flag("concurrency", "Number of concurrent workers.").Default(strconv.Itoa(runtime.NumCPU())).Int()
|
||||
noVerification = cli.Flag("no-verification", "Don't verify the results.").Bool()
|
||||
onlyVerified = cli.Flag("only-verified", "Only output verified results.").Bool()
|
||||
filterUnverified = cli.Flag("filter-unverified", "Only output first unverified result per chunk per detector if there are more than one results.").Bool()
|
||||
configFilename = cli.Flag("config", "Path to configuration file.").ExistingFile()
|
||||
cli = kingpin.New("TruffleHog", "TruffleHog is a tool for finding credentials.")
|
||||
cmd string
|
||||
debug = cli.Flag("debug", "Run in debug mode.").Bool()
|
||||
trace = cli.Flag("trace", "Run in trace mode.").Bool()
|
||||
profile = cli.Flag("profile", "Enables profiling and sets a pprof and fgprof server on :18066.").Bool()
|
||||
jsonOut = cli.Flag("json", "Output in JSON format.").Short('j').Bool()
|
||||
jsonLegacy = cli.Flag("json-legacy", "Use the pre-v3.0 JSON format. Only works with git, gitlab, and github sources.").Bool()
|
||||
gitHubActionsFormat = cli.Flag("github-actions", "Output in GitHub Actions format.").Bool()
|
||||
concurrency = cli.Flag("concurrency", "Number of concurrent workers.").Default(strconv.Itoa(runtime.NumCPU())).Int()
|
||||
noVerification = cli.Flag("no-verification", "Don't verify the results.").Bool()
|
||||
onlyVerified = cli.Flag("only-verified", "Only output verified results.").Bool()
|
||||
filterUnverified = cli.Flag("filter-unverified", "Only output first unverified result per chunk per detector if there are more than one results.").Bool()
|
||||
configFilename = cli.Flag("config", "Path to configuration file.").ExistingFile()
|
||||
// rules = cli.Flag("rules", "Path to file with custom rules.").String()
|
||||
printAvgDetectorTime = cli.Flag("print-avg-detector-time", "Print the average time spent on each detector.").Bool()
|
||||
noUpdate = cli.Flag("no-update", "Don't check for updates.").Bool()
|
||||
fail = cli.Flag("fail", "Exit with code 183 if results are found.").Bool()
|
||||
verifiers = cli.Flag("verifier", "Set custom verification endpoints.").StringMap()
|
||||
archiveMaxSize = cli.Flag("archive-max-size", "Maximum size of archive to scan. (Byte units eg. 512B, 2KB, 4MB)").Bytes()
|
||||
archiveMaxDepth = cli.Flag("archive-max-depth", "Maximum depth of archive to scan.").Int()
|
||||
archiveTimeout = cli.Flag("archive-timeout", "Maximum time to spend extracting an archive.").Duration()
|
||||
includeDetectors = cli.Flag("include-detectors", "Comma separated list of detector types to include. Protobuf name or IDs may be used, as well as ranges.").Default("all").String()
|
||||
excludeDetectors = cli.Flag("exclude-detectors", "Comma separated list of detector types to exclude. Protobuf name or IDs may be used, as well as ranges. IDs defined here take precedence over the include list.").String()
|
||||
|
||||
gitScan = cli.Command("git", "Find credentials in git repositories.")
|
||||
gitScanURI = gitScan.Arg("uri", "Git repository URL. https://, file://, or ssh:// schema expected.").Required().String()
|
||||
gitScanIncludePaths = gitScan.Flag("include-paths", "Path to file with newline separated regexes for files to include in scan.").Short('i').String()
|
||||
gitScanExcludePaths = gitScan.Flag("exclude-paths", "Path to file with newline separated regexes for files to exclude in scan.").Short('x').String()
|
||||
gitScanExcludeGlobs = gitScan.Flag("exclude-globs", "Comma separated list of globs to exclude in scan. This option filters at the `git log` level, resulting in faster scans.").String()
|
||||
gitScanSinceCommit = gitScan.Flag("since-commit", "Commit to start scan from.").String()
|
||||
gitScanBranch = gitScan.Flag("branch", "Branch to scan.").String()
|
||||
gitScanMaxDepth = gitScan.Flag("max-depth", "Maximum depth of commits to scan.").Int()
|
||||
@@ -58,15 +69,17 @@ var (
|
||||
_ = gitScan.Flag("entropy", "No-op flag for backwards compat.").Bool()
|
||||
_ = gitScan.Flag("regex", "No-op flag for backwards compat.").Bool()
|
||||
|
||||
githubScan = cli.Command("github", "Find credentials in GitHub repositories.")
|
||||
githubScanEndpoint = githubScan.Flag("endpoint", "GitHub endpoint.").Default("https://api.github.com").String()
|
||||
githubScanRepos = githubScan.Flag("repo", `GitHub repository to scan. You can repeat this flag. Example: "https://github.com/dustin-decker/secretsandstuff"`).Strings()
|
||||
githubScanOrgs = githubScan.Flag("org", `GitHub organization to scan. You can repeat this flag. Example: "trufflesecurity"`).Strings()
|
||||
githubScanToken = githubScan.Flag("token", "GitHub token. Can be provided with environment variable GITHUB_TOKEN.").Envar("GITHUB_TOKEN").String()
|
||||
githubIncludeForks = githubScan.Flag("include-forks", "Include forks in scan.").Bool()
|
||||
githubIncludeMembers = githubScan.Flag("include-members", "Include organization member repositories in scan.").Bool()
|
||||
githubIncludeRepos = githubScan.Flag("include-repos", `Repositories to include in an org scan. This can also be a glob pattern. You can repeat this flag. Must use Github repo full name. Example: "trufflesecurity/trufflehog", "trufflesecurity/t*"`).Strings()
|
||||
githubExcludeRepos = githubScan.Flag("exclude-repos", `Repositories to exclude in an org scan. This can also be a glob pattern. You can repeat this flag. Must use Github repo full name. Example: "trufflesecurity/driftwood", "trufflesecurity/d*"`).Strings()
|
||||
githubScan = cli.Command("github", "Find credentials in GitHub repositories.")
|
||||
githubScanEndpoint = githubScan.Flag("endpoint", "GitHub endpoint.").Default("https://api.github.com").String()
|
||||
githubScanRepos = githubScan.Flag("repo", `GitHub repository to scan. You can repeat this flag. Example: "https://github.com/dustin-decker/secretsandstuff"`).Strings()
|
||||
githubScanOrgs = githubScan.Flag("org", `GitHub organization to scan. You can repeat this flag. Example: "trufflesecurity"`).Strings()
|
||||
githubScanToken = githubScan.Flag("token", "GitHub token. Can be provided with environment variable GITHUB_TOKEN.").Envar("GITHUB_TOKEN").String()
|
||||
githubIncludeForks = githubScan.Flag("include-forks", "Include forks in scan.").Bool()
|
||||
githubIncludeMembers = githubScan.Flag("include-members", "Include organization member repositories in scan.").Bool()
|
||||
githubIncludeRepos = githubScan.Flag("include-repos", `Repositories to include in an org scan. This can also be a glob pattern. You can repeat this flag. Must use Github repo full name. Example: "trufflesecurity/trufflehog", "trufflesecurity/t*"`).Strings()
|
||||
githubExcludeRepos = githubScan.Flag("exclude-repos", `Repositories to exclude in an org scan. This can also be a glob pattern. You can repeat this flag. Must use Github repo full name. Example: "trufflesecurity/driftwood", "trufflesecurity/d*"`).Strings()
|
||||
githubScanIncludePaths = githubScan.Flag("include-paths", "Path to file with newline separated regexes for files to include in scan.").Short('i').String()
|
||||
githubScanExcludePaths = githubScan.Flag("exclude-paths", "Path to file with newline separated regexes for files to exclude in scan.").Short('x').String()
|
||||
|
||||
gitlabScan = cli.Command("gitlab", "Find credentials in GitLab repositories.")
|
||||
// TODO: Add more GitLab options
|
||||
@@ -76,18 +89,33 @@ var (
|
||||
gitlabScanIncludePaths = gitlabScan.Flag("include-paths", "Path to file with newline separated regexes for files to include in scan.").Short('i').String()
|
||||
gitlabScanExcludePaths = gitlabScan.Flag("exclude-paths", "Path to file with newline separated regexes for files to exclude in scan.").Short('x').String()
|
||||
|
||||
filesystemScan = cli.Command("filesystem", "Find credentials in a filesystem.")
|
||||
filesystemDirectories = filesystemScan.Flag("directory", "Path to directory to scan. You can repeat this flag.").Required().Strings()
|
||||
filesystemScan = cli.Command("filesystem", "Find credentials in a filesystem.")
|
||||
filesystemPaths = filesystemScan.Arg("path", "Path to file or directory to scan.").Strings()
|
||||
// DEPRECATED: --directory is deprecated in favor of arguments.
|
||||
filesystemDirectories = filesystemScan.Flag("directory", "Path to directory to scan. You can repeat this flag.").Strings()
|
||||
// TODO: Add more filesystem scan options. Currently only supports scanning a list of directories.
|
||||
// filesystemScanRecursive = filesystemScan.Flag("recursive", "Scan recursively.").Short('r').Bool()
|
||||
// filesystemScanIncludePaths = filesystemScan.Flag("include-paths", "Path to file with newline separated regexes for files to include in scan.").Short('i').String()
|
||||
// filesystemScanExcludePaths = filesystemScan.Flag("exclude-paths", "Path to file with newline separated regexes for files to exclude in scan.").Short('x').String()
|
||||
filesystemScanIncludePaths = filesystemScan.Flag("include-paths", "Path to file with newline separated regexes for files to include in scan.").Short('i').String()
|
||||
filesystemScanExcludePaths = filesystemScan.Flag("exclude-paths", "Path to file with newline separated regexes for files to exclude in scan.").Short('x').String()
|
||||
|
||||
s3Scan = cli.Command("s3", "Find credentials in S3 buckets.")
|
||||
s3ScanKey = s3Scan.Flag("key", "S3 key used to authenticate. Can be provided with environment variable AWS_ACCESS_KEY_ID.").Envar("AWS_ACCESS_KEY_ID").String()
|
||||
s3ScanSecret = s3Scan.Flag("secret", "S3 secret used to authenticate. Can be provided with environment variable AWS_SECRET_ACCESS_KEY.").Envar("AWS_SECRET_ACCESS_KEY").String()
|
||||
s3ScanCloudEnv = s3Scan.Flag("cloud-environment", "Use IAM credentials in cloud environment.").Bool()
|
||||
s3ScanBuckets = s3Scan.Flag("bucket", "Name of S3 bucket to scan. You can repeat this flag.").Strings()
|
||||
s3Scan = cli.Command("s3", "Find credentials in S3 buckets.")
|
||||
s3ScanKey = s3Scan.Flag("key", "S3 key used to authenticate. Can be provided with environment variable AWS_ACCESS_KEY_ID.").Envar("AWS_ACCESS_KEY_ID").String()
|
||||
s3ScanSecret = s3Scan.Flag("secret", "S3 secret used to authenticate. Can be provided with environment variable AWS_SECRET_ACCESS_KEY.").Envar("AWS_SECRET_ACCESS_KEY").String()
|
||||
s3ScanSessionToken = s3Scan.Flag("session-token", "S3 session token used to authenticate temporary credentials. Can be provided with environment variable AWS_SESSION_TOKEN.").Envar("AWS_SESSION_TOKEN").String()
|
||||
s3ScanCloudEnv = s3Scan.Flag("cloud-environment", "Use IAM credentials in cloud environment.").Bool()
|
||||
s3ScanBuckets = s3Scan.Flag("bucket", "Name of S3 bucket to scan. You can repeat this flag.").Strings()
|
||||
|
||||
gcsScan = cli.Command("gcs", "Find credentials in GCS buckets.")
|
||||
gcsProjectID = gcsScan.Flag("project-id", "GCS project ID used to authenticate. Can NOT be used with unauth scan. Can be provided with environment variable GOOGLE_CLOUD_PROJECT.").Envar("GOOGLE_CLOUD_PROJECT").String()
|
||||
gcsCloudEnv = gcsScan.Flag("cloud-environment", "Use Application Default Credentials, IAM credentials to authenticate.").Bool()
|
||||
gcsServiceAccount = gcsScan.Flag("service-account", "Path to GCS service account JSON file.").ExistingFile()
|
||||
gcsWithoutAuth = gcsScan.Flag("without-auth", "Scan GCS buckets without authentication. This will only work for public buckets").Bool()
|
||||
gcsAPIKey = gcsScan.Flag("api-key", "GCS API key used to authenticate. Can be provided with environment variable GOOGLE_API_KEY.").Envar("GOOGLE_API_KEY").String()
|
||||
gcsIncludeBuckets = gcsScan.Flag("include-buckets", "Buckets to scan. Comma seperated list of buckets. You can repeat this flag. Globs are supported").Short('I').Strings()
|
||||
gcsExcludeBuckets = gcsScan.Flag("exclude-buckets", "Buckets to exclude from scan. Comma separated list of buckets. Globs are supported").Short('X').Strings()
|
||||
gcsIncludeObjects = gcsScan.Flag("include-objects", "Objects to scan. Comma separated list of objects. you can repeat this flag. Globs are supported").Short('i').Strings()
|
||||
gcsExcludeObjects = gcsScan.Flag("exclude-objects", "Objects to exclude from scan. Comma separated list of objects. You can repeat this flag. Globs are supported").Short('x').Strings()
|
||||
gcsMaxObjectSize = gcsScan.Flag("max-object-size", "Maximum size of objects to scan. Objects larger than this will be skipped. (Byte units eg. 512B, 2KB, 4MB)").Default("10MB").Bytes()
|
||||
|
||||
syslogScan = cli.Command("syslog", "Scan syslog")
|
||||
syslogAddress = syslogScan.Flag("address", "Address and port to listen on for syslog. Example: 127.0.0.1:514").String()
|
||||
@@ -112,24 +140,26 @@ func init() {
|
||||
cli.Version("trufflehog " + version.BuildVersion)
|
||||
cmd = kingpin.MustParse(cli.Parse(os.Args[1:]))
|
||||
|
||||
if *jsonOut {
|
||||
logrus.SetFormatter(&logrus.JSONFormatter{})
|
||||
}
|
||||
switch {
|
||||
case *trace:
|
||||
log.SetLevel(5)
|
||||
logrus.SetLevel(logrus.TraceLevel)
|
||||
logrus.Debugf("running version %s", version.BuildVersion)
|
||||
case *debug:
|
||||
log.SetLevel(2)
|
||||
logrus.SetLevel(logrus.DebugLevel)
|
||||
logrus.Debugf("running version %s", version.BuildVersion)
|
||||
default:
|
||||
logrus.SetLevel(logrus.InfoLevel)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
// setup logger
|
||||
logFormat := log.WithConsoleSink
|
||||
if *jsonOut {
|
||||
logFormat = log.WithJSONSink
|
||||
}
|
||||
logger, sync := log.New("trufflehog", logFormat(os.Stderr))
|
||||
// make it the default logger for contexts
|
||||
context.SetDefaultLogger(logger)
|
||||
defer func() { _ = sync() }()
|
||||
logFatal := logFatalFunc(logger)
|
||||
|
||||
updateCfg := overseer.Config{
|
||||
Program: run,
|
||||
Debug: *debug,
|
||||
@@ -147,14 +177,16 @@ func main() {
|
||||
|
||||
err := overseer.RunErr(updateCfg)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("error occured with trufflehog updater 🐷")
|
||||
logFatal(err, "error occured with trufflehog updater 🐷")
|
||||
}
|
||||
}
|
||||
|
||||
func run(state overseer.State) {
|
||||
if *debug {
|
||||
logrus.Debugf("trufflehog %s", version.BuildVersion)
|
||||
}
|
||||
ctx := context.Background()
|
||||
logger := ctx.Logger()
|
||||
logFatal := logFatalFunc(logger)
|
||||
|
||||
logger.V(2).Info(fmt.Sprintf("trufflehog %s", version.BuildVersion))
|
||||
|
||||
if *githubScanToken != "" {
|
||||
// NOTE: this kludge is here to do an authenticated shallow commit
|
||||
@@ -167,138 +199,244 @@ func run(state overseer.State) {
|
||||
*concurrency = 1
|
||||
}
|
||||
|
||||
if *debug {
|
||||
if *profile {
|
||||
go func() {
|
||||
router := mux.NewRouter()
|
||||
router.PathPrefix("/debug/pprof").Handler(http.DefaultServeMux)
|
||||
router.PathPrefix("/debug/fgprof").Handler(fgprof.Handler())
|
||||
logrus.Info("starting pprof and fgprof server on :18066 /debug/pprof and /debug/fgprof")
|
||||
logger.Info("starting pprof and fgprof server on :18066 /debug/pprof and /debug/fgprof")
|
||||
if err := http.ListenAndServe(":18066", router); err != nil {
|
||||
logrus.Error(err)
|
||||
logger.Error(err, "error serving pprof and fgprof")
|
||||
}
|
||||
}()
|
||||
}
|
||||
logger, sync := log.New("trufflehog", log.WithConsoleSink(os.Stderr))
|
||||
context.SetDefaultLogger(logger)
|
||||
defer func() { _ = sync() }()
|
||||
|
||||
conf := &config.Config{}
|
||||
if *configFilename != "" {
|
||||
var err error
|
||||
conf, err = config.Read(*configFilename)
|
||||
if err != nil {
|
||||
logger.Error(err, "error parsing the provided configuration file")
|
||||
os.Exit(1)
|
||||
logFatal(err, "error parsing the provided configuration file")
|
||||
}
|
||||
}
|
||||
|
||||
ctx := context.TODO()
|
||||
urls := splitVerifierURLs(*verifiers)
|
||||
|
||||
if *archiveMaxSize != 0 {
|
||||
handlers.SetArchiveMaxSize(int(*archiveMaxSize))
|
||||
}
|
||||
if *archiveMaxDepth != 0 {
|
||||
handlers.SetArchiveMaxDepth(*archiveMaxDepth)
|
||||
}
|
||||
if *archiveTimeout != 0 {
|
||||
handlers.SetArchiveMaxTimeout(*archiveTimeout)
|
||||
}
|
||||
|
||||
// Build include and exclude detector sets for filtering on engine initialization.
|
||||
var includeDetectorSet, excludeDetectorSet map[config.DetectorID]struct{}
|
||||
{
|
||||
includeList, err := config.ParseDetectors(*includeDetectors)
|
||||
if err != nil {
|
||||
// Exit if there was an error to inform the user of the misconfiguration.
|
||||
logFatal(err, "invalid include list detector configuration")
|
||||
}
|
||||
excludeList, err := config.ParseDetectors(*excludeDetectors)
|
||||
if err != nil {
|
||||
// Exit if there was an error to inform the user of the misconfiguration.
|
||||
logFatal(err, "invalid exclude list detector configuration")
|
||||
}
|
||||
includeDetectorSet = detectorTypeToSet(includeList)
|
||||
excludeDetectorSet = detectorTypeToSet(excludeList)
|
||||
}
|
||||
|
||||
// Verify that all the user-provided detectors support the optional
|
||||
// detector features.
|
||||
{
|
||||
isVersioner := engine.DefaultDetectorTypesImplementing[detectors.Versioner]()
|
||||
for id := range includeDetectorSet {
|
||||
if id.Version == 0 {
|
||||
// Version not provided.
|
||||
continue
|
||||
}
|
||||
if _, ok := isVersioner[id.ID]; ok {
|
||||
// Version provided for a Versioner detector.
|
||||
continue
|
||||
}
|
||||
// Version provided on a non-Versioner detector.
|
||||
logFatal(
|
||||
fmt.Errorf("version provided but detector does not have a version"),
|
||||
"invalid include list detector configuration",
|
||||
"detector", id,
|
||||
)
|
||||
}
|
||||
for id := range excludeDetectorSet {
|
||||
if id.Version == 0 {
|
||||
// Version not provided.
|
||||
continue
|
||||
}
|
||||
if _, ok := isVersioner[id.ID]; ok {
|
||||
// Version provided for a Versioner detector.
|
||||
continue
|
||||
}
|
||||
// Version provided on a non-Versioner detector.
|
||||
logFatal(
|
||||
fmt.Errorf("version provided but detector does not have a version"),
|
||||
"invalid exclude list detector configuration",
|
||||
"detector", id,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
includeFilter := func(d detectors.Detector) bool {
|
||||
_, ok := getWithDetectorID(d, includeDetectorSet)
|
||||
return ok
|
||||
}
|
||||
excludeFilter := func(d detectors.Detector) bool {
|
||||
_, ok := getWithDetectorID(d, excludeDetectorSet)
|
||||
return !ok
|
||||
}
|
||||
|
||||
e := engine.Start(ctx,
|
||||
engine.WithConcurrency(*concurrency),
|
||||
engine.WithDecoders(decoders.DefaultDecoders()...),
|
||||
engine.WithDetectors(!*noVerification, engine.DefaultDetectors()...),
|
||||
engine.WithDetectors(!*noVerification, engine.CustomDetectors(ctx, urls)...),
|
||||
engine.WithDetectors(!*noVerification, conf.Detectors...),
|
||||
engine.WithFilterDetectors(includeFilter),
|
||||
engine.WithFilterDetectors(excludeFilter),
|
||||
engine.WithFilterUnverified(*filterUnverified),
|
||||
)
|
||||
|
||||
filter, err := common.FilterFromFiles(*gitScanIncludePaths, *gitScanExcludePaths)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("could not create filter")
|
||||
}
|
||||
|
||||
var repoPath string
|
||||
var remote bool
|
||||
switch cmd {
|
||||
case gitScan.FullCommand():
|
||||
filter, err := common.FilterFromFiles(*gitScanIncludePaths, *gitScanExcludePaths)
|
||||
if err != nil {
|
||||
logFatal(err, "could not create filter")
|
||||
}
|
||||
repoPath, remote, err = git.PrepareRepoSinceCommit(ctx, *gitScanURI, *gitScanSinceCommit)
|
||||
if err != nil || repoPath == "" {
|
||||
logrus.WithError(err).Fatal("error preparing git repo for scanning")
|
||||
logFatal(err, "error preparing git repo for scanning")
|
||||
}
|
||||
if remote {
|
||||
defer os.RemoveAll(repoPath)
|
||||
}
|
||||
|
||||
g := func(c *sources.Config) {
|
||||
c.RepoPath = repoPath
|
||||
c.HeadRef = *gitScanBranch
|
||||
c.BaseRef = *gitScanSinceCommit
|
||||
c.MaxDepth = *gitScanMaxDepth
|
||||
c.Filter = filter
|
||||
excludedGlobs := []string{}
|
||||
if *gitScanExcludeGlobs != "" {
|
||||
excludedGlobs = strings.Split(*gitScanExcludeGlobs, ",")
|
||||
}
|
||||
|
||||
if err = e.ScanGit(ctx, sources.NewConfig(g)); err != nil {
|
||||
logrus.WithError(err).Fatal("Failed to scan Git.")
|
||||
cfg := sources.GitConfig{
|
||||
RepoPath: repoPath,
|
||||
HeadRef: *gitScanBranch,
|
||||
BaseRef: *gitScanSinceCommit,
|
||||
MaxDepth: *gitScanMaxDepth,
|
||||
Filter: filter,
|
||||
ExcludeGlobs: excludedGlobs,
|
||||
}
|
||||
if err = e.ScanGit(ctx, cfg); err != nil {
|
||||
logFatal(err, "Failed to scan Git.")
|
||||
}
|
||||
case githubScan.FullCommand():
|
||||
filter, err := common.FilterFromFiles(*githubScanIncludePaths, *githubScanExcludePaths)
|
||||
if err != nil {
|
||||
logFatal(err, "could not create filter")
|
||||
}
|
||||
if len(*githubScanOrgs) == 0 && len(*githubScanRepos) == 0 {
|
||||
logrus.Fatal("You must specify at least one organization or repository.")
|
||||
logFatal(fmt.Errorf("invalid config"), "You must specify at least one organization or repository.")
|
||||
}
|
||||
|
||||
github := func(c *sources.Config) {
|
||||
c.Endpoint = *githubScanEndpoint
|
||||
c.Repos = *githubScanRepos
|
||||
c.Orgs = *githubScanOrgs
|
||||
c.Token = *githubScanToken
|
||||
c.IncludeForks = *githubIncludeForks
|
||||
c.IncludeMembers = *githubIncludeMembers
|
||||
c.Concurrency = *concurrency
|
||||
c.ExcludeRepos = *githubExcludeRepos
|
||||
c.IncludeRepos = *githubIncludeRepos
|
||||
cfg := sources.GithubConfig{
|
||||
Endpoint: *githubScanEndpoint,
|
||||
Token: *githubScanToken,
|
||||
IncludeForks: *githubIncludeForks,
|
||||
IncludeMembers: *githubIncludeMembers,
|
||||
Concurrency: *concurrency,
|
||||
ExcludeRepos: *githubExcludeRepos,
|
||||
IncludeRepos: *githubIncludeRepos,
|
||||
Repos: *githubScanRepos,
|
||||
Orgs: *githubScanOrgs,
|
||||
Filter: filter,
|
||||
}
|
||||
|
||||
if err = e.ScanGitHub(ctx, sources.NewConfig(github)); err != nil {
|
||||
logrus.WithError(err).Fatal("Failed to scan Github.")
|
||||
if err := e.ScanGitHub(ctx, cfg); err != nil {
|
||||
logFatal(err, "Failed to scan Github.")
|
||||
}
|
||||
case gitlabScan.FullCommand():
|
||||
filter, err := common.FilterFromFiles(*gitlabScanIncludePaths, *gitlabScanExcludePaths)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Fatal("could not create filter")
|
||||
logFatal(err, "could not create filter")
|
||||
}
|
||||
|
||||
gitlab := func(c *sources.Config) {
|
||||
c.Endpoint = *gitlabScanEndpoint
|
||||
c.Token = *gitlabScanToken
|
||||
c.Repos = *gitlabScanRepos
|
||||
c.Filter = filter
|
||||
cfg := sources.GitlabConfig{
|
||||
Endpoint: *gitlabScanEndpoint,
|
||||
Token: *gitlabScanToken,
|
||||
Repos: *gitlabScanRepos,
|
||||
Filter: filter,
|
||||
}
|
||||
|
||||
if err = e.ScanGitLab(ctx, sources.NewConfig(gitlab)); err != nil {
|
||||
logrus.WithError(err).Fatal("Failed to scan GitLab.")
|
||||
if err := e.ScanGitLab(ctx, cfg); err != nil {
|
||||
logFatal(err, "Failed to scan GitLab.")
|
||||
}
|
||||
case filesystemScan.FullCommand():
|
||||
fs := func(c *sources.Config) {
|
||||
c.Directories = *filesystemDirectories
|
||||
filter, err := common.FilterFromFiles(*filesystemScanIncludePaths, *filesystemScanExcludePaths)
|
||||
if err != nil {
|
||||
logFatal(err, "could not create filter")
|
||||
}
|
||||
|
||||
if err = e.ScanFileSystem(ctx, sources.NewConfig(fs)); err != nil {
|
||||
logrus.WithError(err).Fatal("Failed to scan filesystem")
|
||||
if len(*filesystemDirectories) > 0 {
|
||||
ctx.Logger().Info("--directory flag is deprecated, please pass directories as arguments")
|
||||
}
|
||||
paths := make([]string, 0, len(*filesystemPaths)+len(*filesystemDirectories))
|
||||
paths = append(paths, *filesystemPaths...)
|
||||
paths = append(paths, *filesystemDirectories...)
|
||||
cfg := sources.FilesystemConfig{
|
||||
Paths: paths,
|
||||
Filter: filter,
|
||||
}
|
||||
if err = e.ScanFileSystem(ctx, cfg); err != nil {
|
||||
logFatal(err, "Failed to scan filesystem")
|
||||
}
|
||||
case s3Scan.FullCommand():
|
||||
s3 := func(c *sources.Config) {
|
||||
c.Key = *s3ScanKey
|
||||
c.Secret = *s3ScanSecret
|
||||
c.Buckets = *s3ScanBuckets
|
||||
cfg := sources.S3Config{
|
||||
Key: *s3ScanKey,
|
||||
Secret: *s3ScanSecret,
|
||||
SessionToken: *s3ScanSessionToken,
|
||||
Buckets: *s3ScanBuckets,
|
||||
CloudCred: *s3ScanCloudEnv,
|
||||
}
|
||||
|
||||
if err = e.ScanS3(ctx, sources.NewConfig(s3)); err != nil {
|
||||
logrus.WithError(err).Fatal("Failed to scan S3.")
|
||||
if err := e.ScanS3(ctx, cfg); err != nil {
|
||||
logFatal(err, "Failed to scan S3.")
|
||||
}
|
||||
case syslogScan.FullCommand():
|
||||
syslog := func(c *sources.Config) {
|
||||
c.Address = *syslogAddress
|
||||
c.Protocol = *syslogProtocol
|
||||
c.CertPath = *syslogTLSCert
|
||||
c.KeyPath = *syslogTLSKey
|
||||
c.Format = *syslogFormat
|
||||
c.Concurrency = *concurrency
|
||||
cfg := sources.SyslogConfig{
|
||||
Address: *syslogAddress,
|
||||
Format: *syslogFormat,
|
||||
Protocol: *syslogProtocol,
|
||||
CertPath: *syslogTLSCert,
|
||||
KeyPath: *syslogTLSKey,
|
||||
Concurrency: *concurrency,
|
||||
}
|
||||
|
||||
if err = e.ScanSyslog(ctx, sources.NewConfig(syslog)); err != nil {
|
||||
logrus.WithError(err).Fatal("Failed to scan syslog.")
|
||||
if err := e.ScanSyslog(ctx, cfg); err != nil {
|
||||
logFatal(err, "Failed to scan syslog.")
|
||||
}
|
||||
case circleCiScan.FullCommand():
|
||||
if err = e.ScanCircleCI(ctx, *circleCiScanToken); err != nil {
|
||||
logrus.WithError(err).Fatal("Failed to scan CircleCI.")
|
||||
if err := e.ScanCircleCI(ctx, *circleCiScanToken); err != nil {
|
||||
logFatal(err, "Failed to scan CircleCI.")
|
||||
}
|
||||
case gcsScan.FullCommand():
|
||||
cfg := sources.GCSConfig{
|
||||
ProjectID: *gcsProjectID,
|
||||
CloudCred: *gcsCloudEnv,
|
||||
ServiceAccount: *gcsServiceAccount,
|
||||
WithoutAuth: *gcsWithoutAuth,
|
||||
ApiKey: *gcsAPIKey,
|
||||
IncludeBuckets: commaSeperatedToSlice(*gcsIncludeBuckets),
|
||||
ExcludeBuckets: commaSeperatedToSlice(*gcsExcludeBuckets),
|
||||
IncludeObjects: commaSeperatedToSlice(*gcsIncludeObjects),
|
||||
ExcludeObjects: commaSeperatedToSlice(*gcsExcludeObjects),
|
||||
Concurrency: *concurrency,
|
||||
MaxObjectSize: int64(*gcsMaxObjectSize),
|
||||
}
|
||||
if err := e.ScanGCS(ctx, cfg); err != nil {
|
||||
logFatal(err, "Failed to scan GCS.")
|
||||
}
|
||||
}
|
||||
// asynchronously wait for scanning to finish and cleanup
|
||||
@@ -317,28 +455,50 @@ func run(state overseer.State) {
|
||||
}
|
||||
foundResults = true
|
||||
|
||||
var err error
|
||||
switch {
|
||||
case *jsonLegacy:
|
||||
output.PrintLegacyJSON(ctx, &r)
|
||||
err = output.PrintLegacyJSON(ctx, &r)
|
||||
case *jsonOut:
|
||||
output.PrintJSON(&r)
|
||||
err = output.PrintJSON(&r)
|
||||
case *gitHubActionsFormat:
|
||||
err = output.PrintGitHubActionsOutput(&r)
|
||||
default:
|
||||
output.PrintPlainOutput(&r)
|
||||
err = output.PrintPlainOutput(&r)
|
||||
}
|
||||
if err != nil {
|
||||
logFatal(err, "error printing results")
|
||||
}
|
||||
}
|
||||
logrus.Debugf("scanned %d chunks", e.ChunksScanned())
|
||||
logrus.Debugf("scanned %d bytes", e.BytesScanned())
|
||||
logger.V(2).Info("finished scanning",
|
||||
"chunks", e.ChunksScanned(),
|
||||
"bytes", e.BytesScanned(),
|
||||
)
|
||||
|
||||
if *printAvgDetectorTime {
|
||||
printAverageDetectorTime(e)
|
||||
}
|
||||
|
||||
if foundResults && *fail {
|
||||
logrus.Debug("exiting with code 183 because results were found")
|
||||
logger.V(2).Info("exiting with code 183 because results were found")
|
||||
os.Exit(183)
|
||||
}
|
||||
}
|
||||
|
||||
func commaSeperatedToSlice(s []string) []string {
|
||||
var result []string
|
||||
for _, items := range s {
|
||||
for _, item := range strings.Split(items, ",") {
|
||||
item = strings.TrimSpace(item)
|
||||
if item == "" {
|
||||
continue
|
||||
}
|
||||
result = append(result, item)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func printAverageDetectorTime(e *engine.Engine) {
|
||||
fmt.Fprintln(os.Stderr, "Average detector time is the measurement of average time spent on each detector when results are returned.")
|
||||
for detectorName, durations := range e.DetectorAvgTime() {
|
||||
@@ -350,3 +510,54 @@ func printAverageDetectorTime(e *engine.Engine) {
|
||||
fmt.Fprintf(os.Stderr, "%s: %s\n", detectorName, avgDuration)
|
||||
}
|
||||
}
|
||||
|
||||
func splitVerifierURLs(verifierURLs map[string]string) map[string][]string {
|
||||
verifiers := make(map[string][]string, len(verifierURLs))
|
||||
for k, v := range verifierURLs {
|
||||
key := strings.ToLower(k)
|
||||
sliceOfValues := strings.Split(v, ",")
|
||||
for i, s := range sliceOfValues {
|
||||
sliceOfValues[i] = strings.TrimSpace(s)
|
||||
}
|
||||
verifiers[key] = sliceOfValues
|
||||
}
|
||||
return verifiers
|
||||
}
|
||||
|
||||
// logFatalFunc returns a log.Fatal style function. Calling the returned
|
||||
// function will terminate the program without cleanup.
|
||||
func logFatalFunc(logger logr.Logger) func(error, string, ...any) {
|
||||
return func(err error, message string, keyAndVals ...any) {
|
||||
logger.Error(err, message, keyAndVals...)
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
return
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
|
||||
// detectorTypeToSet is a helper function to convert a slice of detector IDs into a set.
|
||||
func detectorTypeToSet(detectors []config.DetectorID) map[config.DetectorID]struct{} {
|
||||
output := make(map[config.DetectorID]struct{}, len(detectors))
|
||||
for _, d := range detectors {
|
||||
output[d] = struct{}{}
|
||||
}
|
||||
return output
|
||||
}
|
||||
|
||||
// getWithDetectorID is a helper function to get a value from a map using a
|
||||
// detector's ID. This function behaves like a normal map lookup, with an extra
|
||||
// step of checking for the non-specific version of a detector.
|
||||
func getWithDetectorID[T any](d detectors.Detector, data map[config.DetectorID]T) (T, bool) {
|
||||
key := config.GetDetectorID(d)
|
||||
// Check if the specific ID is provided.
|
||||
if t, ok := data[key]; ok || key.Version == 0 {
|
||||
return t, ok
|
||||
}
|
||||
// Check if the generic type is provided without a version.
|
||||
// This means "all" versions of a type.
|
||||
key.Version = 0
|
||||
t, ok := data[key]
|
||||
return t, ok
|
||||
}
|
||||
|
||||
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
// Package cache provides an interface which can be implemented by different cache types.
|
||||
package cache
|
||||
|
||||
// Cache is used to store key/value pairs.
|
||||
type Cache interface {
|
||||
// Set stores the given key/value pair.
|
||||
Set(string, string)
|
||||
// Get returns the value for the given key and a boolean indicating if the key was found.
|
||||
Get(string) (string, bool)
|
||||
// Exists returns true if the given key exists in the cache.
|
||||
Exists(string) bool
|
||||
// Delete the given key from the cache.
|
||||
Delete(string)
|
||||
// Clear all key/value pairs from the cache.
|
||||
Clear()
|
||||
// Count the number of key/value pairs in the cache.
|
||||
Count() int
|
||||
// Contents returns all keys in the cache encoded as a string.
|
||||
Contents() string
|
||||
}
|
||||
Vendored
+85
@@ -0,0 +1,85 @@
|
||||
package memory
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/patrickmn/go-cache"
|
||||
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/context"
|
||||
)
|
||||
|
||||
const (
|
||||
expirationInterval = 12 * time.Hour
|
||||
purgeInterval = 13 * time.Hour
|
||||
defaultExpiration = cache.DefaultExpiration
|
||||
)
|
||||
|
||||
// Cache is a wrapper around the go-cache library.
|
||||
type Cache struct {
|
||||
c *cache.Cache
|
||||
}
|
||||
|
||||
// New constructs a new in-memory cache.
|
||||
func New() *Cache {
|
||||
c := cache.New(expirationInterval, purgeInterval)
|
||||
return &Cache{c: c}
|
||||
}
|
||||
|
||||
// NewWithData constructs a new in-memory cache with existing data.
|
||||
func NewWithData(ctx context.Context, data []string) *Cache {
|
||||
ctx.Logger().V(3).Info("Loading cache", "num-items", len(data))
|
||||
|
||||
items := make(map[string]cache.Item, len(data))
|
||||
for _, d := range data {
|
||||
items[d] = cache.Item{Object: d, Expiration: int64(defaultExpiration)}
|
||||
}
|
||||
|
||||
c := cache.NewFrom(expirationInterval, purgeInterval, items)
|
||||
return &Cache{c: c}
|
||||
}
|
||||
|
||||
// Set adds a key-value pair to the cache.
|
||||
func (c *Cache) Set(key, value string) {
|
||||
c.c.Set(key, value, defaultExpiration)
|
||||
}
|
||||
|
||||
// Get returns the value for the given key.
|
||||
func (c *Cache) Get(key string) (string, bool) {
|
||||
res, ok := c.c.Get(key)
|
||||
if !ok {
|
||||
return "", ok
|
||||
}
|
||||
return res.(string), ok
|
||||
}
|
||||
|
||||
// Exists returns true if the given key exists in the cache.
|
||||
func (c *Cache) Exists(key string) bool {
|
||||
_, ok := c.c.Get(key)
|
||||
return ok
|
||||
}
|
||||
|
||||
// Delete removes the key-value pair from the cache.
|
||||
func (c *Cache) Delete(key string) {
|
||||
c.c.Delete(key)
|
||||
}
|
||||
|
||||
// Clear removes all key-value pairs from the cache.
|
||||
func (c *Cache) Clear() {
|
||||
c.c.Flush()
|
||||
}
|
||||
|
||||
// Count returns the number of key-value pairs in the cache.
|
||||
func (c *Cache) Count() int {
|
||||
return c.c.ItemCount()
|
||||
}
|
||||
|
||||
// Contents returns all key-value pairs in the cache encodes as a string.
|
||||
func (c *Cache) Contents() string {
|
||||
items := c.c.Items()
|
||||
res := make([]string, 0, len(items))
|
||||
for k := range items {
|
||||
res = append(res, k)
|
||||
}
|
||||
return strings.Join(res, ",")
|
||||
}
|
||||
Vendored
+153
@@ -0,0 +1,153 @@
|
||||
package memory
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
|
||||
logContext "github.com/trufflesecurity/trufflehog/v3/pkg/context"
|
||||
)
|
||||
|
||||
func TestCache(t *testing.T) {
|
||||
c := New()
|
||||
|
||||
// Test set and get.
|
||||
c.Set("key1", "key1")
|
||||
v, ok := c.Get("key1")
|
||||
if !ok || v != "key1" {
|
||||
t.Fatalf("Unexpected value for key1: %v, %v", v, ok)
|
||||
}
|
||||
|
||||
// Test exists.
|
||||
if !c.Exists("key1") {
|
||||
t.Fatalf("Expected key1 to exist")
|
||||
}
|
||||
|
||||
// Test the count.
|
||||
if c.Count() != 1 {
|
||||
t.Fatalf("Unexpected count: %d", c.Count())
|
||||
}
|
||||
|
||||
// Test delete.
|
||||
c.Delete("key1")
|
||||
v, ok = c.Get("key1")
|
||||
if ok || v != "" {
|
||||
t.Fatalf("Unexpected value for key1 after delete: %v, %v", v, ok)
|
||||
}
|
||||
|
||||
// Test clear.
|
||||
c.Set("key10", "key10")
|
||||
c.Clear()
|
||||
v, ok = c.Get("key10")
|
||||
if ok || v != "" {
|
||||
t.Fatalf("Unexpected value for key10 after clear: %v, %v", v, ok)
|
||||
}
|
||||
|
||||
// Test contents.
|
||||
keys := []string{"key1", "key2", "key3"}
|
||||
for _, k := range keys {
|
||||
c.Set(k, k)
|
||||
}
|
||||
|
||||
items := c.Contents()
|
||||
sort.Strings(keys)
|
||||
res := strings.Split(items, ",")
|
||||
sort.Strings(res)
|
||||
|
||||
if len(keys) != len(res) {
|
||||
t.Fatalf("Unexpected length of items: %d", len(res))
|
||||
}
|
||||
if !cmp.Equal(keys, res) {
|
||||
t.Fatalf("Unexpected items: %v", res)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCache_NewWithData(t *testing.T) {
|
||||
c := NewWithData(logContext.Background(), []string{"key1", "key2", "key3"})
|
||||
|
||||
// Test the count.
|
||||
if c.Count() != 3 {
|
||||
t.Fatalf("Unexpected count: %d", c.Count())
|
||||
}
|
||||
|
||||
// Test contents.
|
||||
keys := []string{"key1", "key2", "key3"}
|
||||
items := c.Contents()
|
||||
sort.Strings(keys)
|
||||
res := strings.Split(items, ",")
|
||||
sort.Strings(res)
|
||||
|
||||
if len(keys) != len(res) {
|
||||
t.Fatalf("Unexpected length of items: %d", len(res))
|
||||
}
|
||||
if !cmp.Equal(keys, res) {
|
||||
t.Fatalf("Unexpected items: %v", res)
|
||||
}
|
||||
}
|
||||
|
||||
func setupBenchmarks(b *testing.B) *Cache {
|
||||
b.Helper()
|
||||
|
||||
c := New()
|
||||
|
||||
for i := 0; i < 500_000; i++ {
|
||||
key := fmt.Sprintf("key%d", i)
|
||||
c.Set(key, key)
|
||||
}
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
func BenchmarkSet(b *testing.B) {
|
||||
c := New()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
key := fmt.Sprintf("key%d", i)
|
||||
c.Set(key, key)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkGet(b *testing.B) {
|
||||
c := setupBenchmarks(b)
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
key := fmt.Sprintf("key%d", i)
|
||||
c.Get(key)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkDelete(b *testing.B) {
|
||||
c := setupBenchmarks(b)
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
key := fmt.Sprintf("key%d", i)
|
||||
c.Delete(key)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCount(b *testing.B) {
|
||||
c := setupBenchmarks(b)
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
c.Count()
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkContents(b *testing.B) {
|
||||
c := setupBenchmarks(b)
|
||||
b.ResetTimer()
|
||||
|
||||
var s string
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
s = c.Contents()
|
||||
}
|
||||
|
||||
_ = s
|
||||
}
|
||||
+12
-4
@@ -6,7 +6,7 @@ import (
|
||||
"os"
|
||||
"regexp"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/context"
|
||||
)
|
||||
|
||||
type Filter struct {
|
||||
@@ -20,7 +20,8 @@ type FilterRuleSet []regexp.Regexp
|
||||
func FilterEmpty() *Filter {
|
||||
filter, err := FilterFromFiles("", "")
|
||||
if err != nil {
|
||||
log.WithError(err).Fatalf("could not create empty filter")
|
||||
context.Background().Logger().Error(err, "could not create empty filter")
|
||||
os.Exit(1)
|
||||
}
|
||||
return filter
|
||||
}
|
||||
@@ -57,15 +58,19 @@ func FilterRulesFromFile(source string) (*FilterRuleSet, error) {
|
||||
}
|
||||
|
||||
commentPattern := regexp.MustCompile(`^\s*#`)
|
||||
emptyLinePattern := regexp.MustCompile(`^\s*$`)
|
||||
|
||||
file, err := os.Open(source)
|
||||
logger := context.Background().Logger().WithValues("file", source)
|
||||
if err != nil {
|
||||
log.WithError(err).Fatalf("unable to open filter file: %s", source)
|
||||
logger.Error(err, "unable to open filter file", "file", source)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer func(file *os.File) {
|
||||
err := file.Close()
|
||||
if err != nil {
|
||||
log.WithError(err).Fatalf("unable to close filter file: %s", source)
|
||||
logger.Error(err, "unable to close filter file")
|
||||
os.Exit(1)
|
||||
}
|
||||
}(file)
|
||||
|
||||
@@ -75,6 +80,9 @@ func FilterRulesFromFile(source string) (*FilterRuleSet, error) {
|
||||
if commentPattern.MatchString(line) {
|
||||
continue
|
||||
}
|
||||
if emptyLinePattern.MatchString(line) {
|
||||
continue
|
||||
}
|
||||
pattern, err := regexp.Compile(line)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can not compile regular expression: %s", line)
|
||||
|
||||
@@ -129,6 +129,13 @@ func TestFilterFromFile(t *testing.T) {
|
||||
pattern: "test",
|
||||
pass: false,
|
||||
},
|
||||
"EmptyLinesAreIgnored": {
|
||||
includeFile: false,
|
||||
excludeFile: true,
|
||||
excludeFileContents: " \ntest.txt",
|
||||
pattern: "hello world.txt",
|
||||
pass: true,
|
||||
},
|
||||
}
|
||||
for name, test := range tests {
|
||||
var includeTestFile, excludeTestFile string
|
||||
|
||||
+3
-4
@@ -9,7 +9,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/go-retryablehttp"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var caCerts = []string{
|
||||
@@ -94,7 +93,7 @@ func NewCustomTransport(T http.RoundTripper) *CustomTransport {
|
||||
|
||||
func PinnedRetryableHttpClient() *http.Client {
|
||||
httpClient := retryablehttp.NewClient()
|
||||
httpClient.Logger = logrus.WithField("name", "PinnedRetryableHttpClient").WithField("level", logrus.DebugLevel)
|
||||
httpClient.Logger = nil
|
||||
httpClient.HTTPClient.Transport = NewCustomTransport(&http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
RootCAs: PinnedCertPool(),
|
||||
@@ -116,7 +115,7 @@ func PinnedRetryableHttpClient() *http.Client {
|
||||
func RetryableHttpClient() *http.Client {
|
||||
httpClient := retryablehttp.NewClient()
|
||||
httpClient.RetryMax = 3
|
||||
httpClient.Logger = logrus.WithField("name", "RetryableHttpClient").WithField("level", logrus.DebugLevel)
|
||||
httpClient.Logger = nil
|
||||
httpClient.HTTPClient.Timeout = 3 * time.Second
|
||||
httpClient.HTTPClient.Transport = NewCustomTransport(nil)
|
||||
return httpClient.StandardClient()
|
||||
@@ -125,7 +124,7 @@ func RetryableHttpClient() *http.Client {
|
||||
func RetryableHttpClientTimeout(timeOutSeconds int64) *http.Client {
|
||||
httpClient := retryablehttp.NewClient()
|
||||
httpClient.RetryMax = 3
|
||||
httpClient.Logger = logrus.WithField("name", "RetryableHttpClientTimeout").WithField("level", logrus.DebugLevel)
|
||||
httpClient.Logger = nil
|
||||
httpClient.HTTPClient.Timeout = time.Duration(timeOutSeconds) * time.Second
|
||||
httpClient.HTTPClient.Transport = NewCustomTransport(nil)
|
||||
return httpClient.StandardClient()
|
||||
|
||||
@@ -4,8 +4,6 @@ import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const EmailPattern = `\b(?:[a-z0-9!#$%&'*+/=?^_\x60{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_\x60{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])\b`
|
||||
@@ -24,7 +22,7 @@ func BuildRegex(pattern string, specialChar string, length int) string {
|
||||
|
||||
func BuildRegexJWT(firstRange, secondRange, thirdRange string) string {
|
||||
if RangeValidation(firstRange) || RangeValidation(secondRange) || RangeValidation(thirdRange) {
|
||||
log.Error("Min value should not be greater than or equal to max")
|
||||
panic("Min value should not be greater than or equal to max")
|
||||
}
|
||||
return fmt.Sprintf(`\b(ey[%s]{%s}.ey[%s-\/_]{%s}.[%s-\/_]{%s})\b`, AlphaNumPattern, firstRange, AlphaNumPattern, secondRange, AlphaNumPattern, thirdRange)
|
||||
}
|
||||
|
||||
@@ -7,9 +7,9 @@ import (
|
||||
"time"
|
||||
|
||||
secretmanager "cloud.google.com/go/secretmanager/apiv1"
|
||||
"cloud.google.com/go/secretmanager/apiv1/secretmanagerpb"
|
||||
"github.com/joho/godotenv"
|
||||
"github.com/pkg/errors"
|
||||
secretmanagerpb "google.golang.org/genproto/googleapis/cloud/secretmanager/v1"
|
||||
)
|
||||
|
||||
type Secret struct{ kv map[string]string }
|
||||
|
||||
+4
-3
@@ -2,16 +2,17 @@ package common
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
KB, MB, GB, TB, PB = 1e3, 1e6, 1e9, 1e12, 1e15
|
||||
IGNORED_EXTENSIONS = []string{"mp4", "avi", "mpeg", "mpg", "mov", "wmv", "m4p", "swf", "mp2", "flv", "vob", "webm", "hdv", "3gp", "ogg", "mp3", "wav", "flac", "webp"}
|
||||
IgnoredExtensions = []string{"mp4", "avi", "mpeg", "mpg", "mov", "wmv", "m4p", "swf", "mp2", "flv", "vob", "webm", "hdv", "3gp", "ogg", "mp3", "wav", "flac", "webp"}
|
||||
)
|
||||
|
||||
func SkipFile(filename string) bool {
|
||||
for _, ext := range IGNORED_EXTENSIONS {
|
||||
if filepath.Ext(filename) == ext {
|
||||
for _, ext := range IgnoredExtensions {
|
||||
if strings.TrimPrefix(filepath.Ext(filename), ".") == ext {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package common
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestSkipFile(t *testing.T) {
|
||||
type testCase struct {
|
||||
file string
|
||||
want bool
|
||||
}
|
||||
|
||||
// Add a test case for each ignored extension.
|
||||
testCases := make([]testCase, 0, len(IgnoredExtensions)+1)
|
||||
for _, ext := range IgnoredExtensions {
|
||||
testCases = append(testCases, testCase{
|
||||
file: "test." + ext,
|
||||
want: true,
|
||||
})
|
||||
}
|
||||
|
||||
// Add a test case for a file that should not be skipped.
|
||||
testCases = append(testCases, testCase{file: "test.txt", want: false})
|
||||
|
||||
for _, tt := range testCases {
|
||||
t.Run(tt.file, func(t *testing.T) {
|
||||
if got := SkipFile(tt.file); got != tt.want {
|
||||
t.Errorf("SkipFile(%v) got %v, want %v", tt.file, got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSkipFile(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
SkipFile("test.mp4")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
|
||||
dpb "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb"
|
||||
)
|
||||
|
||||
var (
|
||||
specialGroups = map[string][]DetectorID{
|
||||
"all": allDetectors(),
|
||||
}
|
||||
|
||||
detectorTypeValue = make(map[string]dpb.DetectorType, len(dpb.DetectorType_value))
|
||||
validDetectors = make(map[dpb.DetectorType]struct{}, len(dpb.DetectorType_value))
|
||||
maxDetectorType dpb.DetectorType
|
||||
)
|
||||
|
||||
// Setup package local global variables.
|
||||
func init() {
|
||||
for k, v := range dpb.DetectorType_value {
|
||||
dt := dpb.DetectorType(v)
|
||||
detectorTypeValue[strings.ToLower(k)] = dt
|
||||
validDetectors[dt] = struct{}{}
|
||||
if dt > maxDetectorType {
|
||||
maxDetectorType = dt
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DetectorID identifies a detector type and version. This struct is used as a
|
||||
// way for users to identify detectors, whether unique or not. A DetectorID
|
||||
// with Version = 0 indicates all possible versions of a detector.
|
||||
type DetectorID struct {
|
||||
ID dpb.DetectorType
|
||||
Version int
|
||||
}
|
||||
|
||||
// GetDetectorID extracts the DetectorID from a Detector.
|
||||
func GetDetectorID(d detectors.Detector) DetectorID {
|
||||
var version int
|
||||
if v, ok := d.(detectors.Versioner); ok {
|
||||
version = v.Version()
|
||||
}
|
||||
return DetectorID{
|
||||
ID: d.Type(),
|
||||
Version: version,
|
||||
}
|
||||
}
|
||||
|
||||
// ParseDetectors parses user supplied string into a list of detectors types.
|
||||
// "all" will return the list of all available detectors. The input is comma
|
||||
// separated and may use the case-insensitive detector name defined in the
|
||||
// protobuf, or the protobuf enum number. A range may be used as well in the
|
||||
// form "start-end". Order is preserved and duplicates are ignored.
|
||||
func ParseDetectors(input string) ([]DetectorID, error) {
|
||||
var output []DetectorID
|
||||
seenDetector := map[DetectorID]struct{}{}
|
||||
for _, item := range strings.Split(input, ",") {
|
||||
item = strings.TrimSpace(item)
|
||||
if item == "" {
|
||||
continue
|
||||
}
|
||||
detectors, ok := specialGroups[strings.ToLower(item)]
|
||||
if !ok {
|
||||
var err error
|
||||
detectors, err = asRange(item)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
for _, d := range detectors {
|
||||
if _, ok := seenDetector[d]; ok {
|
||||
continue
|
||||
}
|
||||
seenDetector[d] = struct{}{}
|
||||
output = append(output, d)
|
||||
}
|
||||
}
|
||||
return output, nil
|
||||
}
|
||||
|
||||
func (id DetectorID) String() string {
|
||||
name := dpb.DetectorType_name[int32(id.ID)]
|
||||
if name == "" {
|
||||
name = "<invalid ID>"
|
||||
}
|
||||
if id.Version == 0 {
|
||||
return name
|
||||
}
|
||||
return fmt.Sprintf("%s.v%d", name, id.Version)
|
||||
}
|
||||
|
||||
// allDetectors reutrns an ordered slice of all detector types.
|
||||
func allDetectors() []DetectorID {
|
||||
all := make([]DetectorID, 0, len(dpb.DetectorType_name))
|
||||
for id := range dpb.DetectorType_name {
|
||||
all = append(all, DetectorID{ID: dpb.DetectorType(id)})
|
||||
}
|
||||
sort.Slice(all, func(i, j int) bool { return all[i].ID < all[j].ID })
|
||||
return all
|
||||
}
|
||||
|
||||
// asRange converts a single input into a slice of detector types. If the input
|
||||
// is not in range format, a slice of length 1 is returned. Unbounded ranges
|
||||
// are allowed.
|
||||
func asRange(input string) ([]DetectorID, error) {
|
||||
// Check if it's a single detector type.
|
||||
dt, err := asDetectorID(input)
|
||||
if err == nil {
|
||||
return []DetectorID{dt}, nil
|
||||
}
|
||||
|
||||
// Check if it's a range; if not return the error from above.
|
||||
start, end, found := strings.Cut(input, "-")
|
||||
if !found {
|
||||
return nil, err
|
||||
}
|
||||
start, end = strings.TrimSpace(start), strings.TrimSpace(end)
|
||||
|
||||
// Convert the range start and end to a DetectorType.
|
||||
dtStart, err := asDetectorID(start)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dtEnd, err := asDetectorID(end)
|
||||
// If end is empty it's an unbounded range.
|
||||
if err != nil && end != "" {
|
||||
return nil, err
|
||||
}
|
||||
if end == "" {
|
||||
dtEnd.ID = maxDetectorType
|
||||
}
|
||||
|
||||
// Ensure these ranges don't have versions.
|
||||
if dtEnd.Version != 0 || dtStart.Version != 0 {
|
||||
return nil, fmt.Errorf("versions within ranges are not supported: %s", input)
|
||||
}
|
||||
|
||||
step := dpb.DetectorType(1)
|
||||
if dtStart.ID > dtEnd.ID {
|
||||
step = -1
|
||||
}
|
||||
var output []DetectorID
|
||||
for dt := dtStart.ID; dt != dtEnd.ID; dt += step {
|
||||
if _, ok := validDetectors[dt]; !ok {
|
||||
continue
|
||||
}
|
||||
output = append(output, DetectorID{ID: dt})
|
||||
}
|
||||
return append(output, dtEnd), nil
|
||||
}
|
||||
|
||||
// asDetectorID converts the case-insensitive input into a DetectorID.
|
||||
// Name or ID may be used.
|
||||
func asDetectorID(input string) (DetectorID, error) {
|
||||
if input == "" {
|
||||
return DetectorID{}, fmt.Errorf("empty detector")
|
||||
}
|
||||
var detectorID DetectorID
|
||||
// Separate the version if there is one.
|
||||
if detector, version, hasVersion := strings.Cut(input, "."); hasVersion {
|
||||
parsedVersion, err := parseVersion(version)
|
||||
if err != nil {
|
||||
return DetectorID{}, fmt.Errorf("invalid version for input: %q error: %w", input, err)
|
||||
}
|
||||
detectorID.Version = parsedVersion
|
||||
// Because there was a version, the detector type input is the part before the '.'
|
||||
input = detector
|
||||
}
|
||||
|
||||
// Check if it's a named detector.
|
||||
if dt, ok := detectorTypeValue[strings.ToLower(input)]; ok {
|
||||
detectorID.ID = dt
|
||||
return detectorID, nil
|
||||
}
|
||||
// Check if it's a detector ID.
|
||||
if i, err := strconv.ParseInt(input, 10, 32); err == nil {
|
||||
dt := dpb.DetectorType(i)
|
||||
if _, ok := validDetectors[dt]; !ok {
|
||||
return DetectorID{}, fmt.Errorf("invalid detector ID: %s", input)
|
||||
}
|
||||
detectorID.ID = dt
|
||||
return detectorID, nil
|
||||
}
|
||||
return DetectorID{}, fmt.Errorf("unrecognized detector type: %s", input)
|
||||
}
|
||||
|
||||
func parseVersion(v string) (int, error) {
|
||||
if !strings.HasPrefix(strings.ToLower(v), "v") {
|
||||
return 0, fmt.Errorf("version must start with 'v'")
|
||||
}
|
||||
version := strings.TrimLeft(v, "vV")
|
||||
return strconv.Atoi(version)
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
dpb "github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb"
|
||||
)
|
||||
|
||||
func TestDetectorParsing(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
input string
|
||||
expected []DetectorID
|
||||
}{
|
||||
"all": {"AlL", allDetectors()},
|
||||
"trailing range": {"0-", allDetectors()},
|
||||
"all after 1": {"1-", allDetectors()[1:]},
|
||||
"named and valid range": {"aWs,8-9", []DetectorID{{ID: dpb.DetectorType_AWS}, {ID: dpb.DetectorType_Github}, {ID: dpb.DetectorType_Gitlab}}},
|
||||
"duplicate order preserved": {"9, 8, 9", []DetectorID{{ID: 9}, {ID: 8}}},
|
||||
"named range": {"github - gitlab", []DetectorID{{ID: dpb.DetectorType_Github}, {ID: dpb.DetectorType_Gitlab}}},
|
||||
"range preserved": {"8-9, 7-10", []DetectorID{{ID: 8}, {ID: 9}, {ID: 7}, {ID: 10}}},
|
||||
"reverse range": {"9-8", []DetectorID{{ID: 9}, {ID: 8}}},
|
||||
"range preserved with all": {"10-,all", append(allDetectors()[10:], allDetectors()[:10]...)},
|
||||
"empty list item": {"8, ,9", []DetectorID{{ID: 8}, {ID: 9}}},
|
||||
"invalid end range": {"0-1337", nil},
|
||||
"invalid name": {"foo", nil},
|
||||
"negative": {"-1", nil},
|
||||
"github.v1": {"github.v1", []DetectorID{{ID: dpb.DetectorType_Github, Version: 1}}},
|
||||
"gitlab.v100": {"gitlab.v100", []DetectorID{{ID: dpb.DetectorType_Gitlab, Version: 100}}},
|
||||
"range with versions": {"github.v2 - gitlab.v1", nil},
|
||||
"invalid version no v": {"gitlab.2", nil},
|
||||
"invalid version no number": {"gitlab.github", nil},
|
||||
"capital V is fine": {"GiTlAb.V2", []DetectorID{{ID: dpb.DetectorType_Gitlab, Version: 2}}},
|
||||
"id number with version": {"8.v2", []DetectorID{{ID: 8, Version: 2}}},
|
||||
}
|
||||
|
||||
for name, tt := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
got, gotErr := ParseDetectors(tt.input)
|
||||
if tt.expected == nil {
|
||||
assert.Error(t, gotErr)
|
||||
return
|
||||
}
|
||||
assert.Equal(t, tt.expected, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -166,6 +166,9 @@ func captureCancelCallstack(ctx logCtx, f context.CancelFunc) (Context, context.
|
||||
}
|
||||
f()
|
||||
// Set the error with the stacktrace if the err pointer is non-nil.
|
||||
*ctx.err = fmt.Errorf("%w (%s)", ctx.Err(), string(debug.Stack()))
|
||||
*ctx.err = fmt.Errorf(
|
||||
"%w (canceled at %v\n%s)",
|
||||
ctx.Err(), time.Now(), string(debug.Stack()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/custom_detectorspb"
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
// The maximum number of matches from one chunk. This const is used when
|
||||
@@ -82,71 +83,99 @@ func (c *customRegexWebhook) FromData(ctx context.Context, verify bool, data []b
|
||||
// ]
|
||||
matches := permutateMatches(regexMatches)
|
||||
|
||||
// Create result object and test for verification.
|
||||
for _, match := range matches {
|
||||
if common.IsDone(ctx) {
|
||||
// TODO: Log we're possibly leaving out results.
|
||||
return results, nil
|
||||
}
|
||||
var raw string
|
||||
for _, values := range match {
|
||||
// values[0] contains the entire regex match.
|
||||
raw += values[0]
|
||||
}
|
||||
result := detectors.Result{
|
||||
DetectorType: detectorspb.DetectorType_CustomRegex,
|
||||
Raw: []byte(raw),
|
||||
}
|
||||
g := new(errgroup.Group)
|
||||
|
||||
if isKnownFalsePositive(match) {
|
||||
continue
|
||||
}
|
||||
if !verify {
|
||||
results = append(results, result)
|
||||
continue
|
||||
}
|
||||
// Verify via webhook.
|
||||
jsonBody, err := json.Marshal(map[string]map[string][]string{
|
||||
c.GetName(): match,
|
||||
// Create result object and test for verification.
|
||||
resultsCh := make(chan detectors.Result, maxTotalMatches)
|
||||
for _, match := range matches {
|
||||
match := match
|
||||
g.Go(func() error {
|
||||
return c.createResults(ctx, match, verify, resultsCh)
|
||||
})
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
// Try each config until we successfully verify.
|
||||
for _, verifyConfig := range c.GetVerify() {
|
||||
if common.IsDone(ctx) {
|
||||
// TODO: Log we're possibly leaving out results.
|
||||
return results, nil
|
||||
}
|
||||
req, err := http.NewRequestWithContext(ctx, "POST", verifyConfig.GetEndpoint(), bytes.NewReader(jsonBody))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
for _, header := range verifyConfig.GetHeaders() {
|
||||
key, value, found := strings.Cut(header, ":")
|
||||
if !found {
|
||||
// Should be unreachable due to validation.
|
||||
continue
|
||||
}
|
||||
req.Header.Add(key, strings.TrimLeft(value, "\t\n\v\f\r "))
|
||||
}
|
||||
res, err := httpClient.Do(req)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
// TODO: Read response body.
|
||||
res.Body.Close()
|
||||
if res.StatusCode == http.StatusOK {
|
||||
result.Verified = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore any errors and collect as many of the results as we can.
|
||||
_ = g.Wait()
|
||||
close(resultsCh)
|
||||
|
||||
for result := range resultsCh {
|
||||
results = append(results, result)
|
||||
}
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (c *customRegexWebhook) createResults(ctx context.Context, match map[string][]string, verify bool, results chan<- detectors.Result) error {
|
||||
if common.IsDone(ctx) {
|
||||
// TODO: Log we're possibly leaving out results.
|
||||
return ctx.Err()
|
||||
}
|
||||
var raw string
|
||||
for _, values := range match {
|
||||
// values[0] contains the entire regex match.
|
||||
raw += values[0]
|
||||
}
|
||||
result := detectors.Result{
|
||||
DetectorType: detectorspb.DetectorType_CustomRegex,
|
||||
DetectorName: c.GetName(),
|
||||
Raw: []byte(raw),
|
||||
}
|
||||
|
||||
if !verify {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case results <- result:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
// Verify via webhook.
|
||||
jsonBody, err := json.Marshal(map[string]map[string][]string{
|
||||
c.GetName(): match,
|
||||
})
|
||||
if err != nil {
|
||||
// This should never happen, but if it does, return nil to not
|
||||
// disrupt other verification.
|
||||
return nil
|
||||
}
|
||||
// Try each config until we successfully verify.
|
||||
for _, verifyConfig := range c.GetVerify() {
|
||||
if common.IsDone(ctx) {
|
||||
// TODO: Log we're possibly leaving out results.
|
||||
return ctx.Err()
|
||||
}
|
||||
req, err := http.NewRequestWithContext(ctx, "POST", verifyConfig.GetEndpoint(), bytes.NewReader(jsonBody))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
for _, header := range verifyConfig.GetHeaders() {
|
||||
key, value, found := strings.Cut(header, ":")
|
||||
if !found {
|
||||
// Should be unreachable due to validation.
|
||||
continue
|
||||
}
|
||||
req.Header.Add(key, strings.TrimLeft(value, "\t\n\v\f\r "))
|
||||
}
|
||||
res, err := httpClient.Do(req)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
// TODO: Read response body.
|
||||
res.Body.Close()
|
||||
if res.StatusCode == http.StatusOK {
|
||||
result.Verified = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case results <- result:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (c *customRegexWebhook) Keywords() []string {
|
||||
return c.GetKeywords()
|
||||
}
|
||||
@@ -212,15 +241,6 @@ func permutateMatches(regexMatches map[string][][]string) []map[string][]string
|
||||
return matches
|
||||
}
|
||||
|
||||
// This function will check false positives for common test words, but also it
|
||||
// will make sure the key appears 'random' enough to be a real key.
|
||||
func isKnownFalsePositive(match map[string][]string) bool {
|
||||
for _, values := range match {
|
||||
for _, value := range values {
|
||||
if detectors.IsKnownFalsePositive(value, detectors.DefaultFalsePositives, true) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
func (c *customRegexWebhook) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_CustomRegex
|
||||
}
|
||||
|
||||
@@ -193,6 +193,21 @@ func TestPermutateMatches(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDetector(t *testing.T) {
|
||||
detector, err := NewWebhookCustomRegex(&custom_detectorspb.CustomRegex{
|
||||
Name: "test",
|
||||
// "password" is normally flagged as a false positive, but CustomRegex
|
||||
// should allow the user to decide and report it as a result.
|
||||
Keywords: []string{"password"},
|
||||
Regex: map[string]string{"regex": "password=.*"},
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
results, err := detector.FromData(context.Background(), false, []byte(`password="123456"`))
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 1, len(results))
|
||||
assert.Equal(t, results[0].Raw, []byte(`password="123456"`))
|
||||
}
|
||||
|
||||
func BenchmarkProductIndices(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = productIndices(3, 2, 6)
|
||||
|
||||
+82
-43
@@ -3,7 +3,6 @@ package decoders
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"strings"
|
||||
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/sources"
|
||||
)
|
||||
@@ -13,52 +12,20 @@ type Base64 struct{}
|
||||
var (
|
||||
b64Charset = []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=")
|
||||
b64EndChars = "+/="
|
||||
// Given characters are mostly ASCII, we can use a simple array to map.
|
||||
b64CharsetMapping [128]bool
|
||||
)
|
||||
|
||||
func getSubstringsOfCharacterSet(data []byte, charset []byte, threshold int) []string {
|
||||
count := 0
|
||||
substrings := []string{}
|
||||
letters := strings.Builder{}
|
||||
if len(data) == 0 {
|
||||
return nil
|
||||
func init() {
|
||||
// Build an array of all the characters in the base64 charset.
|
||||
for _, char := range b64Charset {
|
||||
b64CharsetMapping[char] = true
|
||||
}
|
||||
for _, char := range string(data) {
|
||||
if bytes.ContainsRune(charset, char) {
|
||||
letters.WriteRune(char)
|
||||
count++
|
||||
} else {
|
||||
if count > threshold {
|
||||
substrings = appendB64Substring(letters, substrings)
|
||||
}
|
||||
letters.Reset()
|
||||
count = 0
|
||||
}
|
||||
}
|
||||
|
||||
if count > threshold && len(letters.String()) > 0 {
|
||||
substrings = appendB64Substring(letters, substrings)
|
||||
}
|
||||
|
||||
return substrings
|
||||
}
|
||||
|
||||
func appendB64Substring(letters strings.Builder, substrings []string) []string {
|
||||
|
||||
substring := strings.TrimLeft(letters.String(), b64EndChars)
|
||||
// handle key=value
|
||||
if strings.Contains(strings.TrimRight(substring, b64EndChars), "=") {
|
||||
split := strings.SplitN(substring, "=", 2)
|
||||
substrings = append(substrings, split[len(split)-1])
|
||||
} else {
|
||||
substrings = append(substrings, substring)
|
||||
}
|
||||
return substrings
|
||||
}
|
||||
|
||||
func (d *Base64) FromChunk(chunk *sources.Chunk) *sources.Chunk {
|
||||
|
||||
encodedSubstrings := getSubstringsOfCharacterSet(chunk.Data, b64Charset, 20)
|
||||
decodedSubstrings := map[string][]byte{}
|
||||
encodedSubstrings := getSubstringsOfCharacterSet(chunk.Data, 20)
|
||||
decodedSubstrings := make(map[string][]byte)
|
||||
|
||||
for _, str := range encodedSubstrings {
|
||||
dec, err := base64.StdEncoding.DecodeString(str)
|
||||
@@ -68,11 +35,83 @@ func (d *Base64) FromChunk(chunk *sources.Chunk) *sources.Chunk {
|
||||
}
|
||||
|
||||
if len(decodedSubstrings) > 0 {
|
||||
for substring, dec := range decodedSubstrings {
|
||||
chunk.Data = bytes.Replace(chunk.Data, []byte(substring), dec, 1)
|
||||
var result bytes.Buffer
|
||||
result.Grow(len(chunk.Data))
|
||||
|
||||
start := 0
|
||||
for _, encoded := range encodedSubstrings {
|
||||
if decoded, ok := decodedSubstrings[encoded]; ok {
|
||||
end := bytes.Index(chunk.Data[start:], []byte(encoded))
|
||||
if end != -1 {
|
||||
result.Write(chunk.Data[start : start+end])
|
||||
result.Write(decoded)
|
||||
start += end + len(encoded)
|
||||
}
|
||||
}
|
||||
}
|
||||
result.Write(chunk.Data[start:])
|
||||
chunk.Data = result.Bytes()
|
||||
return chunk
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getSubstringsOfCharacterSet(data []byte, threshold int) []string {
|
||||
if len(data) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
count := 0
|
||||
substringsCount := 0
|
||||
|
||||
// Determine the number of substrings that will be returned.
|
||||
// Pre-allocate the slice to avoid reallocations.
|
||||
for _, char := range data {
|
||||
if char < 128 && b64CharsetMapping[char] {
|
||||
count++
|
||||
} else {
|
||||
if count > threshold {
|
||||
substringsCount++
|
||||
}
|
||||
count = 0
|
||||
}
|
||||
}
|
||||
if count > threshold {
|
||||
substringsCount++
|
||||
}
|
||||
|
||||
count = 0
|
||||
start := 0
|
||||
substrings := make([]string, 0, substringsCount)
|
||||
|
||||
for i, char := range data {
|
||||
if char < 128 && b64CharsetMapping[char] {
|
||||
if count == 0 {
|
||||
start = i
|
||||
}
|
||||
count++
|
||||
} else {
|
||||
if count > threshold {
|
||||
substrings = appendB64Substring(data, start, count, substrings)
|
||||
}
|
||||
count = 0
|
||||
}
|
||||
}
|
||||
|
||||
if count > threshold {
|
||||
substrings = appendB64Substring(data, start, count, substrings)
|
||||
}
|
||||
|
||||
return substrings
|
||||
}
|
||||
|
||||
func appendB64Substring(data []byte, start, count int, substrings []string) []string {
|
||||
substring := bytes.TrimLeft(data[start:start+count], b64EndChars)
|
||||
if idx := bytes.IndexByte(bytes.TrimRight(substring, b64EndChars), '='); idx != -1 {
|
||||
substrings = append(substrings, string(substring[idx+1:]))
|
||||
} else {
|
||||
substrings = append(substrings, string(substring))
|
||||
}
|
||||
return substrings
|
||||
}
|
||||
|
||||
@@ -90,13 +90,29 @@ func TestBase64_FromChunk(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkFromChunk(benchmark *testing.B) {
|
||||
func BenchmarkFromChunkSmall(b *testing.B) {
|
||||
d := Base64{}
|
||||
for name, data := range detectors.MustGetBenchmarkData() {
|
||||
benchmark.Run(name, func(b *testing.B) {
|
||||
for n := 0; n < b.N; n++ {
|
||||
d.FromChunk(&sources.Chunk{Data: data})
|
||||
}
|
||||
})
|
||||
data := detectors.MustGetBenchmarkData()["small"]
|
||||
|
||||
for n := 0; n < b.N; n++ {
|
||||
d.FromChunk(&sources.Chunk{Data: data})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkFromChunkMedium(b *testing.B) {
|
||||
d := Base64{}
|
||||
data := detectors.MustGetBenchmarkData()["medium"]
|
||||
|
||||
for n := 0; n < b.N; n++ {
|
||||
d.FromChunk(&sources.Chunk{Data: data})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkFromChunkLarge(b *testing.B) {
|
||||
d := Base64{}
|
||||
data := detectors.MustGetBenchmarkData()["big"]
|
||||
|
||||
for n := 0; n < b.N; n++ {
|
||||
d.FromChunk(&sources.Chunk{Data: data})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ func DefaultDecoders() []Decoder {
|
||||
return []Decoder{
|
||||
&UTF8{},
|
||||
&Base64{},
|
||||
&UTF16{},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
package decoders
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/sources"
|
||||
)
|
||||
|
||||
type UTF16 struct{}
|
||||
|
||||
func (d *UTF16) FromChunk(chunk *sources.Chunk) *sources.Chunk {
|
||||
if chunk == nil || len(chunk.Data) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if utf16Data, err := utf16ToUTF8(chunk.Data); err == nil {
|
||||
chunk.Data = utf16Data
|
||||
return chunk
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// utf16ToUTF8 converts a byte slice containing UTF-16 encoded data to a UTF-8 encoded byte slice.
|
||||
func utf16ToUTF8(b []byte) ([]byte, error) {
|
||||
endianness, err := guessUTF16Endianness(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
for i := 0; i < len(b); i += 2 {
|
||||
r := rune(endianness.Uint16(b[i:]))
|
||||
if utf8.ValidRune(r) {
|
||||
buf.WriteRune(r)
|
||||
}
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
func guessUTF16Endianness(b []byte) (binary.ByteOrder, error) {
|
||||
if len(b) < 2 || len(b)%2 != 0 {
|
||||
return nil, fmt.Errorf("input length must be even and at least 2 bytes long")
|
||||
}
|
||||
|
||||
var evenNullBytes, oddNullBytes int
|
||||
|
||||
for i := 0; i < len(b); i += 2 {
|
||||
if b[i] == 0 {
|
||||
oddNullBytes++
|
||||
}
|
||||
if b[i+1] == 0 {
|
||||
evenNullBytes++
|
||||
}
|
||||
}
|
||||
|
||||
if evenNullBytes > oddNullBytes {
|
||||
return binary.LittleEndian, nil
|
||||
}
|
||||
if oddNullBytes > evenNullBytes {
|
||||
return binary.BigEndian, nil
|
||||
}
|
||||
return nil, fmt.Errorf("could not determine endianness")
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package decoders
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/sources"
|
||||
)
|
||||
|
||||
func TestUTF16Decoder(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
input []byte
|
||||
expected []byte
|
||||
expectNil bool
|
||||
}{
|
||||
{
|
||||
name: "Valid UTF-16LE input",
|
||||
input: []byte{72, 0, 101, 0, 108, 0, 108, 0, 111, 0, 32, 0, 87, 0, 111, 0, 114, 0, 108, 0, 100, 0},
|
||||
expected: []byte("Hello World"),
|
||||
expectNil: false,
|
||||
},
|
||||
{
|
||||
name: "Valid UTF-16BE input",
|
||||
input: []byte{0, 72, 0, 101, 0, 108, 0, 108, 0, 111, 0, 32, 0, 87, 0, 111, 0, 114, 0, 108, 0, 100},
|
||||
expected: []byte("Hello World"),
|
||||
expectNil: false,
|
||||
},
|
||||
{
|
||||
name: "Invalid UTF-16 input (it's UTF-8)",
|
||||
input: []byte("Hello World!"),
|
||||
expected: nil,
|
||||
expectNil: true,
|
||||
},
|
||||
{
|
||||
name: "Invalid UTF-16 input (odd length)",
|
||||
input: []byte{72, 0, 101, 0, 108, 0, 108, 0, 111, 0, 32, 0, 87, 0, 111, 0, 114, 0, 108, 0, 0},
|
||||
expected: nil,
|
||||
expectNil: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
chunk := &sources.Chunk{Data: tc.input}
|
||||
decoder := &UTF16{}
|
||||
decodedChunk := decoder.FromChunk(chunk)
|
||||
|
||||
if tc.expectNil {
|
||||
if decodedChunk != nil {
|
||||
t.Errorf("Expected nil, got chunk with data: %v", decodedChunk.Data)
|
||||
}
|
||||
return
|
||||
}
|
||||
if decodedChunk == nil {
|
||||
t.Errorf("Expected chunk with data, got nil")
|
||||
return
|
||||
}
|
||||
if !bytes.Equal(decodedChunk.Data, tc.expected) {
|
||||
t.Errorf("Expected decoded data: %v, got: %v", tc.expected, decodedChunk.Data)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUtf16ToUtf8(b *testing.B) {
|
||||
// Example UTF-16LE encoded data
|
||||
data := []byte{72, 0, 101, 0, 108, 0, 108, 0, 111, 0, 32, 0, 87, 0, 111, 0, 114, 0, 108, 0, 100, 0}
|
||||
|
||||
for n := 0; n < b.N; n++ {
|
||||
_, _ = utf16ToUTF8(data)
|
||||
}
|
||||
}
|
||||
+20
-9
@@ -26,19 +26,30 @@ func (d *UTF8) FromChunk(chunk *sources.Chunk) *sources.Chunk {
|
||||
// extacting contigous portions of printable characters that we care
|
||||
// about from some bytes
|
||||
func extractSubstrings(b []byte) []byte {
|
||||
fields := bytes.FieldsFunc(b, func(r rune) bool {
|
||||
isValidByte := func(c byte) bool {
|
||||
// https://www.rapidtables.com/code/text/ascii-table.html
|
||||
// split on anything that is not ascii space through tilde
|
||||
return !(r > 31 && r < 127)
|
||||
})
|
||||
return c > 31 && c < 127
|
||||
}
|
||||
|
||||
keep := [][]byte{}
|
||||
for _, field := range fields {
|
||||
// Remove fields shorter than 6 characters.
|
||||
if bts := bytes.TrimSpace(field); len(bts) > 5 {
|
||||
keep = append(keep, bts)
|
||||
field := make([]byte, len(b))
|
||||
fieldLen := 0
|
||||
buf := &bytes.Buffer{}
|
||||
for i, c := range b {
|
||||
if isValidByte(c) {
|
||||
field[fieldLen] = c
|
||||
fieldLen++
|
||||
} else {
|
||||
if fieldLen > 5 {
|
||||
buf.Write(field[:fieldLen])
|
||||
}
|
||||
fieldLen = 0
|
||||
}
|
||||
|
||||
if i == len(b)-1 && fieldLen > 5 {
|
||||
buf.Write(field[:fieldLen])
|
||||
}
|
||||
}
|
||||
|
||||
return bytes.Join(keep, []byte("\n"))
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/kylelemons/godebug/pretty"
|
||||
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/sources"
|
||||
)
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ package abbysale
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
@@ -52,7 +51,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
req.Header.Add("x-api-key", fmt.Sprintf("%s", resMatch))
|
||||
req.Header.Add("x-api-key", resMatch)
|
||||
res, err := client.Do(req)
|
||||
if err == nil {
|
||||
defer res.Body.Close()
|
||||
@@ -72,3 +71,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_Abbysale
|
||||
}
|
||||
|
||||
@@ -72,3 +72,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_Abstract
|
||||
}
|
||||
|
||||
@@ -83,3 +83,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_AbuseIPDB
|
||||
}
|
||||
|
||||
@@ -70,3 +70,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_Accuweather
|
||||
}
|
||||
|
||||
@@ -70,3 +70,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_AdafruitIO
|
||||
}
|
||||
|
||||
@@ -82,3 +82,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_AdobeIO
|
||||
}
|
||||
|
||||
@@ -80,3 +80,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_Adzuna
|
||||
}
|
||||
|
||||
@@ -83,3 +83,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_Aeroworkflow
|
||||
}
|
||||
|
||||
@@ -83,3 +83,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_Agora
|
||||
}
|
||||
|
||||
@@ -73,3 +73,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_Aha
|
||||
}
|
||||
|
||||
@@ -87,3 +87,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_AirbrakeProjectKey
|
||||
}
|
||||
|
||||
@@ -70,3 +70,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_AirbrakeUserKey
|
||||
}
|
||||
|
||||
@@ -73,3 +73,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_Airship
|
||||
}
|
||||
|
||||
@@ -81,3 +81,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_AirtableApiKey
|
||||
}
|
||||
|
||||
@@ -73,3 +73,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_AirVisual
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package moonclerck
|
||||
package alchemy
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -20,16 +20,16 @@ var (
|
||||
client = common.SaneHttpClient()
|
||||
|
||||
// Make sure that your group is surrounded in boundary characters such as below to reduce false positives.
|
||||
keyPat = regexp.MustCompile(detectors.PrefixRegex([]string{"moonclerck"}) + `\b([0-9a-z]{32})\b`)
|
||||
keyPat = regexp.MustCompile(detectors.PrefixRegex([]string{"alchemy"}) + `\b([0-9a-zA-Z]{23}_[0-9a-zA-Z]{8})\b`)
|
||||
)
|
||||
|
||||
// Keywords are used for efficiently pre-filtering chunks.
|
||||
// Use identifiers in the secret preferably, or the provider name.
|
||||
func (s Scanner) Keywords() []string {
|
||||
return []string{"moonclerck"}
|
||||
return []string{"alchemy"}
|
||||
}
|
||||
|
||||
// FromData will find and optionally verify Moonclerck secrets in a given set of bytes.
|
||||
// FromData will find and optionally verify Alchemy secrets in a given set of bytes.
|
||||
func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (results []detectors.Result, err error) {
|
||||
dataStr := string(data)
|
||||
|
||||
@@ -42,17 +42,15 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
resMatch := strings.TrimSpace(match[1])
|
||||
|
||||
s1 := detectors.Result{
|
||||
DetectorType: detectorspb.DetectorType_Moonclerk,
|
||||
DetectorType: detectorspb.DetectorType_Alchemy,
|
||||
Raw: []byte(resMatch),
|
||||
}
|
||||
|
||||
if verify {
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", "https://api.moonclerk.com/forms", nil)
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", "https://eth-mainnet.g.alchemy.com/v2/"+resMatch+"/getNFTs/?owner=vitalik.eth", nil)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
req.Header.Add("Accept", "application/vnd.moonclerk+json;version=1")
|
||||
req.Header.Add("Authorization", "Token token="+resMatch)
|
||||
res, err := client.Do(req)
|
||||
if err == nil {
|
||||
defer res.Body.Close()
|
||||
@@ -72,3 +70,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_Alchemy
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
//go:build detectors
|
||||
// +build detectors
|
||||
|
||||
package alchemy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/kylelemons/godebug/pretty"
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
|
||||
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/common"
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb"
|
||||
)
|
||||
|
||||
func TestAlchemy_FromChunk(t *testing.T) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||
defer cancel()
|
||||
testSecrets, err := common.GetSecret(ctx, "trufflehog-testing", "detectors4")
|
||||
if err != nil {
|
||||
t.Fatalf("could not get test secrets from GCP: %s", err)
|
||||
}
|
||||
secret := testSecrets.MustGetField("ALCHEMY")
|
||||
inactiveSecret := testSecrets.MustGetField("ALCHEMY_INACTIVE")
|
||||
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
data []byte
|
||||
verify bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
s Scanner
|
||||
args args
|
||||
want []detectors.Result
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "found, verified",
|
||||
s: Scanner{},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
data: []byte(fmt.Sprintf("You can find a alchemy secret %s within", secret)),
|
||||
verify: true,
|
||||
},
|
||||
want: []detectors.Result{
|
||||
{
|
||||
DetectorType: detectorspb.DetectorType_Alchemy,
|
||||
Verified: true,
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "found, unverified",
|
||||
s: Scanner{},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
data: []byte(fmt.Sprintf("You can find a alchemy secret %s within but not valid", inactiveSecret)), // the secret would satisfy the regex but not pass validation
|
||||
verify: true,
|
||||
},
|
||||
want: []detectors.Result{
|
||||
{
|
||||
DetectorType: detectorspb.DetectorType_Alchemy,
|
||||
Verified: false,
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "not found",
|
||||
s: Scanner{},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
data: []byte("You cannot find the secret within"),
|
||||
verify: true,
|
||||
},
|
||||
want: nil,
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s := Scanner{}
|
||||
got, err := s.FromData(tt.args.ctx, tt.args.verify, tt.args.data)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("Alchemy.FromData() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
for i := range got {
|
||||
if len(got[i].Raw) == 0 {
|
||||
t.Fatalf("no raw secret present: \n %+v", got[i])
|
||||
}
|
||||
got[i].Raw = nil
|
||||
}
|
||||
if diff := pretty.Compare(got, tt.want); diff != "" {
|
||||
t.Errorf("Alchemy.FromData() %s diff: (-got +want)\n%s", tt.name, diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkFromData(benchmark *testing.B) {
|
||||
ctx := context.Background()
|
||||
s := Scanner{}
|
||||
for name, data := range detectors.MustGetBenchmarkData() {
|
||||
benchmark.Run(name, func(b *testing.B) {
|
||||
for n := 0; n < b.N; n++ {
|
||||
_, err := s.FromData(ctx, false, data)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -76,3 +76,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_Alconost
|
||||
}
|
||||
|
||||
@@ -82,3 +82,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_Alegra
|
||||
}
|
||||
|
||||
@@ -74,3 +74,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_AletheiaApi
|
||||
}
|
||||
|
||||
@@ -80,3 +80,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_AlgoliaAdminKey
|
||||
}
|
||||
|
||||
@@ -3,9 +3,9 @@ package alibaba
|
||||
import (
|
||||
"context"
|
||||
"crypto/hmac"
|
||||
"crypto/rand"
|
||||
"crypto/sha1"
|
||||
"encoding/base64"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"regexp"
|
||||
@@ -38,10 +38,9 @@ func (s Scanner) Keywords() []string {
|
||||
}
|
||||
|
||||
func randString(n int) string {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
const alphanum = "0123456789abcdefghijklmnopqrstuvwxyz"
|
||||
var bytes = make([]byte, n)
|
||||
rand.Read(bytes)
|
||||
_, _ = rand.Read(bytes)
|
||||
for i, b := range bytes {
|
||||
bytes[i] = alphanum[b%byte(len(alphanum))]
|
||||
}
|
||||
@@ -130,3 +129,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_Alibaba
|
||||
}
|
||||
|
||||
@@ -96,6 +96,7 @@ func TestAlibaba_FromChunk(t *testing.T) {
|
||||
t.Fatalf("no raw secret present: \n %+v", got[i])
|
||||
}
|
||||
got[i].Raw = nil
|
||||
got[i].RawV2 = nil
|
||||
}
|
||||
if diff := pretty.Compare(got, tt.want); diff != "" {
|
||||
t.Errorf("Alibaba.FromData() %s diff: (-got +want)\n%s", tt.name, diff)
|
||||
|
||||
@@ -71,3 +71,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_AlienVault
|
||||
}
|
||||
|
||||
@@ -77,3 +77,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_Allsports
|
||||
}
|
||||
|
||||
@@ -88,3 +88,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_Amadeus
|
||||
}
|
||||
|
||||
@@ -72,3 +72,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_Ambee
|
||||
}
|
||||
|
||||
@@ -81,3 +81,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_AmplitudeApiKey
|
||||
}
|
||||
|
||||
@@ -82,3 +82,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_Anypoint
|
||||
}
|
||||
|
||||
@@ -71,3 +71,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_Apacta
|
||||
}
|
||||
|
||||
@@ -86,3 +86,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
type Response struct {
|
||||
ReturnCode int `json:"return_code"`
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_Api2Cart
|
||||
}
|
||||
|
||||
@@ -84,3 +84,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_ApiDeck
|
||||
}
|
||||
|
||||
@@ -80,3 +80,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_Apiflash
|
||||
}
|
||||
|
||||
@@ -83,3 +83,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_ApiFonica
|
||||
}
|
||||
|
||||
@@ -70,3 +70,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_Apify
|
||||
}
|
||||
|
||||
@@ -70,3 +70,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_Apilayer
|
||||
}
|
||||
|
||||
@@ -84,3 +84,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_APIMatic
|
||||
}
|
||||
|
||||
@@ -72,3 +72,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_ApiScience
|
||||
}
|
||||
|
||||
@@ -72,3 +72,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_APITemplate
|
||||
}
|
||||
|
||||
@@ -71,3 +71,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_Apollo
|
||||
}
|
||||
|
||||
@@ -92,3 +92,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_Appcues
|
||||
}
|
||||
|
||||
@@ -75,3 +75,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_Appfollow
|
||||
}
|
||||
|
||||
@@ -76,3 +76,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_Appointedd
|
||||
}
|
||||
|
||||
@@ -72,3 +72,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_AppSynergy
|
||||
}
|
||||
|
||||
@@ -91,3 +91,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_Apptivo
|
||||
}
|
||||
|
||||
@@ -83,3 +83,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_ArtifactoryAccessToken
|
||||
}
|
||||
|
||||
@@ -82,3 +82,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_Artsy
|
||||
}
|
||||
|
||||
@@ -72,3 +72,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_AsanaOauth
|
||||
}
|
||||
|
||||
@@ -71,3 +71,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_AsanaPersonalAccessToken
|
||||
}
|
||||
|
||||
@@ -72,3 +72,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_AssemblyAI
|
||||
}
|
||||
|
||||
@@ -72,3 +72,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_Atera
|
||||
}
|
||||
|
||||
@@ -81,3 +81,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_Audd
|
||||
}
|
||||
|
||||
@@ -90,3 +90,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_Auth0ManagementApiToken
|
||||
}
|
||||
|
||||
@@ -116,3 +116,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_Auth0oauth
|
||||
}
|
||||
|
||||
@@ -82,3 +82,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_Autodesk
|
||||
}
|
||||
|
||||
@@ -81,3 +81,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detectorspb.DetectorType {
|
||||
return detectorspb.DetectorType_Autoklose
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user