Compare commits

..

220 Commits

Author SHA1 Message Date
Mike Vanbuskirk 6a02151add re-add actions CLI switch to action yml 2023-03-28 14:52:03 -04:00
Mike Vanbuskirk c78d10149b ensure stdout is still provided (#1217) 2023-03-28 11:29:48 -07:00
Dustin Decker cb454bfc05 Add GitHub Actions output (#1201)
* Add GitHub Actions output

Co-authored-by: Mike Vanbuskirk <mike.vanbuskirk@trufflesec.com>
2023-03-28 09:07:26 -07:00
Zachary Rice fb9ae75661 Support for exclude globs at the git log level (#1202)
* init

* seems to be working

* better comment

* rm conditional

* Add more context to exclude-globs description
2023-03-28 10:46:03 -05:00
dependabot[bot] c06dd8a928 Bump cloud.google.com/go/storage from 1.30.0 to 1.30.1 (#1209)
Bumps [cloud.google.com/go/storage](https://github.com/googleapis/google-cloud-go) from 1.30.0 to 1.30.1.
- [Release notes](https://github.com/googleapis/google-cloud-go/releases)
- [Changelog](https://github.com/googleapis/google-cloud-go/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-cloud-go/compare/pubsub/v1.30.0...spanner/v1.30.1)

---
updated-dependencies:
- dependency-name: cloud.google.com/go/storage
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-27 16:15:22 -07:00
ahrav ac19de75bf Delete progress tracking from GCS source (#1190)
* Add in-memory caching lib, used by the GCS source.

* Use cache for tracking progress for the GCS source.

* fix merge issue.

* fix merge issue.

* fix test.

* Fix static check.

* Add test for NewWithData.

* Use cache for tracking progress for the GCS source.

* fix merge issue.

* fix merge issue.

* fix test.

* update comment.

* update comments.

* Use cache for tracking progress for the GCS source.

* fix merge issue.

* fix merge issue.

* fix test.

* remove unused dep.

* address comments.

* Add exists method.

* Use cache for tracking progress for the GCS source.

* fix merge issue.

* fix merge issue.

* fix test.

* rebase.

* fix test.

* Use cache for tracking progress for the GCS source.

* fix merge issue.

* fix merge issue.

* fix test.

* rebase.

* rebase.

* split encode resume by comma.

* update comment.

add comment for shouldCache.

remove redundant return.

* delete old code.

* delete more code.

* update comment.
2023-03-27 10:39:16 -07:00
ahrav b8467ee17e Add Oauth creds to GCS. (#1212) 2023-03-27 10:29:21 -07:00
ahrav 03a534d59f Use correct date format for Date posted. (#1211) 2023-03-27 10:27:28 -07:00
dependabot[bot] 3861eaad33 Bump github.com/rabbitmq/amqp091-go from 1.7.0 to 1.8.0 (#1208)
Bumps [github.com/rabbitmq/amqp091-go](https://github.com/rabbitmq/amqp091-go) from 1.7.0 to 1.8.0.
- [Release notes](https://github.com/rabbitmq/amqp091-go/releases)
- [Changelog](https://github.com/rabbitmq/amqp091-go/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rabbitmq/amqp091-go/compare/v1.7.0...v1.8.0)

---
updated-dependencies:
- dependency-name: github.com/rabbitmq/amqp091-go
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-27 10:08:55 -07:00
dependabot[bot] 05eed21b65 Bump google.golang.org/api from 0.111.0 to 0.114.0 (#1210)
Bumps [google.golang.org/api](https://github.com/googleapis/google-api-go-client) from 0.111.0 to 0.114.0.
- [Release notes](https://github.com/googleapis/google-api-go-client/releases)
- [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.111.0...v0.114.0)

---
updated-dependencies:
- dependency-name: google.golang.org/api
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-27 10:08:33 -07:00
Dustin Decker 31d5655308 Fix OpenAI test (#1186)
* Add OpenAI Detector

* Add OpenAI Detector tests

* Add OpenAI Detector to defaults.go

* Removing references to github detector in tests

* update test

---------

Co-authored-by: Yassine Ilmi <Yassine.Ilmi@thomsonreuters.com>
2023-03-27 10:07:57 -07:00
dependabot[bot] 87c9e0db07 Bump actions/setup-go from 3 to 4 (#1191)
Bumps [actions/setup-go](https://github.com/actions/setup-go) from 3 to 4.
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](https://github.com/actions/setup-go/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/setup-go
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-21 12:50:12 -07:00
ahrav ffbd9c1ead [chore] - log enumeration duration (#1187)
* log enumeration duration.

* use defer to print enumeration duration stat.

* remove temp var.
2023-03-21 09:14:58 -07:00
ahrav 62d44f59f5 Add in-memory caching pkg (#1189)
* Add in-memory caching lib, used by the GCS source.

* Fix static check.

* Add test for NewWithData.

* update comment.

* update comments.

* remove unused dep.

* address comments.

* Add exists method.

* fix test.
2023-03-20 16:16:49 -07:00
dependabot[bot] 1f24889fdd Bump github.com/googleapis/gax-go/v2 from 2.7.1 to 2.8.0 (#1192)
Bumps [github.com/googleapis/gax-go/v2](https://github.com/googleapis/gax-go) from 2.7.1 to 2.8.0.
- [Release notes](https://github.com/googleapis/gax-go/releases)
- [Commits](https://github.com/googleapis/gax-go/compare/v2.7.1...v2.8.0)

---
updated-dependencies:
- dependency-name: github.com/googleapis/gax-go/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-20 11:15:09 -07:00
dependabot[bot] 54a36e333a Bump google.golang.org/protobuf from 1.29.1 to 1.30.0 (#1193)
Bumps [google.golang.org/protobuf](https://github.com/protocolbuffers/protobuf-go) from 1.29.1 to 1.30.0.
- [Release notes](https://github.com/protocolbuffers/protobuf-go/releases)
- [Changelog](https://github.com/protocolbuffers/protobuf-go/blob/master/release.bash)
- [Commits](https://github.com/protocolbuffers/protobuf-go/compare/v1.29.1...v1.30.0)

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-20 11:13:34 -07:00
dependabot[bot] bf36567243 Bump github.com/go-git/go-git/v5 from 5.6.0 to 5.6.1 (#1194)
Bumps [github.com/go-git/go-git/v5](https://github.com/go-git/go-git) from 5.6.0 to 5.6.1.
- [Release notes](https://github.com/go-git/go-git/releases)
- [Commits](https://github.com/go-git/go-git/compare/v5.6.0...v5.6.1)

---
updated-dependencies:
- dependency-name: github.com/go-git/go-git/v5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-20 11:09:35 -07:00
dependabot[bot] 992b8d242d Bump cloud.google.com/go/storage from 1.29.0 to 1.30.0 (#1195)
Bumps [cloud.google.com/go/storage](https://github.com/googleapis/google-cloud-go) from 1.29.0 to 1.30.0.
- [Release notes](https://github.com/googleapis/google-cloud-go/releases)
- [Changelog](https://github.com/googleapis/google-cloud-go/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-cloud-go/compare/pubsub/v1.29.0...spanner/v1.30.0)

---
updated-dependencies:
- dependency-name: cloud.google.com/go/storage
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-20 10:50:04 -07:00
dependabot[bot] 73029c500c Bump go.mongodb.org/mongo-driver from 1.11.2 to 1.11.3 (#1196)
Bumps [go.mongodb.org/mongo-driver](https://github.com/mongodb/mongo-go-driver) from 1.11.2 to 1.11.3.
- [Release notes](https://github.com/mongodb/mongo-go-driver/releases)
- [Commits](https://github.com/mongodb/mongo-go-driver/compare/v1.11.2...v1.11.3)

---
updated-dependencies:
- dependency-name: go.mongodb.org/mongo-driver
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-20 10:06:28 -07:00
garg472 3e4496156c added new detectors and fixed mesibo detector (#1166)
* added new detectors and fixed mesibo detector

* added bscscan.com API detector

* added coinmarketcap detector

* update alchemy

* update blocknative

* update bscscan test

* update cmc test

* update tests

---------

Co-authored-by: Dustin Decker <dustin@trufflesec.com>
2023-03-16 18:57:08 -07:00
Yassine Ilmi d382d5cb1c Add OpenAI API Tokens detector (#1142)
* Add OpenAI Detector

* Add OpenAI Detector tests

* Add OpenAI Detector to defaults.go

* Removing references to github detector in tests
2023-03-16 17:58:22 -07:00
ahrav c617bd7a4e Add resuming capability to GCS source (#1161)
* Add resuming capability to GCS source.

* Handle no auth scans.

* complete resume logic

* Use custom function type.

* remove functions.

* linter.

* fix test.

* fix test.

* Handle concurrent map writes.

* use string as CLI flag for include/exclude.

* handle emtpy buckets.

* Handle enumeration on initial job run.

* Rename stats to attributes.

* remove redundant return.

* If test fails due to 400, that is fine, it's expected.

* Add unauth GCS source type.

* comments.

* update proto.

* Use short flag.

* address comments.
2023-03-16 17:53:42 -07:00
ahrav 6193509098 add support for json service account and service account file. (#1185) 2023-03-16 13:04:36 -07:00
raju-kamble 3c1bb45bfb updating browserstack detector user and key PrefixRegex strings (#1176)
Co-authored-by: raju-bs <raju@browserstack.com>
2023-03-16 08:41:29 -07:00
Miccah 0fe9bf0868 Ignore errors from CustomRegex so the channel doesn't leak (#1149) 2023-03-15 17:26:03 -05:00
Zachary Rice f0b6b5d0d9 add a break statement when iterating through keywords (#1184) 2023-03-15 16:51:03 -05:00
Miccah ef9488c77d [chore] Log git output on error (#1180) 2023-03-15 15:32:29 -05:00
dependabot[bot] e105126227 Bump google.golang.org/protobuf from 1.29.0 to 1.29.1 (#1182)
Bumps [google.golang.org/protobuf](https://github.com/protocolbuffers/protobuf-go) from 1.29.0 to 1.29.1.
- [Release notes](https://github.com/protocolbuffers/protobuf-go/releases)
- [Changelog](https://github.com/protocolbuffers/protobuf-go/blob/master/release.bash)
- [Commits](https://github.com/protocolbuffers/protobuf-go/compare/v1.29.0...v1.29.1)

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-15 12:56:22 -07:00
Tim Walter a7abd6231d Fix git commit date string formatting (#1181) 2023-03-14 22:39:12 -05:00
ahrav 17e8d7030e Add unauth GCS source type. (#1178) 2023-03-13 16:54:45 -07:00
dependabot[bot] af24d36ce8 Bump github.com/xanzy/go-gitlab from 0.80.2 to 0.81.0 (#1172)
Bumps [github.com/xanzy/go-gitlab](https://github.com/xanzy/go-gitlab) from 0.80.2 to 0.81.0.
- [Release notes](https://github.com/xanzy/go-gitlab/releases)
- [Changelog](https://github.com/xanzy/go-gitlab/blob/master/releases_test.go)
- [Commits](https://github.com/xanzy/go-gitlab/compare/v0.80.2...v0.81.0)

---
updated-dependencies:
- dependency-name: github.com/xanzy/go-gitlab
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-13 10:59:49 -05:00
dependabot[bot] 597b618fd9 Bump github.com/fatih/color from 1.13.0 to 1.15.0 (#1174)
Bumps [github.com/fatih/color](https://github.com/fatih/color) from 1.13.0 to 1.15.0.
- [Release notes](https://github.com/fatih/color/releases)
- [Commits](https://github.com/fatih/color/compare/v1.13.0...v1.15.0)

---
updated-dependencies:
- dependency-name: github.com/fatih/color
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-13 09:49:18 -05:00
dependabot[bot] 8076067b30 Bump github.com/googleapis/gax-go/v2 from 2.7.0 to 2.7.1 (#1171)
Bumps [github.com/googleapis/gax-go/v2](https://github.com/googleapis/gax-go) from 2.7.0 to 2.7.1.
- [Release notes](https://github.com/googleapis/gax-go/releases)
- [Commits](https://github.com/googleapis/gax-go/compare/v2.7.0...v2.7.1)

---
updated-dependencies:
- dependency-name: github.com/googleapis/gax-go/v2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-13 09:47:50 -05:00
Dustin Decker 585bd82d47 update integration test excludes (#1169) 2023-03-10 14:41:29 -08:00
trufflesteeeve 2b1c42ceb1 Make slack webhook detector regex more specific (#1168)
* Make slack webhook detector regex more specific

* fixup - add better body contains check
2023-03-10 14:01:10 -08:00
Dylan Ayrey 2f61e4f5aa Update README.md 2023-03-09 08:18:49 -08:00
ahrav cbf299aa77 Add gcs scanning integration (#1153)
* Setup for GCS scanning.

* Update GCS engine w/ projectID req.

* Add concurrency field to gcsManager.

* add errgroup to gcsManager.

* Update gcs manager.

* Use defautl ADC.

* use ADC.'

* Add TOOD.

* add log to iterator completion.

* use a BinaryReader instead of concrete object for channel type.

* initial test for Chunks.

* Add tests for chunking objects.

* Add concurrency.

* update metadata to include content type and acls.

* Add object reading code.

* Add integration test.

* Add entrypoint.

* Add removed wg.Wait().

* remove dead code.

* remove build.

* Remove period from file extension.

* remove used.

* Add comment.

* Setup for GCS scanning.

* Update GCS engine w/ projectID req.

* Add concurrency field to gcsManager.

* add errgroup to gcsManager.

* Update gcs manager.

* Use defautl ADC.

* use ADC.'

* Add TOOD.

* add log to iterator completion.

* use a BinaryReader instead of concrete object for channel type.

* initial test for Chunks.

* Add tests for chunking objects.

* Add concurrency.

* update metadata to include content type and acls.

* Add object reading code.

* Add integration test.

* Add entrypoint.

* Add removed wg.Wait().

* remove dead code.

* remove build.

* remove used.

* Add file type for objects.

* Add check for file type and size.

* Add default file size.

* Add additinoal auth options and remaining CLI flags.

* Handle errors in go routines.

* Handle resuming for buckets.

* Remove redundant words in comment.

* remove ok check on bool check.

* remove extra blank line.

* Add return if handler handles chunk.

* Add comment.

* remove extra blank line.

* cleanup comment.

* Add comment.

* move up fxn.

* go mod tidy.

* Add exclusion to perf testing buckets.

* Handle blocking the channel.

* remove unused const.

* fix tests.

* fix tests.

* Handle gcs manger options better.

* update fxn name.

* Remove arg name.

* ignore buckets in gcsManager test.

* fix test.

* propulate gsManagerOpts.

* inline err check.

* Add readme.

* update readme spelling.

* fix test.
2023-03-07 17:32:04 -08:00
dependabot[bot] 3fdef756f2 Bump github.com/getsentry/sentry-go from 0.18.0 to 0.19.0 (#1157)
Bumps [github.com/getsentry/sentry-go](https://github.com/getsentry/sentry-go) from 0.18.0 to 0.19.0.
- [Release notes](https://github.com/getsentry/sentry-go/releases)
- [Changelog](https://github.com/getsentry/sentry-go/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-go/compare/v0.18.0...v0.19.0)

---
updated-dependencies:
- dependency-name: github.com/getsentry/sentry-go
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-07 10:41:16 -08:00
dependabot[bot] 638ff804f1 Bump github.com/bradleyfalzon/ghinstallation/v2 from 2.1.0 to 2.2.0 (#1148)
Bumps [github.com/bradleyfalzon/ghinstallation/v2](https://github.com/bradleyfalzon/ghinstallation) from 2.1.0 to 2.2.0.
- [Release notes](https://github.com/bradleyfalzon/ghinstallation/releases)
- [Commits](https://github.com/bradleyfalzon/ghinstallation/compare/v2.1.0...v2.2.0)

---
updated-dependencies:
- dependency-name: github.com/bradleyfalzon/ghinstallation/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-06 17:07:44 -08:00
dependabot[bot] d5cbd7b999 Bump github.com/go-git/go-git/v5 from 5.5.2 to 5.6.0 (#1147)
Bumps [github.com/go-git/go-git/v5](https://github.com/go-git/go-git) from 5.5.2 to 5.6.0.
- [Release notes](https://github.com/go-git/go-git/releases)
- [Commits](https://github.com/go-git/go-git/compare/v5.5.2...v5.6.0)

---
updated-dependencies:
- dependency-name: github.com/go-git/go-git/v5
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-06 17:07:14 -08:00
dependabot[bot] c8077145d5 Bump golang.org/x/crypto from 0.6.0 to 0.7.0 (#1158)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.6.0 to 0.7.0.
- [Release notes](https://github.com/golang/crypto/releases)
- [Commits](https://github.com/golang/crypto/compare/v0.6.0...v0.7.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-06 16:11:59 -08:00
ahrav 5c99a1e754 Remove period from file extension (#1154)
* Remove period from file extension.

* Add comment.
2023-03-06 14:49:16 -08:00
Miccah e6846ede54 Support filtering detectors by version (#1150)
* Adjust types to use DetectorID struct

* Parse versions with detector include and exclude input

* Update detectors filter to use version

Co-authored-by: steeeve <steve@trufflesec.com>

* Implement Versioner for github, gitlab, and npm detectors

Co-authored-by: steeeve <steve@trufflesec.com>

---------

Co-authored-by: steeeve <steve@trufflesec.com>
2023-03-02 16:33:56 -06:00
Dustin Decker 4500ac3b10 Release should only run on tags (#1146) 2023-03-02 09:57:38 -08:00
Zachary Rice 4777b77ec6 Keyword optimization (#1144)
* init

* ignore trufflehog binary and added comment

* remove unused keywords in chunk, better comment

* remove keywords from engine struct
2023-03-02 11:32:37 -06:00
zhuwenxing c72840de67 Rename .pre-commit-hooks.yml to .pre-commit-hooks.yaml (#1141)
Signed-off-by: zhuwenxing <wenxing.zhu@zilliz.com>
2023-03-01 09:00:12 -08:00
ahrav aa47e5e248 Only scanned staged git changes. (#1143) 2023-03-01 08:58:36 -08:00
Yassine Ilmi 0cf9139df6 Disable profiler in debug mode and add profile switch (#1136) 2023-02-28 12:49:54 -08:00
ahrav 86370333ec Add pre-commit yml config (#1138)
* Add pre-commit yml config.

* Add --fail flag.
2023-02-28 11:31:24 -08:00
dependabot[bot] 64c163cd90 Bump github.com/stretchr/testify from 1.8.1 to 1.8.2 (#1130)
Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.8.1 to 1.8.2.
- [Release notes](https://github.com/stretchr/testify/releases)
- [Commits](https://github.com/stretchr/testify/compare/v1.8.1...v1.8.2)

---
updated-dependencies:
- dependency-name: github.com/stretchr/testify
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-28 08:46:04 -08:00
Miccah 3870be256c Close response bodies (#1137) 2023-02-28 10:43:00 -06:00
ah̳̕mͭͭͨͩ̐e̘ͬ́͋ͬ̊̓͂d 2315192fda Custom regex parallel verify (#1127)
* Refactor generating CustomRegex results into a helper function

* Added errGroup for createResults, and ensure goroutines are non-blocking

* clean return

---------

Co-authored-by: Miccah Castorina <m.castorina93@gmail.com>
2023-02-28 11:12:24 -05:00
Miccah 6209a80ce1 [chore] Address more linter errors (#1134)
* Address lint errors in detectors

* Update deprecated ioutil call
2023-02-28 10:00:41 -06:00
Miccah 4efe5313f4 [chore] Address lint errors (#1133)
* Update strings.Title to cases.Title

* Migrate go-genproto to google-cloud-go

See: https://github.com/googleapis/google-cloud-go/blob/main/migration.md

* Check error in test

* Check error from sem.Acquire

* Remove unused code
2023-02-27 21:03:47 -06:00
Miccah 7373954ddf [chore] Update docs for individual file scanning (#1132) 2023-02-27 21:03:19 -06:00
Miccah d2d03426ed Implement String for ScanErrors (#1131)
This will concatenate all errors together into a single string. When
possible, it would be better to log the actual errors slice to take
advantage of structured logging.
2023-02-27 21:02:59 -06:00
Miccah dd39848709 Add ability to include and exclude detectors (#1106)
* Add ability to include and exclude detectors

* Trim space before checking for empty items

* Explicitly check for integer overflow

* Use strconv.ParseInt instead of strconv.Atoi

* Address comments
2023-02-27 16:46:45 -06:00
Miccah c5b4d6f28b Support file scanning in filesystem source (#1030)
* Rename directories to paths

* Generate protos

* Add file scanning support to filesystem source

* Add directories back to filesystem proto

* Generate protos

* Combine paths and directories from in source

* Add filesystem filter

* Address comments
2023-02-27 12:15:05 -06:00
Bill Rich ae2d510ced Gitparse message fix (#1125)
* Fix messages being reused

* Add comment about change.
2023-02-23 15:20:54 -08:00
dependabot[bot] 05f6bd369f Bump github.com/xanzy/go-gitlab from 0.78.0 to 0.80.2 (#1117)
Bumps [github.com/xanzy/go-gitlab](https://github.com/xanzy/go-gitlab) from 0.78.0 to 0.80.2.
- [Release notes](https://github.com/xanzy/go-gitlab/releases)
- [Changelog](https://github.com/xanzy/go-gitlab/blob/master/releases_test.go)
- [Commits](https://github.com/xanzy/go-gitlab/compare/v0.78.0...v0.80.2)

---
updated-dependencies:
- dependency-name: github.com/xanzy/go-gitlab
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-22 09:33:16 -08:00
raju-kamble d151c1363e fixing browserstack regex username detection (#1123) 2023-02-22 08:17:48 -08:00
ah̳̕mͭͭͨͩ̐e̘ͬ́͋ͬ̊̓͂d ee5b028c67 Adding initial protos for Google Drive scanner (#1121) 2023-02-22 10:04:46 -05:00
dependabot[bot] 38562df0f6 Bump github.com/rabbitmq/amqp091-go from 1.6.0 to 1.7.0 (#1103)
Bumps [github.com/rabbitmq/amqp091-go](https://github.com/rabbitmq/amqp091-go) from 1.6.0 to 1.7.0.
- [Release notes](https://github.com/rabbitmq/amqp091-go/releases)
- [Changelog](https://github.com/rabbitmq/amqp091-go/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rabbitmq/amqp091-go/compare/v1.6.0...v1.7.0)

---
updated-dependencies:
- dependency-name: github.com/rabbitmq/amqp091-go
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-21 15:36:46 -08:00
dependabot[bot] 4f0e66f064 Bump github.com/TheZeroSlave/zapsentry from 1.12.0 to 1.14.0 (#1118)
Bumps [github.com/TheZeroSlave/zapsentry](https://github.com/TheZeroSlave/zapsentry) from 1.12.0 to 1.14.0.
- [Release notes](https://github.com/TheZeroSlave/zapsentry/releases)
- [Commits](https://github.com/TheZeroSlave/zapsentry/compare/v1.12.0...v1.14.0)

---
updated-dependencies:
- dependency-name: github.com/TheZeroSlave/zapsentry
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-21 15:36:16 -08:00
dependabot[bot] 0b4e3a66b1 Bump go.mongodb.org/mongo-driver from 1.11.1 to 1.11.2 (#1119)
Bumps [go.mongodb.org/mongo-driver](https://github.com/mongodb/mongo-go-driver) from 1.11.1 to 1.11.2.
- [Release notes](https://github.com/mongodb/mongo-go-driver/releases)
- [Commits](https://github.com/mongodb/mongo-go-driver/compare/v1.11.1...v1.11.2)

---
updated-dependencies:
- dependency-name: go.mongodb.org/mongo-driver
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-21 15:35:53 -08:00
dependabot[bot] a293033386 Bump golang.org/x/net from 0.6.0 to 0.7.0 (#1122)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.6.0 to 0.7.0.
- [Release notes](https://github.com/golang/net/releases)
- [Commits](https://github.com/golang/net/compare/v0.6.0...v0.7.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-21 15:35:21 -08:00
raju-kamble d20f43b5c6 fix browserstack detector (#1120)
* fixing browserstack regex username detection

* fixing browserstack regex username detection

* fixing browserstack regex username detection

* fix patterns

* fix patterns

---------

Co-authored-by: raju-bs <raju@browserstack.com>
Co-authored-by: Dustin Decker <dustin@trufflesec.com>
2023-02-21 15:33:16 -08:00
dependabot[bot] 9ef9e9870d Bump golang.org/x/oauth2 from 0.4.0 to 0.5.0 (#1116)
Bumps [golang.org/x/oauth2](https://github.com/golang/oauth2) from 0.4.0 to 0.5.0.
- [Release notes](https://github.com/golang/oauth2/releases)
- [Commits](https://github.com/golang/oauth2/compare/v0.4.0...v0.5.0)

---
updated-dependencies:
- dependency-name: golang.org/x/oauth2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-21 13:42:36 -08:00
Bill Rich f1582aafa9 Drop tabs for filenames with spaces (#1115) 2023-02-16 17:15:32 -08:00
Bill Rich 9158dcaa80 Correctly parse most filenames with ' and ' (#1113) 2023-02-16 14:11:35 -08:00
ahrav 012fdfe3a2 Update helper text for max-archive-size. (#1114) 2023-02-16 13:56:55 -08:00
ahrav ea71756e20 [chore] - archive size helper text (#1110) 2023-02-15 10:08:26 -08:00
ahrav ea40c0f306 Add the unit for max archive size. (#1108) 2023-02-15 09:45:27 -08:00
dependabot[bot] bcecbcd3d4 Bump github.com/getsentry/sentry-go from 0.17.0 to 0.18.0 (#1102)
Bumps [github.com/getsentry/sentry-go](https://github.com/getsentry/sentry-go) from 0.17.0 to 0.18.0.
- [Release notes](https://github.com/getsentry/sentry-go/releases)
- [Changelog](https://github.com/getsentry/sentry-go/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-go/compare/v0.17.0...v0.18.0)

---
updated-dependencies:
- dependency-name: github.com/getsentry/sentry-go
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-14 20:56:35 -06:00
dependabot[bot] 926f490c9f Bump golang.org/x/crypto from 0.5.0 to 0.6.0 (#1101)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.5.0 to 0.6.0.
- [Release notes](https://github.com/golang/crypto/releases)
- [Commits](https://github.com/golang/crypto/compare/v0.5.0...v0.6.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-14 20:55:34 -06:00
dependabot[bot] bd17aa91e3 Bump golang.org/x/text from 0.6.0 to 0.7.0 (#1100)
Bumps [golang.org/x/text](https://github.com/golang/text) from 0.6.0 to 0.7.0.
- [Release notes](https://github.com/golang/text/releases)
- [Commits](https://github.com/golang/text/compare/v0.6.0...v0.7.0)

---
updated-dependencies:
- dependency-name: golang.org/x/text
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-14 20:54:24 -06:00
Miccah 161e499142 [chore] Remove logrus from trufflehog (#1095)
* [chore] Remove logrus from trufflehog

* Minor fixes

* Fix logFatal call

* Fix logrus call
2023-02-14 17:00:07 -06:00
Miccah c6826c4574 Fix nil scan options (#1107) 2023-02-14 12:09:45 -06:00
SAYGIN Metin f2139a7615 Github filter support for exclude and include (#1087)
* test

* Add missing head and base hash back.

---------

Co-authored-by: Ahrav Dutta <ahravdutta02@gmail.com>
2023-02-14 08:40:53 -08:00
Dustin Decker 26c455d302 add more confluence options (#1105) 2023-02-13 13:58:02 -08:00
Mike Vanbuskirk 57983aed4e adds TESTING doc w. steps for local GHA tests (#1093)
make doc wording more explicit
2023-02-13 13:06:50 -05:00
trufflesteeeve 4f13090c01 Remove duplicated detectors (#1092)
In this case just Heroku and LinearAPI. But this includes the Moonclerck
detector, which appears to be a typo that got turned into a separate
detector type.

Co-authored-by: zubairk14 <zubair.khan@trufflesec.com>
2023-02-13 11:44:19 -05:00
Dustin Decker ae14e4506f add smoke test (#1099) 2023-02-11 11:09:36 -08:00
Dustin Decker 0c66d30c1f Revert "Make detectors configurable (#1084)" (#1097)
This reverts commit 67784f6928.
2023-02-11 08:12:13 -08:00
ahrav 67784f6928 Make detectors configurable (#1084)
* Make detectors configurable.

* remove redundant check.

* add number of detectors.

* update comment.

* remove reflect.

* inline key.

* replace name w/ type.

* remove temp var.

* fix test name.

* fix engine start.

* add filter unverified to engine.

* reorder engine args.

* Address comments.

* Add include and exclude.

* update comments.

* add comment.

* add comment.
2023-02-10 16:30:38 -08:00
ahrav c5c8d10d28 [chore] - Remove monolithic config struct (#1091)
* REmove monolithic config struct.

* fix broken test.
2023-02-10 12:43:00 -08:00
Miccah d317ddb51a [chore] Remove logrus from circleci, filesystem, gitlab, and s3 sources (#1089)
* [chore] Remove logrus from circleci, filesystem, gitlab, and s3 sources

* Address comments
2023-02-10 11:02:55 -06:00
dependabot[bot] 29be679370 Bump github.com/joho/godotenv from 1.4.0 to 1.5.1 (#1075)
Bumps [github.com/joho/godotenv](https://github.com/joho/godotenv) from 1.4.0 to 1.5.1.
- [Release notes](https://github.com/joho/godotenv/releases)
- [Commits](https://github.com/joho/godotenv/compare/v1.4.0...v1.5.1)

---
updated-dependencies:
- dependency-name: github.com/joho/godotenv
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-09 20:02:06 -08:00
Miccah 0ce72ccda3 [chore] Remove logrus from github source (#1086)
* [chore] Remove logrus from github source

* Fix handleRateLimit test

* Fix tests
2023-02-09 18:02:04 -06:00
Miccah 58e8c1e4ac [chore] Remove logrus from engine package (#1085) 2023-02-09 16:55:19 -06:00
trufflesteeeve 114f4b6989 Add Type() to detector interface (#1088)
* Add Type() to detector interface

The goal here is to allow the detector type information to be used
without the need for reflection. This could possibly allow us to more
easily inject information into detectors or filter them out if
necessary.

Co-authored-by: ahmed <ahmed.zahran@trufflesec.com>

* remove test detector

---------

Co-authored-by: ahmed <ahmed.zahran@trufflesec.com>
2023-02-09 14:46:03 -08:00
ahrav e47cc2451f Dont pre-allocate errors slice. (#1083) 2023-02-08 17:33:30 -08:00
Miccah 1f0fd91205 Skip repo and continue scanning when encountering an error (#1080) 2023-02-08 11:33:01 -06:00
ahrav 0d73dbe638 [chore] - Add tests for errors (#1071) 2023-02-08 04:15:44 -08:00
Bill Rich 7dd2b74f1f Make archive handler configurable (#1077)
* Make archive handler configurable.

* Use common.IsDone()
2023-02-07 15:25:14 -08:00
Bill Rich b37080e6a5 Add max commit size (#1079)
* Add max commit size

* Use common.IsDone

* Use breaks instead of return
2023-02-07 15:25:00 -08:00
ahrav 3f30216356 Add incclude exclude spaces for confluence source. (#1073) 2023-02-06 08:49:45 -08:00
Bill Rich af6e3f8fdf Pull gitparse config options out of pkg consts (#1072)
* Pull gitparse config options out of pkg consts.

* Adjust naming
2023-02-04 13:19:23 -08:00
Miccah 2d35edfb23 Revert "Add TruffleHog version input for GitHub action (#1064)" (#1068)
This reverts commit 8dedd08d89.
2023-02-03 10:05:21 -06:00
Miccah 8dedd08d89 Add TruffleHog version input for GitHub action (#1064) 2023-02-02 14:18:46 -06:00
ahrav 8be89a593b Handle errors in a thread safe manner (#1052)
* Handle errors in a thread safe manner.

* fix test.

* fix linter.

* address comments.
2023-02-02 11:05:33 -08:00
ahrav 80a68b84c2 update webex detector regex (#1062)
* update webex detector regex.

* fix regex.
2023-02-01 18:37:51 -08:00
ahrav 58b78b6a5a Update float detector with correct User-Agent and regex (#1061)
* Update float detector with correct User-Agent and regex.

* update import order.

* update emial.

* Delete http.go

* add http back.
2023-02-01 09:48:13 -08:00
swdbo a53758c4c4 braintree detector: use production API URL instead of the test sandbox version (#1054) 2023-02-01 08:41:52 -08:00
Dustin Decker 1d3206ed36 add bodyclose linter to help prevent file handle leaks (#1048) 2023-01-31 09:04:37 -08:00
dependabot[bot] 26afa76e7c Bump golang.org/x/oauth2 from 0.3.0 to 0.4.0 (#1039)
Bumps [golang.org/x/oauth2](https://github.com/golang/oauth2) from 0.3.0 to 0.4.0.
- [Release notes](https://github.com/golang/oauth2/releases)
- [Commits](https://github.com/golang/oauth2/compare/v0.3.0...v0.4.0)

---
updated-dependencies:
- dependency-name: golang.org/x/oauth2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-27 17:47:18 -08:00
Miccah 8df9db6ecc Remove false positive detection for CustomRegex (#1050)
Checking for false positives can lead to results being removed before
ever getting the opportunity to verify them. Users are already
responsible for verification of custom detectors, so let's not interfere
with how they choose to use it.
2023-01-27 11:57:10 -06:00
ahrav e85411b59f Add file to confluence proto. (#1049) 2023-01-26 17:34:01 -08:00
Alex Shylo 6e58eb4bbb fix-the-typo (#1046)
change programatic -> programmatic
Ref: https://www.dictionary.com/browse/programmatic
2023-01-26 12:53:46 -08:00
Alexandr Marchenko b29b78c10d filesystem support for exclude and include filters (2nd attemp) (#1033)
* fix filter issue - empty lines should be ignored

* filesystem support for filter exclude

Co-authored-by: Dustin Decker <dustin@trufflesec.com>
2023-01-26 09:33:45 -08:00
dependabot[bot] d4f4b1c73e Bump github.com/rabbitmq/amqp091-go from 1.5.0 to 1.6.0 (#1036)
Bumps [github.com/rabbitmq/amqp091-go](https://github.com/rabbitmq/amqp091-go) from 1.5.0 to 1.6.0.
- [Release notes](https://github.com/rabbitmq/amqp091-go/releases)
- [Changelog](https://github.com/rabbitmq/amqp091-go/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rabbitmq/amqp091-go/compare/v1.5.0...v1.6.0)

---
updated-dependencies:
- dependency-name: github.com/rabbitmq/amqp091-go
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-26 09:27:32 -08:00
Miccah 539be34752 Add openssh-client to trufflehog container (#1045)
* Add openssh-client to docker container

* Add ssh auth example and --rm to all docker run commands
2023-01-26 11:26:03 -06:00
Bill Rich 00ebb2ed64 Full git log when targeting base merge commit (#1044)
* Full git log when targeting merge commits

* Full log is needed whenever base is specified.
2023-01-26 09:17:54 -08:00
Dustin Decker 4ef546a06b fix github integration tests (#1042) 2023-01-25 08:57:39 -08:00
Bill Rich ac1dd23d37 Limit diff size to prevent out of control memory use. (#1035)
* Limit diff size to prevent out of control memory use.

* Group consts
2023-01-23 10:14:10 -08:00
ahrav 2088f030f9 Add location to Teams metadata. (#1034) 2023-01-23 08:12:05 -08:00
ahmed 2060ae1c47 Updated stdout to print results in alphabetical order for consistent output (#1032) 2023-01-19 12:58:50 -05:00
dependabot[bot] 86f80fc5a8 Bump github.com/sergi/go-diff from 1.2.0 to 1.3.1 (#1023)
Bumps [github.com/sergi/go-diff](https://github.com/sergi/go-diff) from 1.2.0 to 1.3.1.
- [Release notes](https://github.com/sergi/go-diff/releases)
- [Commits](https://github.com/sergi/go-diff/compare/v1.2.0...v1.3.1)

---
updated-dependencies:
- dependency-name: github.com/sergi/go-diff
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-17 15:26:29 -06:00
dependabot[bot] c62eb18e6d Bump github.com/xanzy/go-gitlab from 0.77.0 to 0.78.0 (#1024)
Bumps [github.com/xanzy/go-gitlab](https://github.com/xanzy/go-gitlab) from 0.77.0 to 0.78.0.
- [Release notes](https://github.com/xanzy/go-gitlab/releases)
- [Changelog](https://github.com/xanzy/go-gitlab/blob/master/releases_test.go)
- [Commits](https://github.com/xanzy/go-gitlab/compare/v0.77.0...v0.78.0)

---
updated-dependencies:
- dependency-name: github.com/xanzy/go-gitlab
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-17 15:25:04 -06:00
dependabot[bot] 8acd9fdd3b Bump github.com/getsentry/sentry-go from 0.16.0 to 0.17.0 (#1022)
Bumps [github.com/getsentry/sentry-go](https://github.com/getsentry/sentry-go) from 0.16.0 to 0.17.0.
- [Release notes](https://github.com/getsentry/sentry-go/releases)
- [Changelog](https://github.com/getsentry/sentry-go/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-go/compare/v0.16.0...v0.17.0)

---
updated-dependencies:
- dependency-name: github.com/getsentry/sentry-go
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-17 15:20:01 -06:00
ahrav 1621403e11 Add concurrency to CircleCi source (#1029)
* Small cleanup of CircleCi source.

* Add concurrency to circleci.

* merge w/ cleanup branch.

* Rdefine loop var.

* Delete github.go

* reverge file delete.

* Add debug log for scan errors.

* make collecting scanned errors thread safe.

* pre-allocate errors slice.
2023-01-17 12:24:49 -08:00
ahrav 319ae64a02 [chore] - Small cleanup of CircleCi source (#1028)
* Small cleanup of CircleCi source.

* address comments.

* Add context to methods as first param.
2023-01-17 09:36:18 -08:00
Dustin Decker bc27fef7bc remove logger from retryable client, it is not respecting loglevels (#1020) 2023-01-13 15:28:00 -08:00
Miccah 45b02f46d9 Record timestamp when a context was cancelled (#1018) 2023-01-13 12:21:09 -06:00
Cameron Lonsdale 0aa8e1cd98 Use access-token endpoint for validity check (#991) 2023-01-11 19:19:51 -08:00
ahrav 477e2a1332 Update entrypoint (#1013)
* Update entrypoint.

* update comment.

* Call each extra arg on its own.

* Update loop.

* Update extra args.

* Use miccah's magic script.

* Fix path to bash.

* update entrypoint.

* Add bash to Dockerfile.

* update goreleaser dockerfile.
2023-01-11 18:58:05 -08:00
Bill Rich 430d5c764c Rename and export isGitSource (#1016) 2023-01-10 12:51:58 -08:00
Bill Rich 8b2e1d36cf Copy metadata for line number aware sources (#1011)
* Copy metadata for line number aware sources

* Improve style
2023-01-10 09:35:44 -08:00
Clark Brown 864cf00337 Revert "Allow for default value to be used. (#999)" (#1004)
This reverts commit ee6817ad85.
2023-01-09 18:09:58 -06:00
Miccah e5ede17c77 Validate custom regular expressions on detector initialization (#1010)
* Validate custom regular expressions on detector initialization

* Add regex name to error message
2023-01-09 17:30:47 -06:00
Miccah 74831f63d5 Capture callstack of canceled contexts (#979) 2023-01-09 17:27:06 -06:00
ahrav 09d4422cdb Handle invalid regex for custom detector. (#1005)
* Handle invalid regex for custom detector.

* Add comment highlighting invalid regex.
2023-01-09 09:45:30 -08:00
dependabot[bot] 7de0178842 Bump golang.org/x/crypto from 0.4.0 to 0.5.0 (#1009)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.4.0 to 0.5.0.
- [Release notes](https://github.com/golang/crypto/releases)
- [Commits](https://github.com/golang/crypto/compare/v0.4.0...v0.5.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-09 09:32:29 -08:00
dependabot[bot] 6d384ce3e8 Bump github.com/hashicorp/go-retryablehttp from 0.7.1 to 0.7.2 (#1008)
Bumps [github.com/hashicorp/go-retryablehttp](https://github.com/hashicorp/go-retryablehttp) from 0.7.1 to 0.7.2.
- [Release notes](https://github.com/hashicorp/go-retryablehttp/releases)
- [Commits](https://github.com/hashicorp/go-retryablehttp/compare/v0.7.1...v0.7.2)

---
updated-dependencies:
- dependency-name: github.com/hashicorp/go-retryablehttp
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-09 09:31:23 -08:00
dependabot[bot] 0e24d406d5 Bump github.com/go-git/go-git/v5 from 5.5.1 to 5.5.2 (#1007)
Bumps [github.com/go-git/go-git/v5](https://github.com/go-git/go-git) from 5.5.1 to 5.5.2.
- [Release notes](https://github.com/go-git/go-git/releases)
- [Commits](https://github.com/go-git/go-git/compare/v5.5.1...v5.5.2)

---
updated-dependencies:
- dependency-name: github.com/go-git/go-git/v5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-09 09:30:56 -08:00
dependabot[bot] d72c31b8b6 Bump cloud.google.com/go/secretmanager from 1.9.0 to 1.10.0 (#1006)
Bumps [cloud.google.com/go/secretmanager](https://github.com/googleapis/google-cloud-go) from 1.9.0 to 1.10.0.
- [Release notes](https://github.com/googleapis/google-cloud-go/releases)
- [Changelog](https://github.com/googleapis/google-cloud-go/blob/main/documentai/CHANGES.md)
- [Commits](https://github.com/googleapis/google-cloud-go/compare/dlp/v1.9.0...asset/v1.10.0)

---
updated-dependencies:
- dependency-name: cloud.google.com/go/secretmanager
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-09 09:29:26 -08:00
Yassine Ilmi d720c0c0f3 Switch to retryableHttpClient for GitHub AuthN API Client + More Logs (#995)
* Adding missing flags to Readme

* Use retryableHttpClient by default for GitHub

* Adding repoUrl for scanning time log

* Use WithField instead of WithFields

* Updating README with lasted --help output
2023-01-09 09:21:56 -08:00
dependabot[bot] 705c01e5f3 Bump goreleaser/goreleaser-action from 3 to 4 (#980)
Bumps [goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action) from 3 to 4.
- [Release notes](https://github.com/goreleaser/goreleaser-action/releases)
- [Commits](https://github.com/goreleaser/goreleaser-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: goreleaser/goreleaser-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-09 09:20:41 -08:00
Pulkit Aggarwal fc6fd29f3f Fix GitUrl Return (#987)
Co-authored-by: ahrav <ahravdutta02@gmail.com>
2023-01-09 09:17:30 -08:00
ahrav ee6817ad85 Allow for default value to be used. (#999) 2023-01-06 16:05:02 -08:00
Dustin Decker 5f6143f09a Add Circle CI source (#997)
* Add Circle CI source

* remove SHA1 line

* remove trim
2023-01-05 21:44:37 -08:00
ahrav 3fadec950e Make GA action default base an empty string. (#996) 2023-01-05 16:48:07 -08:00
Yassine Ilmi 330a6f7cdc Removing Debug version Println to logrus debug (#993) 2023-01-03 10:36:27 -06:00
ahrav 009756dce6 add proto that was missing. (#986) 2022-12-23 13:27:07 -08:00
Miccah 8859771a2a Remove custom log leveler (#985)
Instead of manually using a log leveler, rely on the global one defined
in the `log` package.
2022-12-20 19:03:53 -06:00
Miccah 130d5ae3ad Add custom regex detector docs (#983) 2022-12-20 18:24:41 -06:00
Miccah f5b83ee2a5 Add configuration parsing and custom detectors to engine (#968)
* Add configuration parsing for custom detectors

* Error on empty filename
2022-12-20 10:14:49 -06:00
dependabot[bot] cc6bd31586 Bump golang.org/x/crypto from 0.3.0 to 0.4.0 (#982)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.3.0 to 0.4.0.
- [Release notes](https://github.com/golang/crypto/releases)
- [Commits](https://github.com/golang/crypto/compare/v0.3.0...v0.4.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-19 15:45:21 -08:00
dependabot[bot] e3b6de0fdc Bump github.com/xanzy/go-gitlab from 0.76.0 to 0.77.0 (#981)
Bumps [github.com/xanzy/go-gitlab](https://github.com/xanzy/go-gitlab) from 0.76.0 to 0.77.0.
- [Release notes](https://github.com/xanzy/go-gitlab/releases)
- [Changelog](https://github.com/xanzy/go-gitlab/blob/master/releases_test.go)
- [Commits](https://github.com/xanzy/go-gitlab/compare/v0.76.0...v0.77.0)

---
updated-dependencies:
- dependency-name: github.com/xanzy/go-gitlab
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-19 15:32:16 -08:00
ahrav 936a139596 Allow using a glob for include list. (#977)
* Allow using a glob for include list.

* Update command flag.

* Make comment more clear.

* update comment.

* Allow scanning repo and org at the same time.
2022-12-16 13:28:16 -08:00
Gonçalo Silva e091fab94f Use Todoist's REST API v2 (#978)
v1 was deprecated on December 5, 2022.
2022-12-14 16:52:19 -08:00
Miccah 861ad057c7 Implement CustomRegex detector (#950)
* Remove verifying successRanges because it is unused in webhook

* Move custom_detectors validation code into its own file

* Initial implementation of custom regex detector

Secret verification is done via webhook.

* Add CustomRegex detector type

* Add upper bound to permutation

* Return early if the context is canceled

* Add headers from configuration

* Add detector name as a key in the JSON body

* Implement faster algorithm for productIndices
2022-12-14 10:26:53 -06:00
Bill Rich 36ca2601e0 Add s3 object count to trace logs (#975)
* Add s3 object count to trace logs

* fix debug level
2022-12-13 16:46:09 -08:00
Miccah 7ac7fdae44 Add more logging for git sources (#974) 2022-12-13 17:51:57 -06:00
dependabot[bot] 6dd0441f6c Bump github.com/envoyproxy/protoc-gen-validate from 0.6.13 to 0.9.1 (#963)
Bumps [github.com/envoyproxy/protoc-gen-validate](https://github.com/envoyproxy/protoc-gen-validate) from 0.6.13 to 0.9.1.
- [Release notes](https://github.com/envoyproxy/protoc-gen-validate/releases)
- [Changelog](https://github.com/bufbuild/protoc-gen-validate/blob/main/.goreleaser.yaml)
- [Commits](https://github.com/envoyproxy/protoc-gen-validate/compare/v0.6.13...v0.9.1)

---
updated-dependencies:
- dependency-name: github.com/envoyproxy/protoc-gen-validate
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-12 16:02:35 -08:00
dependabot[bot] a0b8edd987 Bump github.com/go-git/go-git/v5 from 5.4.2 to 5.5.1 (#972)
Bumps [github.com/go-git/go-git/v5](https://github.com/go-git/go-git) from 5.4.2 to 5.5.1.
- [Release notes](https://github.com/go-git/go-git/releases)
- [Commits](https://github.com/go-git/go-git/compare/v5.4.2...v5.5.1)

---
updated-dependencies:
- dependency-name: github.com/go-git/go-git/v5
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-12 15:56:26 -08:00
ahrav 26befdd1ec [bug] - Handle error when scanning s3 bucket. (#969)
* Handle error when scanning s# bucket.

* move wait outside loop.

* Add logging.

* revert changes.

* remove.

* revert.
2022-12-12 10:10:06 -08:00
dependabot[bot] 4020c4002b Bump github.com/getsentry/sentry-go from 0.15.0 to 0.16.0 (#973)
Bumps [github.com/getsentry/sentry-go](https://github.com/getsentry/sentry-go) from 0.15.0 to 0.16.0.
- [Release notes](https://github.com/getsentry/sentry-go/releases)
- [Changelog](https://github.com/getsentry/sentry-go/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-go/compare/v0.15.0...v0.16.0)

---
updated-dependencies:
- dependency-name: github.com/getsentry/sentry-go
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-12 10:09:44 -08:00
dependabot[bot] aada296ddc Bump go.mongodb.org/mongo-driver from 1.11.0 to 1.11.1 (#971)
Bumps [go.mongodb.org/mongo-driver](https://github.com/mongodb/mongo-go-driver) from 1.11.0 to 1.11.1.
- [Release notes](https://github.com/mongodb/mongo-go-driver/releases)
- [Commits](https://github.com/mongodb/mongo-go-driver/compare/v1.11.0...v1.11.1)

---
updated-dependencies:
- dependency-name: go.mongodb.org/mongo-driver
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-12 10:08:52 -08:00
Bill Rich f3249009f7 Bump github.com/bill-rich/disk-buffer-reader from v0.1.6 to v0.1.7 (#970) 2022-12-09 15:52:41 -08:00
dependabot[bot] 544359eee6 Bump github.com/xanzy/go-gitlab from 0.74.0 to 0.76.0 (#934)
Bumps [github.com/xanzy/go-gitlab](https://github.com/xanzy/go-gitlab) from 0.74.0 to 0.76.0.
- [Release notes](https://github.com/xanzy/go-gitlab/releases)
- [Changelog](https://github.com/xanzy/go-gitlab/blob/master/releases_test.go)
- [Commits](https://github.com/xanzy/go-gitlab/compare/v0.74.0...v0.76.0)

---
updated-dependencies:
- dependency-name: github.com/xanzy/go-gitlab
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-09 17:01:27 -06:00
Dustin Decker 7de9bdd12d Support globbing with ignore repos (#967) 2022-12-09 12:10:42 -08:00
ahrav a72b9feb35 Only scan org with --org flag. (#931) 2022-12-06 16:18:48 -08:00
dependabot[bot] f008d4bead Bump go.uber.org/zap from 1.23.0 to 1.24.0 (#955)
Bumps [go.uber.org/zap](https://github.com/uber-go/zap) from 1.23.0 to 1.24.0.
- [Release notes](https://github.com/uber-go/zap/releases)
- [Changelog](https://github.com/uber-go/zap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/uber-go/zap/compare/v1.23.0...v1.24.0)

---
updated-dependencies:
- dependency-name: go.uber.org/zap
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-06 15:38:28 -08:00
dependabot[bot] 6ee3000e53 Bump github.com/go-sql-driver/mysql from 1.6.0 to 1.7.0 (#954)
Bumps [github.com/go-sql-driver/mysql](https://github.com/go-sql-driver/mysql) from 1.6.0 to 1.7.0.
- [Release notes](https://github.com/go-sql-driver/mysql/releases)
- [Changelog](https://github.com/go-sql-driver/mysql/blob/master/CHANGELOG.md)
- [Commits](https://github.com/go-sql-driver/mysql/compare/v1.6.0...v1.7.0)

---
updated-dependencies:
- dependency-name: github.com/go-sql-driver/mysql
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-06 15:37:32 -08:00
Pulkit Aggarwal d96b7f8468 Update Adding_Detectors_external.md (#957) 2022-12-06 15:36:55 -08:00
Bill Rich 335ce85ce4 Export line number code (#962) 2022-12-06 15:31:15 -08:00
Bill Rich 4e2ce4f6fe Pre-commit not GH action PR (#961) 2022-12-06 14:32:25 -08:00
Bill Rich 33d32d2de4 Don't scan the --since-commit target (#960) 2022-12-06 13:24:27 -08:00
Bill Rich 1a1c2e275e Change chunker test source (#959)
* Change chunker test source

* Emit chunk if the size isn't 0
2022-12-06 12:45:08 -08:00
Bill Rich 9f99ee470d Integration test fixes (#956)
* Adjust repo count for new app

* Fix chunk test count
2022-12-06 08:42:24 -08:00
Dylan Ayrey c3e596e853 Update README.md (#952) 2022-12-02 12:09:25 -08:00
Miccah 2a2bcd93ac Add CustomRegex validation (#939)
* Add validation skeleton

* Add custom detector validation with tests

* Validate and test regex vars

* Implement RegexVarString

* Use RegexVarString for validating regex variables

* Add numerics to the regex variable matching

Co-authored-by: hxnyk <8292703+hxnyk@users.noreply.github.com>
2022-12-02 11:26:22 -06:00
Miccah 5a339b0ca1 Add test for configuring custom regex with webhook verification (#946) 2022-12-02 11:23:20 -06:00
Bill Rich 3b055ce3f9 Add logger to context (#947)
* Add logger to context

* Fatal on no org
2022-11-30 11:10:05 -08:00
Bill Rich c26142d898 Use new diskbufferreader version (#941) 2022-11-28 12:22:30 -08:00
Bill Rich f1ec9e74eb Close files to clean up tmp files (#940) 2022-11-22 13:13:34 -08:00
0xflotus 45ebafff61 fix: small errors (#917) 2022-11-22 09:01:52 -08:00
Bill Rich 79cae3b82b Add newlines when file is split (#937) 2022-11-22 09:01:39 -08:00
Dustin Decker 28dd25beeb S3 scanner improvements (#938) 2022-11-21 19:15:26 -08:00
Miccah 4409210b87 Add custom detectors configuration parsing (#927)
* Add custom_detectors proto

* Generate proto code

* Create custom_detectors package

Also create protoyaml package to test YAML unmarshalling the
configuration.

* Simplify custom_detectors proto by removing connection

* Generate proto code

* Update custom_detectors parsing tests
2022-11-21 15:10:38 -06:00
ahrav 054e98d108 Update slack webhook detector string check (#932)
* Update slack webhook detector check to text.

* remove redunant slashes.
2022-11-21 10:50:23 -08:00
Jessica 6e25664a52 add rambbitmq detector (#936)
* add rambbitmq detector

* use fixed length redaction

Co-authored-by: Dustin Decker <dustin@trufflesec.com>
2022-11-21 10:47:41 -08:00
Dustin Decker b45369cdbb Skip some FTP FPs (#929) 2022-11-21 06:52:21 -08:00
Thiago Lages de Alencar 9757c339d9 Fix error message (#933) 2022-11-20 05:31:11 -08:00
Dustin Decker ae4b387448 add LDAP detector (#896) 2022-11-18 19:45:11 -08:00
Dustin Decker b18edef01a Enable skipping of particular key IDs (#930)
* Enable skipping of particular key IDs

* update test
2022-11-18 09:09:40 -08:00
Miccah 87e7aa3970 Add warning about using trufflehog as a library (#928) 2022-11-18 09:30:51 -06:00
Miccah b3d3f531a4 Return an error from ReadToMax when it panics (#925) 2022-11-16 14:24:05 -06:00
ahrav eb4ff435a5 Use pointer to type. (#926) 2022-11-16 10:36:23 -08:00
ahrav b8be0a64a8 Use pointer to type. (#926) 2022-11-16 10:35:48 -08:00
dependabot[bot] d3b550a2e3 Bump cloud.google.com/go/secretmanager from 1.8.0 to 1.9.0 (#906)
Bumps [cloud.google.com/go/secretmanager](https://github.com/googleapis/google-cloud-go) from 1.8.0 to 1.9.0.
- [Release notes](https://github.com/googleapis/google-cloud-go/releases)
- [Changelog](https://github.com/googleapis/google-cloud-go/blob/main/documentai/CHANGES.md)
- [Commits](https://github.com/googleapis/google-cloud-go/compare/asset/v1.8.0...asset/v1.9.0)

---
updated-dependencies:
- dependency-name: cloud.google.com/go/secretmanager
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-16 08:48:45 -08:00
dependabot[bot] e5ba2c9a3c Bump github.com/getsentry/sentry-go from 0.14.0 to 0.15.0 (#914)
Bumps [github.com/getsentry/sentry-go](https://github.com/getsentry/sentry-go) from 0.14.0 to 0.15.0.
- [Release notes](https://github.com/getsentry/sentry-go/releases)
- [Changelog](https://github.com/getsentry/sentry-go/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-go/compare/v0.14.0...v0.15.0)

---
updated-dependencies:
- dependency-name: github.com/getsentry/sentry-go
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-16 08:47:38 -08:00
dependabot[bot] 1228127d12 Bump google-github-actions/auth from 0 to 1 (#912)
Bumps [google-github-actions/auth](https://github.com/google-github-actions/auth) from 0 to 1.
- [Release notes](https://github.com/google-github-actions/auth/releases)
- [Changelog](https://github.com/google-github-actions/auth/blob/main/CHANGELOG.md)
- [Commits](https://github.com/google-github-actions/auth/compare/v0...v1)

---
updated-dependencies:
- dependency-name: google-github-actions/auth
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-16 08:46:26 -08:00
Miccah 86f9e1288f Initialize scan options if given a nil pointer (#924) 2022-11-15 17:01:59 -06:00
Miccah 696f5c68f4 Log the stack trace and recover object (#923)
* Log the stack trace and recover object

* Remove stderr log
2022-11-15 16:48:02 -06:00
Jessica 3d501975e4 Add filter as scan option to gitlab module's git scan (#919) 2022-11-15 13:02:37 -08:00
Ankush Goel 64cfe4d85e Update github_old.go (#916) 2022-11-15 10:40:55 -08:00
jcastilloixl 741130fb8d Update README.md (#920)
Fixing help subcommand reference to be `--help`, not `-h`, which does not work:

```
$ trufflehog git -h
trufflehog: error: unknown short flag '-h', try --help
$ trufflehog --version
trufflehog 3.16.4
```
2022-11-15 10:40:21 -08:00
Bill Rich d3b24fa592 Replace plain decoder with utf8 (#922) 2022-11-15 09:36:01 -08:00
Johann Saunier 42a82fc7e1 Update Scrapfly API Key Format (#910) 2022-11-11 15:24:17 -05:00
JJ Asghar aead0425d9 Fixed the brew install tap command (#911)
* Fixed the brew install tap command

It seems you need to run the full tap, not just trufflehog.

Signed-off-by: JJ Asghar <awesome@ibm.com>

* Update README.md

Signed-off-by: JJ Asghar <awesome@ibm.com>
Co-authored-by: Dustin Decker <dustin@trufflesec.com>
2022-11-11 15:21:47 -05:00
Ankush Goel bb0fa055dc fixed mailchimp detector (#909)
* fixed mailchimp detector

* Use sane http client

Co-authored-by: Dustin Decker <dustin@trufflesec.com>
2022-11-10 09:47:25 -05:00
kstilwell ecd25784f5 Adding Shopify detector (#875)
* Fixes/work based on testing

* Remove some commented code

* Change how verification happens and grab additional information

* Address linter warnings.

* add shopify detector to default detectors.

Co-authored-by: Dustin Decker <dustin@trufflesec.com>
Co-authored-by: Ahrav Dutta <ahravdutta02@gmail.com>
2022-11-08 16:21:57 -08:00
dependabot[bot] 02ed33d1c1 Bump go.mongodb.org/mongo-driver from 1.10.3 to 1.11.0 (#905) 2022-11-07 07:31:59 -08:00
Dustin Decker 5f0964add8 remove path for deduping URI 2022-11-06 08:12:46 -08:00
ahrav 28983036a0 only write if the filechunk has len > 0. (#903) 2022-11-05 18:19:41 -07:00
trufflesteeeve e8cd2e7fae Add Unknown visibility level (#902) 2022-11-04 14:28:20 -04:00
ahrav dd141fb55f [oc-147] - Add context to all git methods (#901)
* Add context to all git methods.

* remove logrus.

* Add ctx.

* Address comments.

* Add error to clone failing.

* Return error.
2022-11-03 16:36:52 -07:00
Dustin Decker 3a143f095b add option to skip tls verification for confluence (#900) 2022-11-03 13:10:01 -07:00
Miccah ab54ec4072 Check for closed channel in HandleFile (#895)
* Check for closed channel in HandleFile

* Refactor to be more readable

* Fix handler search
2022-11-02 16:35:19 -05:00
Miccah 85f5f3ea7b Add sqlserver integration test and some default params (#891)
* Improve anonymous redaction

* Add sqlserver integration test and some default params
2022-11-02 11:04:49 -05:00
Dustin Decker a7fc12240f Do local URI verification, while attempting to defuse SSRF (#879)
* simplify monogo pattern

* do URI verification locally, while attempting to defuse SSRF

* test SSRF defuse

* simplify err check logic per linter recommendation

* split up detectors

* address comments

* remove unused var
2022-11-01 17:27:24 -07:00
ahrav fe1e475a04 Prevent concurrent read and writes to visibility map. (#892) 2022-11-01 16:20:59 -07:00
dependabot[bot] 2884864cd3 Bump github.com/xanzy/go-gitlab from 0.73.1 to 0.74.0 (#886)
Bumps [github.com/xanzy/go-gitlab](https://github.com/xanzy/go-gitlab) from 0.73.1 to 0.74.0.
- [Release notes](https://github.com/xanzy/go-gitlab/releases)
- [Changelog](https://github.com/xanzy/go-gitlab/blob/master/releases_test.go)
- [Commits](https://github.com/xanzy/go-gitlab/compare/v0.73.1...v0.74.0)

---
updated-dependencies:
- dependency-name: github.com/xanzy/go-gitlab
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-31 13:01:29 -05:00
dependabot[bot] 2ac483da1f Bump github.com/TheZeroSlave/zapsentry from 1.11.0 to 1.12.0 (#887)
Bumps [github.com/TheZeroSlave/zapsentry](https://github.com/TheZeroSlave/zapsentry) from 1.11.0 to 1.12.0.
- [Release notes](https://github.com/TheZeroSlave/zapsentry/releases)
- [Commits](https://github.com/TheZeroSlave/zapsentry/compare/v1.11.0...v1.12.0)

---
updated-dependencies:
- dependency-name: github.com/TheZeroSlave/zapsentry
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-31 12:59:56 -05:00
ahrav fe029b1098 [THOG-793] - Return all unverified results (#856)
* Remove the check to filter and return only a single unverified result.

* Revert "Remove the check to filter and return only a single unverified result."

This reverts commit 494e432803.

* Add new CLI flag to filter unverified results.
2022-10-31 09:36:10 -07:00
Alexandr Marchenko c91158d8f7 remove updates check from github action (#883)
Because action uses the latest image there is no need to check for updates each time`
2022-10-31 09:34:33 -07:00
dependabot[bot] 6696c85d32 Bump cloud.google.com/go/secretmanager from 1.7.0 to 1.8.0 (#888)
Bumps [cloud.google.com/go/secretmanager](https://github.com/googleapis/google-cloud-go) from 1.7.0 to 1.8.0.
- [Release notes](https://github.com/googleapis/google-cloud-go/releases)
- [Changelog](https://github.com/googleapis/google-cloud-go/blob/main/documentai/CHANGES.md)
- [Commits](https://github.com/googleapis/google-cloud-go/compare/asset/v1.7.0...asset/v1.8.0)

---
updated-dependencies:
- dependency-name: cloud.google.com/go/secretmanager
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-31 08:59:58 -07:00
dependabot[bot] 4a458c9eab Bump github.com/mattn/go-sqlite3 from 1.14.15 to 1.14.16 (#889)
Bumps [github.com/mattn/go-sqlite3](https://github.com/mattn/go-sqlite3) from 1.14.15 to 1.14.16.
- [Release notes](https://github.com/mattn/go-sqlite3/releases)
- [Commits](https://github.com/mattn/go-sqlite3/compare/v1.14.15...v1.14.16)

---
updated-dependencies:
- dependency-name: github.com/mattn/go-sqlite3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-31 08:59:36 -07:00
910 changed files with 17037 additions and 3816 deletions
+19
View File
@@ -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`
+1 -1
View File
@@ -17,7 +17,7 @@ jobs:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/setup-go@v3
- uses: actions/setup-go@v4
with:
go-version: '1.18'
- uses: actions/checkout@v3
+2 -9
View File
@@ -1,16 +1,9 @@
name: Release
# on:
# push:
# tags:
# - 'v*'
on:
push:
tags:
- v*
branches:
- main
permissions:
contents: write
@@ -40,11 +33,11 @@ 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'
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v3
uses: goreleaser/goreleaser-action@v4
with:
distribution: goreleaser
version: latest
+3 -2
View File
@@ -7,13 +7,14 @@ 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'
- name: Checkout code
@@ -27,4 +28,4 @@ jobs:
with:
path: ./
base: ${{ github.event.repository.default_branch }}
head: HEAD
head: HEAD
+24
View File
@@ -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
+1 -1
View File
@@ -16,7 +16,7 @@ jobs:
name: Run Snifftest
runs-on: ubuntu-latest
steps:
- uses: actions/setup-go@v3
- uses: actions/setup-go@v4
with:
go-version: '1.18'
- uses: actions/checkout@v3
+4 -4
View File
@@ -17,13 +17,13 @@ jobs:
id-token: 'write'
steps:
- name: Install Go
uses: actions/setup-go@v3
uses: actions/setup-go@v4
with:
go-version: '1.18'
- name: Checkout code
uses: actions/checkout@v3
- id: 'auth'
uses: 'google-github-actions/auth@v0'
uses: 'google-github-actions/auth@v1'
with:
workload_identity_provider: 'projects/811013774421/locations/global/workloadIdentityPools/github-pool/providers/github-provider'
service_account: 'github-ci-external@trufflehog-testing.iam.gserviceaccount.com'
@@ -36,13 +36,13 @@ jobs:
id-token: 'write'
steps:
- name: Install Go
uses: actions/setup-go@v3
uses: actions/setup-go@v4
with:
go-version: '1.18'
- name: Checkout code
uses: actions/checkout@v3
- id: 'auth'
uses: 'google-github-actions/auth@v0'
uses: 'google-github-actions/auth@v1'
with:
workload_identity_provider: 'projects/811013774421/locations/global/workloadIdentityPools/github-pool/providers/github-provider'
service_account: 'github-ci-external@trufflehog-testing.iam.gserviceaccount.com'
+4 -1
View File
@@ -1,4 +1,7 @@
.idea
dist
.env
*.test
*.test
# binary
trufflehog
+6
View File
@@ -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
View File
@@ -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 -1
View File
@@ -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/
+2 -2
View File
@@ -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 --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
+159 -38
View File
@@ -28,7 +28,7 @@ https://join.slack.com/t/trufflehog-community/shared_invite/zt-pw2qbi43-Aa86hkii
![GitHub scanning demo](https://storage.googleapis.com/truffle-demos/non-interactive.svg)
```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
@@ -36,7 +36,8 @@ docker run -it -v "$PWD:/pwd" trufflesecurity/trufflehog:latest github --org=tru
### Example 1: Scan a repo for only verified secrets
Command:
```
```bash
trufflehog git https://github.com/trufflesecurity/test_keys --only-verified
```
@@ -59,14 +60,15 @@ Timestamp: 2022-06-16 10:17:40 -0700 PDT
### Example 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
Command:
```
```bash
trufflehog git https://github.com/trufflesecurity/test_keys --only-verified --json
```
@@ -77,18 +79,37 @@ Expected output:
```
### Example 4: Scan an S3 bucket for verified keys
```
```bash
trufflehog s3 --bucket=<bucket name> --only-verified
```
### Example 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
```
### Example 6: Scan individual files or directories
```bash
trufflehog filesystem path/to/file1.txt path/to/file2.txt path/to/dir
```
### Example 7: Scan GCS buckets for verified secrets.
```bash
trufflehog gcs --project-id=<project-ID> --cloud-environment --only-verified
```
### 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
+ Unathenticated GitHub scans have rate limits. To improve your rate limits, include the `--token` flag with a personal access token
+ 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?
@@ -96,19 +117,19 @@ trufflehog s3 --bucket=<bucket name> --only-verified
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, and S3**.
- We've also added native **support for scanning GitHub, GitLab, filesystems, S3, 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.
## 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
```
```bash
git clone https://github.com/trufflesecurity/trufflehog.git
cd trufflehog; go install
@@ -119,21 +140,21 @@ cd trufflehog; go install
### 3. Docker
> Note: Apple M1 hardware users should run with `docker run --platform linux/arm64` for better performance.
> Note: Apple M1 hardware users should run with `docker run --rm --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
docker run --rm -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 avilable, but there is not container image for that.
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
docker run --rm --platform linux/arm64 -it -v "$PWD:/pwd" trufflesecurity/trufflehog:latest github --repo https://github.com/trufflesecurity/test_keys
```
### 4. Pip (help wanted)
@@ -147,8 +168,7 @@ Help with setting up this packaging would be appreciated!
### 5. Brew
```bash
brew tap trufflesecurity/trufflehog
brew install trufflehog
brew install trufflesecurity/trufflehog/trufflehog
```
## Usage
@@ -159,11 +179,13 @@ 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
- file and stdin (coming soon)
- circleci
- GCS (Google Cloud Storage)
- stdin (coming soon)
Each subcommand can have options that you can see with the `-h` flag provided to the sub command:
Each subcommand can have options that you can see with the `--help` flag provided to the sub command:
```
$ trufflehog git --help
@@ -173,26 +195,20 @@ Find credentials in git repositories.
Flags:
--help Show context-sensitive help (also try --help-long and --help-man).
--debug Run in debug mode
--version Prints trufflehog version.
--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=1 Number of concurrent workers.
--concurrency=10 Number of concurrent workers.
--no-verification Don't verify the results.
--only-verified Only output verified results.
--filter-unverified Only output first unverified result per chunk per detector if there are more than one results.
--config=CONFIG Path to configuration file.
--print-avg-detector-time Print the average time spent on each detector.
--no-update Don't check for updates.
-i, --include-paths=INCLUDE-PATHS
Path to file with newline separated regexes for files to include in scan.
-x, --exclude-paths=EXCLUDE-PATHS
Path to file with newline separated regexes for files to exclude in scan.
--since-commit=SINCE-COMMIT
Commit to start scan from.
--branch=BRANCH Branch to scan.
--max-depth=MAX-DEPTH Maximum depth of commits to scan.
--allow No-op flag for backwards compat.
--entropy No-op flag for backwards compat.
--regex No-op flag for backwards compat.
--fail Exit with code 183 if results are found.
--version Show application version.
Args:
<uri> Git repository URL. https://, file://, or ssh:// schema expected.
@@ -214,7 +230,7 @@ Exit Codes:
Try scanning an entire GitHub organization with the following:
```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
```
### TruffleHog OSS Github Action
@@ -224,9 +240,9 @@ docker run -it -v "$PWD:/pwd" trufflesecurity/trufflehog:latest github --org=tru
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.
@@ -269,13 +285,111 @@ repos:
- id: trufflehog
name: TruffleHog
description: Detect secrets in your data.
entry: bash -c 'trufflehog git file://. --only-verified --fail'
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 --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)
Trufflehog supports detection and verification of custom regular expressions.
For detection, at least one **regular expression** and **keyword** is required.
A **keyword** is a fixed literal string identifier that appears in or around
the regex to be detected. To allow maximum flexibility for verification, a
webhook is used containing the regular expression matches.
Trufflehog will send a JSON POST request containing the regex matches to a
configured webhook endpoint. If the endpoint responds with a `200 OK` response
status code, the secret is considered verified.
**NB:** This feature is alpha and subject to change.
### Regex Detector Example
```yaml
# config.yaml
detectors:
- name: hog detector
keywords:
- hog
regex:
adjective: hogs are (\S+)
verify:
- endpoint: http://localhost:8000/
# unsafe must be set if the endpoint is HTTP
unsafe: true
headers:
- 'Authorization: super secret authorization header'
```
```
$ trufflehog filesystem /tmp --config config.yaml --only-verified
🐷🔑🐷 TruffleHog. Unearth your secrets. 🐷🔑🐷
Found verified result 🐷🔑
Detector Type: CustomRegex
Decoder Type: PLAIN
Raw result: hogs are cool
File: /tmp/hog-facts.txt
```
#### 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
verification server for the above `config.yaml` file.
```python
import json
from http.server import BaseHTTPRequestHandler, HTTPServer
AUTH_HEADER = 'super secret authorization header'
class Verifier(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(405)
self.end_headers()
def do_POST(self):
try:
if self.headers['Authorization'] != AUTH_HEADER:
self.send_response(401)
self.end_headers()
return
# read the body
length = int(self.headers['Content-Length'])
request = json.loads(self.rfile.read(length))
self.log_message("%s", request)
# check the match
if request['hog detector']['adjective'][-1] == 'cool':
self.send_response(200)
self.end_headers()
else:
# any other response besides 200
self.send_response(406)
self.end_headers()
except Exception:
self.send_response(400)
self.end_headers()
with HTTPServer(('', 8000), Verifier) as server:
try:
server.serve_forever()
except KeyboardInterrupt:
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
This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].
@@ -299,3 +413,10 @@ We have published some [documentation and tooling to get started on adding new s
## 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
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/
We take the revenue from the enterprise product to fund more awesome open source projects that the whole community can benefit from.
+7 -1
View File
@@ -8,7 +8,8 @@ inputs:
required: true
base:
description: Start scanning from here (usually main branch).
required: true
required: false
default: ''
head:
description: Scan commits until here (usually dev branch).
required: false
@@ -16,6 +17,9 @@ inputs:
default: ''
description: Extra args to be passed to the trufflehog cli.
required: false
outputs:
results:
description: 'Trufflehog scan results'
branding:
icon: "shield"
color: "green"
@@ -30,4 +34,6 @@ runs:
- --branch
- ${{ inputs.head }}
- --fail
- --no-update
- --github-actions
- ${{ inputs.extra_args }}
+6 -4
View File
@@ -1,5 +1,7 @@
#!/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")
results=$(/usr/bin/trufflehog "${@: 1: $#-1}" "${extra_args[@]}" | tee /dev/tty)
echo "results=$results" >> $GITHUB_OUTPUT
+71 -52
View File
@@ -9,62 +9,70 @@ replace github.com/zricethezav/gitleaks/v8 => github.com/trufflesecurity/gitleak
replace github.com/gitleaks/go-gitdiff => github.com/trufflesecurity/go-gitdiff v0.7.6-zombies2
require (
cloud.google.com/go/secretmanager v1.7.0
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.11.0
github.com/TheZeroSlave/zapsentry v1.14.0
github.com/aws/aws-sdk-go v1.44.83
github.com/bill-rich/disk-buffer-reader v0.1.4
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.2.0
github.com/crewjam/rfc5424 v0.1.0
github.com/denisenkom/go-mssqldb v0.12.3
github.com/envoyproxy/protoc-gen-validate v0.6.13
github.com/fatih/color v1.13.0
github.com/envoyproxy/protoc-gen-validate v0.9.1
github.com/fatih/color v1.15.0
github.com/felixge/fgprof v0.9.3
github.com/getsentry/sentry-go v0.14.0
github.com/getsentry/sentry-go v0.19.0
github.com/go-errors/errors v1.4.2
github.com/go-git/go-git/v5 v5.4.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/zapr v1.2.3
github.com/go-sql-driver/mysql v1.6.0
github.com/go-redis/redis v6.15.9+incompatible
github.com/go-sql-driver/mysql v1.7.0
github.com/gobwas/glob v0.2.3
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.8.0
github.com/gorilla/mux v1.8.0
github.com/h2non/filetype v1.1.3
github.com/hashicorp/go-retryablehttp v0.7.1
github.com/joho/godotenv v1.4.0
github.com/hashicorp/go-retryablehttp v0.7.2
github.com/jlaffaye/ftp v0.1.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/mattn/go-sqlite3 v1.14.15
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/rs/zerolog v1.28.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.73.1
go.mongodb.org/mongo-driver v1.10.3
go.uber.org/zap v1.23.0
golang.org/x/crypto v0.0.0-20220926161630-eccd6366d1be
github.com/xanzy/go-gitlab v0.81.0
go.mongodb.org/mongo-driver v1.11.3
go.uber.org/zap v1.24.0
golang.org/x/crypto v0.7.0
golang.org/x/exp v0.0.0-20221018205818-5c77f4b2bbd7
golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4
google.golang.org/genproto v0.0.0-20220920201722-2b89144ce006
google.golang.org/protobuf v1.28.1
golang.org/x/oauth2 v0.6.0
golang.org/x/sync v0.1.0
golang.org/x/text v0.8.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 v0.104.0 // indirect
cloud.google.com/go/compute v1.7.0 // indirect
cloud.google.com/go/iam v0.3.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
@@ -72,67 +80,78 @@ require (
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
github.com/Azure/go-autorest/logger v0.2.1 // indirect
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
github.com/Microsoft/go-winio v0.4.16 // indirect
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 // indirect
github.com/acomagu/bufpipe v1.0.3 // 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-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/benbjohnson/clock v1.1.0 // indirect
github.com/cloudflare/circl v1.1.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dimchansky/utfbom v1.1.1 // indirect
github.com/dsnet/compress v0.0.1 // indirect
github.com/emirpasic/gods v1.12.0 // indirect
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.3.1 // 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.1.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.1.0 // indirect
github.com/googleapis/gax-go/v2 v2.5.1 // 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
github.com/imdario/mergo v0.3.12 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/imdario/mergo v0.3.13 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/jpillora/s3 v1.1.4 // indirect
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect
github.com/kevinburke/ssh_config v1.2.0 // indirect
github.com/klauspost/compress v1.15.11 // 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.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
github.com/therootcompany/xz v1.0.1 // indirect
github.com/ulikunitz/xz v0.5.10 // indirect
github.com/xanzy/ssh-agent v0.3.0 // indirect
github.com/xanzy/ssh-agent v0.3.3 // indirect
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
github.com/xdg-go/scram v1.1.1 // indirect
github.com/xdg-go/stringprep v1.0.3 // indirect
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
go.opencensus.io v0.23.0 // indirect
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.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
golang.org/x/net v0.0.0-20221002022538-bcab6841153b // indirect
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
golang.org/x/tools v0.1.12 // indirect
google.golang.org/api v0.96.0 // indirect
golang.org/x/mod v0.8.0 // indirect
golang.org/x/net v0.8.0 // indirect
golang.org/x/sys v0.6.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.6.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.49.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
)
+198 -645
View File
File diff suppressed because it is too large Load Diff
+6 -2
View File
@@ -49,8 +49,12 @@ If you think that something should be included outside of these guidelines, plea
```bash
go run hack/generate/generate.go detector <DetectorType enum name>
```
3. Add Secret Scanner
3. Complete the secret detector.
Add the secret scanner to the `pkg/engine/defaults.go` file like `github.com/trufflesecurity/trufflehog/v3/pkg/detectors/<detector_name>` and
`<detector_name>.Scanner{},`
4. Complete the secret detector.
The previous step templated a boilerplate + some example code as a package in the `pkg/detectors` folder for you to work on.
The secret detector can be completed with these general steps:
@@ -104,4 +108,4 @@ Now, the detector test should attempt to load the given env key from that file.
### Testing a detector
```bash
go test ./pkg/detectors/<detector> -tags=detectors
```
```
+5 -3
View File
@@ -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>>")
}
+38 -19
View File
@@ -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)
path, repo, err := git.CloneRepoUsingUnauthenticated(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 {
+305 -104
View File
@@ -2,7 +2,6 @@ package main
import (
"fmt"
"log"
"net/http"
_ "net/http/pprof"
"os"
@@ -13,16 +12,21 @@ 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/pb/detectorspb"
"github.com/trufflesecurity/trufflehog/v3/pkg/sources"
"github.com/trufflesecurity/trufflehog/v3/pkg/sources/git"
"github.com/trufflesecurity/trufflehog/v3/pkg/updater"
@@ -30,24 +34,34 @@ 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()
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()
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()
@@ -55,26 +69,34 @@ 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()
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
gitlabScanEndpoint = gitlabScan.Flag("endpoint", "GitLab endpoint.").Default("https://gitlab.com").String()
gitlabScanRepos = gitlabScan.Flag("repo", "GitLab repo url. You can repeat this flag. Leave empty to scan all repos accessible with provided credential. Example: https://gitlab.com/org/repo.git").Strings()
gitlabScanToken = gitlabScan.Flag("token", "GitLab token. Can be provided with environment variable GITLAB_TOKEN.").Envar("GITLAB_TOKEN").Required().String()
gitlabScanEndpoint = gitlabScan.Flag("endpoint", "GitLab endpoint.").Default("https://gitlab.com").String()
gitlabScanRepos = gitlabScan.Flag("repo", "GitLab repo url. You can repeat this flag. Leave empty to scan all repos accessible with provided credential. Example: https://gitlab.com/org/repo.git").Strings()
gitlabScanToken = gitlabScan.Flag("token", "GitLab token. Can be provided with environment variable GITLAB_TOKEN.").Envar("GITLAB_TOKEN").Required().String()
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()
@@ -82,12 +104,27 @@ var (
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()
syslogProtocol = syslogScan.Flag("protocol", "Protocol to listen on. udp or tcp").String()
syslogTLSCert = syslogScan.Flag("cert", "Path to TLS cert.").String()
syslogTLSKey = syslogScan.Flag("key", "Path to TLS key.").String()
syslogFormat = syslogScan.Flag("format", "Log format. Can be rfc3164 or rfc5424").String()
circleCiScan = cli.Command("circleci", "Scan CircleCI")
circleCiScanToken = circleCiScan.Flag("token", "CircleCI token. Can also be provided with environment variable").Envar("CIRCLECI_TOKEN").Required().String()
)
func init() {
@@ -102,22 +139,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:
logrus.SetLevel(logrus.TraceLevel)
logrus.Debugf("running version %s", version.BuildVersion)
log.SetLevel(5)
case *debug:
logrus.SetLevel(logrus.DebugLevel)
logrus.Debugf("running version %s", version.BuildVersion)
default:
logrus.SetLevel(logrus.InfoLevel)
log.SetLevel(2)
}
}
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,
@@ -135,14 +176,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 {
fmt.Println("trufflehog " + 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
@@ -155,111 +198,226 @@ 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")
}
}()
}
ctx := context.TODO()
conf := &config.Config{}
if *configFilename != "" {
var err error
conf, err = config.Read(*configFilename)
if err != nil {
logFatal(err, "error parsing the provided configuration file")
}
}
if *archiveMaxSize != 0 {
handlers.SetArchiveMaxSize(int(*archiveMaxSize))
}
if *archiveMaxDepth != 0 {
handlers.SetArchiveMaxDepth(*archiveMaxDepth)
}
if *archiveTimeout != 0 {
handlers.SetArchiveMaxTimeout(*archiveTimeout)
}
// Build include and exclude detector filter sets.
var includeDetectorTypes, excludeDetectorTypes map[detectorspb.DetectorType]config.DetectorID
{
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")
}
includeDetectorTypes = detectorTypeToMap(includeList)
excludeDetectorTypes = detectorTypeToMap(excludeList)
}
includeFilter := func(d detectors.Detector) bool {
id, ok := includeDetectorTypes[d.Type()]
if id.Version == 0 {
return ok
}
versionD, ok := d.(detectors.Versioner)
if !ok {
// Error: version provided but not a detectors.Versioner
logFatal(
fmt.Errorf("version provided but detector does not have a version"),
"invalid include list detector configuration",
"detector", id,
)
}
return versionD.Version() == id.Version
}
excludeFilter := func(d detectors.Detector) bool {
id, ok := excludeDetectorTypes[d.Type()]
if id.Version == 0 {
return !ok
}
versionD, ok := d.(detectors.Versioner)
if !ok {
// Error: version provided but not a detectors.Versioner
logFatal(
fmt.Errorf("version provided but detector does not have a version"),
"invalid exclude list detector configuration",
"detector", id,
)
}
return versionD.Version() != id.Version
}
e := engine.Start(ctx,
engine.WithConcurrency(*concurrency),
engine.WithDecoders(decoders.DefaultDecoders()...),
engine.WithDetectors(!*noVerification, engine.DefaultDetectors()...),
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():
repoPath, remote, err = git.PrepareRepoSinceCommit(*gitScanURI, *gitScanSinceCommit)
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 {
log.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
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():
gitlab := func(c *sources.Config) {
c.Endpoint = *gitlabScanEndpoint
c.Token = *gitlabScanToken
c.Repos = *gitlabScanRepos
filter, err := common.FilterFromFiles(*gitlabScanIncludePaths, *gitlabScanExcludePaths)
if err != nil {
logFatal(err, "could not create filter")
}
if err = e.ScanGitLab(ctx, sources.NewConfig(gitlab)); err != nil {
logrus.WithError(err).Fatal("Failed to scan GitLab.")
cfg := sources.GitlabConfig{
Endpoint: *gitlabScanEndpoint,
Token: *gitlabScanToken,
Repos: *gitlabScanRepos,
Filter: filter,
}
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,
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 {
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
@@ -278,28 +436,50 @@ func run(state overseer.State) {
}
foundResults = true
var err error
switch {
case *jsonLegacy:
output.PrintLegacyJSON(&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() {
@@ -311,3 +491,24 @@ func printAverageDetectorTime(e *engine.Engine) {
fmt.Fprintf(os.Stderr, "%s: %s\n", detectorName, avgDuration)
}
}
// 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)
}
}
func detectorTypeToMap(detectors []config.DetectorID) map[detectorspb.DetectorType]config.DetectorID {
output := make(map[detectorspb.DetectorType]config.DetectorID, len(detectors))
for _, d := range detectors {
output[d.ID] = d
}
return output
}
+20
View File
@@ -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
}
+85
View File
@@ -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, ",")
}
+153
View File
@@ -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
View File
@@ -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)
+7
View File
@@ -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
+1 -3
View File
@@ -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)
}
+8 -2
View File
@@ -18,7 +18,10 @@ func Recover(ctx context.Context) {
if eventID := sentry.CurrentHub().Recover(err); eventID != nil {
ctx.Logger().Info("panic captured", "event_id", *eventID)
}
fmt.Fprint(os.Stderr, panicStack)
ctx.Logger().Error(fmt.Errorf("panic"), "recovered from panic",
"stack-trace", panicStack,
"recover", err,
)
if !sentry.Flush(time.Second * 5) {
ctx.Logger().Info("sentry flush failed")
}
@@ -32,7 +35,10 @@ func RecoverWithExit(ctx context.Context) {
if eventID := sentry.CurrentHub().Recover(err); eventID != nil {
ctx.Logger().Info("panic captured", "event_id", *eventID)
}
fmt.Fprint(os.Stderr, panicStack)
ctx.Logger().Error(fmt.Errorf("panic"), "recovered from panic before exiting",
"stack-trace", panicStack,
"recover", err,
)
if !sentry.Flush(time.Second * 5) {
ctx.Logger().Info("sentry flush failed")
}
+1 -1
View File
@@ -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 }
+5 -12
View File
@@ -2,24 +2,17 @@ package common
import (
"path/filepath"
"github.com/h2non/filetype"
"strings"
)
var (
KB, MB, GB, TB, PB = 1e3, 1e6, 1e9, 1e12, 1e15
IGNORED_EXTENSIONS = []string{"pdf", "mp4", "avi", "mpeg", "mpg", "mov", "wmv", "m4p", "swf", "mp2", "flv", "vob", "webm", "hdv", "3gp", "ogg", "mp3", "wav", "flac", "tif", "tiff", "jpg", "jpeg", "png", "gif", "zip", "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, data []byte) bool {
if filepath.Ext(filename) == "" {
//no sepcified extension, check mimetype
if filetype.IsArchive(data[:256]) {
return true
}
}
for _, ext := range IGNORED_EXTENSIONS {
if filepath.Ext(filename) == ext {
func SkipFile(filename string) bool {
for _, ext := range IgnoredExtensions {
if strings.TrimPrefix(filepath.Ext(filename), ".") == ext {
return true
}
}
+36
View File
@@ -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")
}
}
+45
View File
@@ -0,0 +1,45 @@
package config
import (
"os"
"github.com/trufflesecurity/trufflehog/v3/pkg/custom_detectors"
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/custom_detectorspb"
"github.com/trufflesecurity/trufflehog/v3/pkg/protoyaml"
)
// Config holds user supplied configuration.
type Config struct {
Detectors []detectors.Detector
}
// Read parses a given filename into a Config.
func Read(filename string) (*Config, error) {
input, err := os.ReadFile(filename)
if err != nil {
return nil, err
}
return NewYAML(input)
}
// NewYAML parses the given YAML data into a Config.
func NewYAML(input []byte) (*Config, error) {
// Parse the raw YAML into a structure.
var messages custom_detectorspb.CustomDetectors
if err := protoyaml.UnmarshalStrict(input, &messages); err != nil {
return nil, err
}
// Convert the structured YAML into detectors.
var detectors []detectors.Detector
for _, detectorConfig := range messages.Detectors {
detector, err := custom_detectors.NewWebhookCustomRegex(detectorConfig)
if err != nil {
return nil, err
}
detectors = append(detectors, detector)
}
return &Config{
Detectors: detectors,
}, nil
}
+183
View File
@@ -0,0 +1,183 @@
package config
import (
"fmt"
"sort"
"strconv"
"strings"
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
}
}
}
type DetectorID struct {
ID dpb.DetectorType
Version int
}
// 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)
}
+47
View File
@@ -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)
})
}
}
+42 -6
View File
@@ -2,6 +2,8 @@ package context
import (
"context"
"fmt"
"runtime/debug"
"time"
"github.com/go-logr/logr"
@@ -38,6 +40,7 @@ type logCtx struct {
// Embed context.Context to get all methods for free.
context.Context
log logr.Logger
err *error
}
// Logger returns a structured logger.
@@ -45,6 +48,13 @@ func (l logCtx) Logger() logr.Logger {
return l.log
}
func (l logCtx) Err() error {
if l.err != nil && *l.err != nil {
return *l.err
}
return l.Context.Err()
}
// Background returns context.Background with a default logger.
func Background() Context {
return logCtx{
@@ -64,30 +74,33 @@ func TODO() Context {
// WithCancel returns context.WithCancel with the log object propagated.
func WithCancel(parent Context) (Context, context.CancelFunc) {
ctx, cancel := context.WithCancel(parent)
return logCtx{
lCtx := logCtx{
log: parent.Logger(),
Context: ctx,
}, cancel
}
return captureCancelCallstack(lCtx, cancel)
}
// WithDeadline returns context.WithDeadline with the log object propagated and
// the deadline added to the structured log values.
func WithDeadline(parent Context, d time.Time) (Context, context.CancelFunc) {
ctx, cancel := context.WithDeadline(parent, d)
return logCtx{
lCtx := logCtx{
log: parent.Logger().WithValues("deadline", d),
Context: ctx,
}, cancel
}
return captureCancelCallstack(lCtx, cancel)
}
// WithTimeout returns context.WithTimeout with the log object propagated and
// the timeout added to the structured log values.
func WithTimeout(parent Context, timeout time.Duration) (Context, context.CancelFunc) {
ctx, cancel := context.WithTimeout(parent, timeout)
return logCtx{
lCtx := logCtx{
log: parent.Logger().WithValues("timeout", timeout),
Context: ctx,
}, cancel
}
return captureCancelCallstack(lCtx, cancel)
}
// WithValue returns context.WithValue with the log object propagated and
@@ -136,3 +149,26 @@ func AddLogger(parent context.Context) Context {
func SetDefaultLogger(l logr.Logger) {
defaultLogger = l
}
// captureCancelCallstack is a helper function to capture the callstack where
// the cancel function was first called.
func captureCancelCallstack(ctx logCtx, f context.CancelFunc) (Context, context.CancelFunc) {
if ctx.err == nil {
var err error
ctx.err = &err
}
return ctx, func() {
// We must check Err() before calling f() since f() sets the error.
// If there's already an error, do nothing special.
if ctx.Err() != nil {
f()
return
}
f()
// Set the error with the stacktrace if the err pointer is non-nil.
*ctx.err = fmt.Errorf(
"%w (canceled at %v\n%s)",
ctx.Err(), time.Now(), string(debug.Stack()),
)
}
}
+43
View File
@@ -169,3 +169,46 @@ func TestDiscardLogger(t *testing.T) {
ctx := Background()
ctx.Logger().Info("this shouldn't panic")
}
func TestErrCallstack(t *testing.T) {
c, cancel := WithCancel(Background())
ctx := c.(logCtx)
cancel()
select {
case <-ctx.Done():
assert.Contains(t, ctx.Err().Error(), "TestErrCallstack")
case <-time.After(1 * time.Second):
assert.Fail(t, "context should be done")
}
}
func TestErrCallstackTimeout(t *testing.T) {
ctx, cancel := WithTimeout(Background(), 10*time.Millisecond)
defer cancel()
select {
case <-ctx.Done():
// Deadline exceeded errors will not have a callstack from the cancel
// function.
assert.NotContains(t, ctx.Err().Error(), "TestErrCallstackTimeout")
case <-time.After(1 * time.Second):
assert.Fail(t, "context should be done")
}
}
func TestErrCallstackTimeoutCancel(t *testing.T) {
ctx, cancel := WithTimeout(Background(), 10*time.Millisecond)
var err error
select {
case <-ctx.Done():
err = ctx.Err()
case <-time.After(1 * time.Second):
assert.Fail(t, "context should be done")
}
// Calling cancel after deadline exceeded should not overwrite the original
// error.
cancel()
assert.Equal(t, err, ctx.Err())
}
+245
View File
@@ -0,0 +1,245 @@
package custom_detectors
import (
"bytes"
"context"
"encoding/json"
"net/http"
"regexp"
"strings"
"github.com/trufflesecurity/trufflehog/v3/pkg/common"
"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
// permutating each regex match to protect the scanner from doing too much work
// for poorly defined regexps.
const maxTotalMatches = 100
// customRegexWebhook is a CustomRegex with webhook validation that is
// guaranteed to be valid (assuming the data is not changed after
// initialization).
type customRegexWebhook struct {
*custom_detectorspb.CustomRegex
}
// Ensure the Scanner satisfies the interface at compile time.
var _ detectors.Detector = (*customRegexWebhook)(nil)
// NewWebhookCustomRegex initializes and validates a customRegexWebhook. An
// unexported type is intentionally returned here to ensure the values have
// been validated.
func NewWebhookCustomRegex(pb *custom_detectorspb.CustomRegex) (*customRegexWebhook, error) {
// TODO: Return all validation errors.
if err := ValidateKeywords(pb.Keywords); err != nil {
return nil, err
}
if err := ValidateRegex(pb.Regex); err != nil {
return nil, err
}
for _, verify := range pb.Verify {
if err := ValidateVerifyEndpoint(verify.Endpoint, verify.Unsafe); err != nil {
return nil, err
}
if err := ValidateVerifyHeaders(verify.Headers); err != nil {
return nil, err
}
}
// TODO: Copy only necessary data out of pb.
return &customRegexWebhook{pb}, nil
}
var httpClient = common.SaneHttpClient()
func (c *customRegexWebhook) FromData(ctx context.Context, verify bool, data []byte) (results []detectors.Result, err error) {
dataStr := string(data)
regexMatches := make(map[string][][]string, len(c.GetRegex()))
// Find all submatches for each regex.
for name, regex := range c.GetRegex() {
regex, err := regexp.Compile(regex)
if err != nil {
// This will only happen if the regex is invalid.
return nil, err
}
regexMatches[name] = regex.FindAllStringSubmatch(dataStr, -1)
}
// Permutate each individual match.
// {
// "foo": [["match1"]]
// "bar": [["match2"], ["match3"]]
// }
// becomes
// [
// {"foo": ["match1"], "bar": ["match2"]},
// {"foo": ["match1"], "bar": ["match3"]},
// ]
matches := permutateMatches(regexMatches)
g := new(errgroup.Group)
// 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)
})
}
// 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,
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()
}
// productIndices produces a permutation of indices for each length. Example:
// productIndices(3, 2) -> [[0 0] [1 0] [2 0] [0 1] [1 1] [2 1]]. It returns
// a slice of length no larger than maxTotalMatches.
func productIndices(lengths ...int) [][]int {
count := 1
for _, l := range lengths {
count *= l
}
if count == 0 {
return nil
}
if count > maxTotalMatches {
count = maxTotalMatches
}
results := make([][]int, count)
for i := 0; i < count; i++ {
j := 1
result := make([]int, 0, len(lengths))
for _, l := range lengths {
result = append(result, (i/j)%l)
j *= l
}
results[i] = result
}
return results
}
// permutateMatches converts the list of all regex matches into all possible
// permutations selecting one from each named entry in the map. For example:
// {"foo": [matchA, matchB], "bar": [matchC]} becomes
//
// [{"foo": matchA, "bar": matchC}, {"foo": matchB, "bar": matchC}]
func permutateMatches(regexMatches map[string][][]string) []map[string][]string {
// Get a consistent order for names and their matching lengths.
// The lengths are used in calculating the permutation so order matters.
names := make([]string, 0, len(regexMatches))
lengths := make([]int, 0, len(regexMatches))
for key, value := range regexMatches {
names = append(names, key)
lengths = append(lengths, len(value))
}
// Permutate all the indices for each match. For example, if "foo" has
// [matchA, matchB] and "bar" has [matchC], we will get indices [0 0] [1 0].
permutationIndices := productIndices(lengths...)
// Build {"foo": matchA, "bar": matchC} and {"foo": matchB, "bar": matchC}
// from the indices.
var matches []map[string][]string
for _, permutation := range permutationIndices {
candidate := make(map[string][]string, len(permutationIndices))
for i, name := range names {
candidate[name] = regexMatches[name][permutation[i]]
}
matches = append(matches, candidate)
}
return matches
}
func (c *customRegexWebhook) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_CustomRegex
}
@@ -0,0 +1,215 @@
package custom_detectors
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/custom_detectorspb"
"github.com/trufflesecurity/trufflehog/v3/pkg/protoyaml"
)
func TestCustomRegexTemplateParsing(t *testing.T) {
testCustomRegexTemplateYaml := `name: Internal bi tool
keywords:
- secret_v1_
- pat_v2_
regex:
id_pat_example: ([a-zA-Z0-9]{32})
secret_pat_example: ([a-zA-Z0-9]{32})
verify:
- endpoint: http://localhost:8000/{id_pat_example}
unsafe: true
headers:
- 'Authorization: Bearer {secret_pat_example.0}'
successRanges:
- 200-250
- '288'`
var got custom_detectorspb.CustomRegex
assert.NoError(t, protoyaml.UnmarshalStrict([]byte(testCustomRegexTemplateYaml), &got))
assert.Equal(t, "Internal bi tool", got.Name)
assert.Equal(t, []string{"secret_v1_", "pat_v2_"}, got.Keywords)
assert.Equal(t, map[string]string{
"id_pat_example": "([a-zA-Z0-9]{32})",
"secret_pat_example": "([a-zA-Z0-9]{32})",
}, got.Regex)
assert.Equal(t, 1, len(got.Verify))
assert.Equal(t, "http://localhost:8000/{id_pat_example}", got.Verify[0].Endpoint)
assert.Equal(t, true, got.Verify[0].Unsafe)
assert.Equal(t, []string{"Authorization: Bearer {secret_pat_example.0}"}, got.Verify[0].Headers)
assert.Equal(t, []string{"200-250", "288"}, got.Verify[0].SuccessRanges)
}
func TestCustomRegexWebhookParsing(t *testing.T) {
testCustomRegexWebhookYaml := `name: Internal bi tool
keywords:
- secret_v1_
- pat_v2_
regex:
id_pat_example: ([a-zA-Z0-9]{32})
secret_pat_example: ([a-zA-Z0-9]{32})
verify:
- endpoint: http://localhost:8000/
unsafe: true
headers:
- 'Authorization: Bearer token'`
var got custom_detectorspb.CustomRegex
assert.NoError(t, protoyaml.UnmarshalStrict([]byte(testCustomRegexWebhookYaml), &got))
assert.Equal(t, "Internal bi tool", got.Name)
assert.Equal(t, []string{"secret_v1_", "pat_v2_"}, got.Keywords)
assert.Equal(t, map[string]string{
"id_pat_example": "([a-zA-Z0-9]{32})",
"secret_pat_example": "([a-zA-Z0-9]{32})",
}, got.Regex)
assert.Equal(t, 1, len(got.Verify))
assert.Equal(t, "http://localhost:8000/", got.Verify[0].Endpoint)
assert.Equal(t, true, got.Verify[0].Unsafe)
assert.Equal(t, []string{"Authorization: Bearer token"}, got.Verify[0].Headers)
}
// TestCustomDetectorsParsing tests the full `detectors` configuration.
func TestCustomDetectorsParsing(t *testing.T) {
// TODO: Support both template and webhook.
testYamlConfig := `detectors:
- name: Internal bi tool
keywords:
- secret_v1_
- pat_v2_
regex:
id_pat_example: ([a-zA-Z0-9]{32})
secret_pat_example: ([a-zA-Z0-9]{32})
verify:
- endpoint: http://localhost:8000/
unsafe: true
headers:
- 'Authorization: Bearer token'`
var messages custom_detectorspb.CustomDetectors
assert.NoError(t, protoyaml.UnmarshalStrict([]byte(testYamlConfig), &messages))
assert.Equal(t, 1, len(messages.Detectors))
got := messages.Detectors[0]
assert.Equal(t, "Internal bi tool", got.Name)
assert.Equal(t, []string{"secret_v1_", "pat_v2_"}, got.Keywords)
assert.Equal(t, map[string]string{
"id_pat_example": "([a-zA-Z0-9]{32})",
"secret_pat_example": "([a-zA-Z0-9]{32})",
}, got.Regex)
assert.Equal(t, 1, len(got.Verify))
assert.Equal(t, "http://localhost:8000/", got.Verify[0].Endpoint)
assert.Equal(t, true, got.Verify[0].Unsafe)
assert.Equal(t, []string{"Authorization: Bearer token"}, got.Verify[0].Headers)
}
func TestFromData_InvalidRegEx(t *testing.T) {
c := &customRegexWebhook{
&custom_detectorspb.CustomRegex{
Name: "Internal bi tool",
Keywords: []string{"secret_v1_", "pat_v2_"},
Regex: map[string]string{
"test": "!!?(?:?)[a-zA-Z0-9]{32}", // invalid regex
},
},
}
_, err := c.FromData(context.Background(), false, []byte("test"))
assert.Error(t, err)
}
func TestProductIndices(t *testing.T) {
tests := []struct {
name string
input []int
want [][]int
}{
{
name: "zero",
input: []int{3, 0},
want: nil,
},
{
name: "one input",
input: []int{3},
want: [][]int{{0}, {1}, {2}},
},
{
name: "two inputs",
input: []int{3, 2},
want: [][]int{
{0, 0}, {1, 0}, {2, 0},
{0, 1}, {1, 1}, {2, 1},
},
},
{
name: "three inputs",
input: []int{3, 2, 3},
want: [][]int{
{0, 0, 0}, {1, 0, 0}, {2, 0, 0},
{0, 1, 0}, {1, 1, 0}, {2, 1, 0},
{0, 0, 1}, {1, 0, 1}, {2, 0, 1},
{0, 1, 1}, {1, 1, 1}, {2, 1, 1},
{0, 0, 2}, {1, 0, 2}, {2, 0, 2},
{0, 1, 2}, {1, 1, 2}, {2, 1, 2},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := productIndices(tt.input...)
assert.Equal(t, tt.want, got)
})
}
}
func TestProductIndicesMax(t *testing.T) {
got := productIndices(2, 3, 4, 5, 6)
assert.GreaterOrEqual(t, 2*3*4*5*6, maxTotalMatches)
assert.Equal(t, maxTotalMatches, len(got))
}
func TestPermutateMatches(t *testing.T) {
tests := []struct {
name string
input map[string][][]string
want []map[string][]string
}{
{
name: "two matches",
input: map[string][][]string{"foo": {{"matchA"}, {"matchB"}}, "bar": {{"matchC"}}},
want: []map[string][]string{
{"foo": {"matchA"}, "bar": {"matchC"}},
{"foo": {"matchB"}, "bar": {"matchC"}},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := permutateMatches(tt.input)
assert.Equal(t, tt.want, got)
})
}
}
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)
}
}
+44
View File
@@ -0,0 +1,44 @@
package custom_detectors
import (
"regexp"
"strconv"
"strings"
)
// nameGroupRegex matches `{ name . group }` ignoring any whitespace.
var nameGroupRegex = regexp.MustCompile(`{\s*([a-zA-Z0-9-_]+)\s*(\.\s*[0-9]*)?\s*}`)
// RegexVarString is a string with embedded {name.group} variables. A name may
// only contain alphanumeric, hyphen, and underscore characters. Group is
// optional but if provided it must be a non-negative integer. If the group is
// omitted it defaults to 0.
type RegexVarString struct {
original string
// map from name to group
variables map[string]int
}
func NewRegexVarString(original string) RegexVarString {
variables := make(map[string]int)
matches := nameGroupRegex.FindAllStringSubmatch(original, -1)
for _, match := range matches {
name, group := match[1], 0
// The second match will start with a period followed by any number
// of whitespace.
if len(match[2]) > 1 {
g, err := strconv.Atoi(strings.TrimSpace(match[2][1:]))
if err != nil {
continue
}
group = g
}
variables[name] = group
}
return RegexVarString{
original: original,
variables: variables,
}
}
@@ -0,0 +1,76 @@
package custom_detectors
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestVarString(t *testing.T) {
tests := []struct {
name string
input string
wantVars map[string]int
}{
{
name: "empty",
input: "{}",
wantVars: map[string]int{},
},
{
name: "no subgroup",
input: "{hello}",
wantVars: map[string]int{
"hello": 0,
},
},
{
name: "with subgroup",
input: "{hello.123}",
wantVars: map[string]int{
"hello": 123,
},
},
{
name: "subgroup with spaces",
input: "{\thell0 . 123 }",
wantVars: map[string]int{
"hell0": 123,
},
},
{
name: "multiple groups",
input: "foo {bar} {bazz.buzz} {buzz.2}",
wantVars: map[string]int{
"bar": 0,
"buzz": 2,
},
},
{
name: "nested groups",
input: "{foo {bar}}",
wantVars: map[string]int{
"bar": 0,
},
},
{
name: "decimal without number",
input: "{foo.}",
wantVars: map[string]int{
"foo": 0,
},
},
{
name: "negative number",
input: "{foo.-1}",
wantVars: map[string]int{},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := NewRegexVarString(tt.input)
assert.Equal(t, tt.input, got.original)
assert.Equal(t, tt.wantVars, got.variables)
})
}
}
+109
View File
@@ -0,0 +1,109 @@
package custom_detectors
import (
"fmt"
"regexp"
"strconv"
"strings"
)
func ValidateKeywords(keywords []string) error {
if len(keywords) == 0 {
return fmt.Errorf("no keywords")
}
for _, keyword := range keywords {
if len(keyword) == 0 {
return fmt.Errorf("empty keyword")
}
}
return nil
}
func ValidateRegex(regex map[string]string) error {
if len(regex) == 0 {
return fmt.Errorf("no regex")
}
for name, reg := range regex {
if _, err := regexp.Compile(reg); err != nil {
return fmt.Errorf("regex '%s': %w", name, err)
}
}
return nil
}
func ValidateVerifyEndpoint(endpoint string, unsafe bool) error {
if len(endpoint) == 0 {
return fmt.Errorf("no endpoint")
}
if strings.HasPrefix(endpoint, "http://") && !unsafe {
return fmt.Errorf("http endpoint must have unsafe=true")
}
return nil
}
func ValidateVerifyHeaders(headers []string) error {
for _, header := range headers {
if !strings.Contains(header, ":") {
return fmt.Errorf("header %q must contain a colon", header)
}
}
return nil
}
func ValidateVerifyRanges(ranges []string) error {
const httpLowerRange = 100
const httpUpperRange = 599
for _, successRange := range ranges {
if !strings.Contains(successRange, "-") {
httpCode, err := strconv.Atoi(successRange)
if err != nil {
return fmt.Errorf("unable to convert http code to int %q", successRange)
}
if httpCode < httpLowerRange || httpCode > httpUpperRange {
return fmt.Errorf("invalid http status code %q", successRange)
}
continue
}
httpRange := strings.Split(successRange, "-")
if len(httpRange) != 2 {
return fmt.Errorf("invalid range format %q", successRange)
}
lowerBound, err := strconv.Atoi(httpRange[0])
if err != nil {
return fmt.Errorf("unable to convert lower bound to int %q", successRange)
}
upperBound, err := strconv.Atoi(httpRange[1])
if err != nil {
return fmt.Errorf("unable to convert upper bound to int %q", successRange)
}
if lowerBound > upperBound {
return fmt.Errorf("lower bound greater than upper bound on range %q", successRange)
}
if lowerBound < httpLowerRange || upperBound > httpUpperRange {
return fmt.Errorf("invalid http status code range %q", successRange)
}
}
return nil
}
func ValidateRegexVars(regex map[string]string, body ...string) error {
for _, b := range body {
matches := NewRegexVarString(b).variables
for match := range matches {
if _, ok := regex[match]; !ok {
return fmt.Errorf("body %q contains an unknown variable", b)
}
}
}
return nil
}
+234
View File
@@ -0,0 +1,234 @@
package custom_detectors
import "testing"
func TestCustomDetectorsKeywordValidation(t *testing.T) {
tests := []struct {
name string
input []string
wantErr bool
}{
{
name: "Test empty list of keywords",
input: []string{},
wantErr: true,
},
{
name: "Test empty keyword",
input: []string{""},
wantErr: true,
},
{
name: "Test valid keywords",
input: []string{"hello", "world"},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := ValidateKeywords(tt.input)
if (got != nil && !tt.wantErr) || (got == nil && tt.wantErr) {
t.Errorf("ValidateKeywords() error = %v, wantErr %v", got, tt.wantErr)
}
})
}
}
func TestCustomDetectorsRegexValidation(t *testing.T) {
tests := []struct {
name string
input map[string]string
wantErr bool
}{
{
name: "Test list of keywords",
input: map[string]string{
"id_pat_example": "([a-zA-Z0-9]{32})",
},
wantErr: false,
},
{
name: "Test empty list of keywords",
input: map[string]string{},
wantErr: true,
},
{
name: "Test invalid regex",
input: map[string]string{
"test": "!!?(?:?)[a-zA-Z0-9]{32}",
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := ValidateRegex(tt.input)
if (got != nil && !tt.wantErr) || (got == nil && tt.wantErr) {
t.Errorf("ValidateRegex() error = %v, wantErr %v", got, tt.wantErr)
}
})
}
}
func TestCustomDetectorsVerifyEndpointValidation(t *testing.T) {
tests := []struct {
name string
endpoint string
unsafe bool
wantErr bool
}{
{
name: "Test http endpoint with unsafe flag",
endpoint: "http://localhost:8000/{id_pat_example}",
unsafe: true,
wantErr: false,
},
{
name: "Test http endpoint without unsafe flag",
endpoint: "http://localhost:8000/{id_pat_example}",
unsafe: false,
wantErr: true,
},
{
name: "Test https endpoint with unsafe flag",
endpoint: "https://localhost:8000/{id_pat_example}",
unsafe: true,
wantErr: false,
},
{
name: "Test https endpoint without unsafe flag",
endpoint: "https://localhost:8000/{id_pat_example}",
unsafe: false,
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := ValidateVerifyEndpoint(tt.endpoint, tt.unsafe)
if (got != nil && !tt.wantErr) || (got == nil && tt.wantErr) {
t.Errorf("ValidateVerifyEndpoint() error = %v, wantErr %v", got, tt.wantErr)
}
})
}
}
func TestCustomDetectorsVerifyHeadersValidation(t *testing.T) {
tests := []struct {
name string
headers []string
wantErr bool
}{
{
name: "Test single header",
headers: []string{"Authorization: Bearer {secret_pat_example.0}"},
wantErr: false,
},
{
name: "Test invalid header",
headers: []string{"Hello world"},
wantErr: true,
},
{
name: "Test ugly header",
headers: []string{"Hello:::::::world::hi:"},
wantErr: false,
},
{
name: "Test empty header",
headers: []string{},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := ValidateVerifyHeaders(tt.headers)
if (got != nil && !tt.wantErr) || (got == nil && tt.wantErr) {
t.Errorf("ValidateVerifyHeaders() error = %v, wantErr %v", got, tt.wantErr)
}
})
}
}
func TestCustomDetectorsVerifyRangeValidation(t *testing.T) {
tests := []struct {
name string
ranges []string
wantErr bool
}{
{
name: "Test multiple mixed ranges",
ranges: []string{"200", "300-350"},
wantErr: false,
},
{
name: "Test invalid non-number range",
ranges: []string{"hi"},
wantErr: true,
},
{
name: "Test invalid lower to upper range",
ranges: []string{"200-100"},
wantErr: true,
},
{
name: "Test invalid http range",
ranges: []string{"400-1000"},
wantErr: true,
},
{
name: "Test multiple ranges with invalid inputs",
ranges: []string{"322", "hello-world", "100-200"},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := ValidateVerifyRanges(tt.ranges)
if (got != nil && !tt.wantErr) || (got == nil && tt.wantErr) {
t.Errorf("ValidateVerifyRanges() error = %v, wantErr %v", got, tt.wantErr)
}
})
}
}
func TestCustomDetectorsVerifyRegexVarsValidation(t *testing.T) {
tests := []struct {
name string
regex map[string]string
body string
wantErr bool
}{
{
name: "Regex defined but not used in body",
regex: map[string]string{"id": "[0-9]{1,10}", "id_pat_example": "([a-zA-Z0-9]{32})"},
body: "hello world",
wantErr: false,
},
{
name: "Regex defined and is used in body",
regex: map[string]string{"id": "[0-9]{1,10}", "id_pat_example": "([a-zA-Z0-9]{32})"},
body: "hello world {id}",
wantErr: false,
},
{
name: "Regex var in body but not defined",
regex: map[string]string{"id": "[0-9]{1,10}", "id_pat_example": "([a-zA-Z0-9]{32})"},
body: "hello world {hello}",
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := ValidateRegexVars(tt.regex, tt.body)
if (got != nil && !tt.wantErr) || (got == nil && tt.wantErr) {
t.Errorf("ValidateRegexVars() error = %v, wantErr %v", got, tt.wantErr)
}
})
}
}
+1 -1
View File
@@ -6,7 +6,7 @@ import (
func DefaultDecoders() []Decoder {
return []Decoder{
&Plain{},
&UTF8{},
&Base64{},
}
}
-14
View File
@@ -1,14 +0,0 @@
package decoders
import (
"github.com/trufflesecurity/trufflehog/v3/pkg/sources"
)
// Ensure the Decoder satisfies the interface at compile time
var _ Decoder = (*Plain)(nil)
type Plain struct{}
func (d *Plain) FromChunk(chunk *sources.Chunk) *sources.Chunk {
return chunk
}
+44
View File
@@ -0,0 +1,44 @@
package decoders
import (
"bytes"
"unicode/utf8"
"github.com/trufflesecurity/trufflehog/v3/pkg/sources"
)
type UTF8 struct{}
func (d *UTF8) FromChunk(chunk *sources.Chunk) *sources.Chunk {
if chunk == nil || len(chunk.Data) == 0 {
return nil
}
if !utf8.Valid(chunk.Data) {
chunk.Data = extractSubstrings(chunk.Data)
return chunk
}
return chunk
}
// extractSubstrings performs similarly to the strings binutil,
// 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 {
// https://www.rapidtables.com/code/text/ascii-table.html
// split on anything that is not ascii space through tilde
return !(r > 31 && r < 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)
}
}
return bytes.Join(keep, []byte("\n"))
}
+87
View File
@@ -0,0 +1,87 @@
package decoders
import (
"testing"
"github.com/kylelemons/godebug/pretty"
"github.com/trufflesecurity/trufflehog/v3/pkg/sources"
)
func TestUTF8_FromChunk(t *testing.T) {
type args struct {
chunk *sources.Chunk
}
tests := []struct {
name string
d *UTF8
args args
want *sources.Chunk
wantErr bool
}{
{
name: "successful UTF8 decode",
d: &UTF8{},
args: args{
chunk: &sources.Chunk{Data: []byte("plain 'ol chunk that should decode successfully")},
},
want: &sources.Chunk{Data: []byte("plain 'ol chunk that should decode successfully")},
wantErr: false,
},
{
name: "successful binary decode",
d: &UTF8{},
args: args{
chunk: &sources.Chunk{Data: []byte("\xf0\x28\x8c\x28 not-entirely utf8 chunk that should decode successfully")},
},
want: &sources.Chunk{Data: []byte("( not-entirely utf8 chunk that should decode successfully")},
wantErr: false,
},
{
name: "unsuccessful decode",
d: &UTF8{},
args: args{
chunk: nil,
},
want: nil,
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
d := &UTF8{}
got := d.FromChunk(tt.args.chunk)
if got != nil && tt.want != nil {
if diff := pretty.Compare(string(got.Data), string(tt.want.Data)); diff != "" {
t.Errorf("%s: Plain.FromChunk() diff: (-got +want)\n%s", tt.name, diff)
}
} else {
if diff := pretty.Compare(got, tt.want); diff != "" {
t.Errorf("%s: Plain.FromChunk() diff: (-got +want)\n%s", tt.name, diff)
}
}
})
}
}
var testBytes = []byte(`some words with random spaces and
newlines with
arbitrary length
of
hey
the lines themselves.
and
short
words
that
go
away.`)
func Benchmark_extractSubstrings(b *testing.B) {
for i := 0; i < b.N; i++ {
extractSubstrings(testBytes)
}
}
+6 -3
View File
@@ -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()
@@ -70,5 +69,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
results = append(results, s1)
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_Abbysale
}
+5 -1
View File
@@ -70,5 +70,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
results = append(results, s1)
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_Abstract
}
+5 -1
View File
@@ -81,5 +81,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
results = append(results, s1)
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_AbuseIPDB
}
+5 -1
View File
@@ -68,5 +68,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
results = append(results, s1)
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_Accuweather
}
+5 -1
View File
@@ -68,5 +68,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
results = append(results, s1)
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_AdafruitIO
}
+5 -1
View File
@@ -80,5 +80,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_AdobeIO
}
+5 -1
View File
@@ -78,5 +78,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
}
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_Adzuna
}
+5 -1
View File
@@ -81,5 +81,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_Aeroworkflow
}
+5 -1
View File
@@ -81,5 +81,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
}
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_Agora
}
+5 -1
View File
@@ -71,5 +71,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
results = append(results, s1)
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_Aha
}
@@ -85,5 +85,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_AirbrakeProjectKey
}
@@ -68,5 +68,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
results = append(results, s1)
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_AirbrakeUserKey
}
+5 -1
View File
@@ -71,5 +71,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
results = append(results, s1)
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_Airship
}
@@ -79,5 +79,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
}
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_AirtableApiKey
}
+5 -1
View File
@@ -71,5 +71,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
results = append(results, s1)
}
return detectors.CleanResults(results), nil
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()
@@ -70,5 +68,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
results = append(results, s1)
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_Alchemy
}
+119
View File
@@ -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)
}
}
})
}
}
+5 -1
View File
@@ -74,5 +74,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
results = append(results, s1)
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_Alconost
}
+5 -1
View File
@@ -80,5 +80,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
}
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_Alegra
}
+5 -1
View File
@@ -72,5 +72,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
results = append(results, s1)
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_AletheiaApi
}
@@ -78,5 +78,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
results = append(results, s1)
}
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_AlgoliaAdminKey
}
+5 -1
View File
@@ -128,5 +128,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
}
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_Alibaba
}
+5 -1
View File
@@ -69,5 +69,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
results = append(results, s1)
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_AlienVault
}
+5 -1
View File
@@ -75,5 +75,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
results = append(results, s1)
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_Allsports
}
+5 -1
View File
@@ -86,5 +86,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
}
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_Amadeus
}
+5 -1
View File
@@ -70,5 +70,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
results = append(results, s1)
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_Ambee
}
@@ -79,5 +79,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
}
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_AmplitudeApiKey
}
+5 -1
View File
@@ -80,5 +80,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
}
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_Anypoint
}
+5 -1
View File
@@ -69,5 +69,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
results = append(results, s1)
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_Apacta
}
+5 -1
View File
@@ -80,9 +80,13 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
results = append(results, s1)
}
return detectors.CleanResults(results), nil
return results, nil
}
type Response struct {
ReturnCode int `json:"return_code"`
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_Api2Cart
}
+5 -1
View File
@@ -82,5 +82,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_ApiDeck
}
+5 -1
View File
@@ -78,5 +78,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
}
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_Apiflash
}
+5 -1
View File
@@ -81,5 +81,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
}
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_ApiFonica
}
+5 -1
View File
@@ -68,5 +68,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
results = append(results, s1)
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_Apify
}
+10 -6
View File
@@ -2,12 +2,12 @@ package apilayer
import (
"context"
"net/http"
"regexp"
"strings"
"github.com/trufflesecurity/trufflehog/v3/pkg/common"
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/detectorspb"
"net/http"
"regexp"
"strings"
)
type Scanner struct{}
@@ -18,7 +18,7 @@ var _ detectors.Detector = (*Scanner)(nil)
var (
client = common.SaneHttpClient()
//Make sure that your group is surrounded in boundry characters such as below to reduce false positives
// Make sure that your group is surrounded in boundry characters such as below to reduce false positives
keyPat = regexp.MustCompile(detectors.PrefixRegex([]string{"apilayer"}) + `\b([a-zA-Z0-9]{32})\b`)
)
@@ -57,7 +57,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
if res.StatusCode >= 200 && res.StatusCode < 300 {
s1.Verified = true
} else {
//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
// 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
if detectors.IsKnownFalsePositive(resMatch, detectors.DefaultFalsePositives, true) {
continue
}
@@ -68,5 +68,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
results = append(results, s1)
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_Apilayer
}
+5 -1
View File
@@ -82,5 +82,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
results = append(results, s1)
}
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_APIMatic
}
+5 -1
View File
@@ -70,5 +70,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
results = append(results, s1)
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_ApiScience
}
+5 -1
View File
@@ -70,5 +70,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
results = append(results, s1)
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_APITemplate
}
+5 -1
View File
@@ -69,5 +69,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
results = append(results, s1)
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_Apollo
}
+5 -1
View File
@@ -90,5 +90,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
}
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_Appcues
}
+5 -1
View File
@@ -73,5 +73,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
results = append(results, s1)
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_Appfollow
}
+5 -1
View File
@@ -74,5 +74,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
results = append(results, s1)
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_Appointedd
}
+5 -1
View File
@@ -70,5 +70,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
results = append(results, s1)
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_AppSynergy
}
+5 -1
View File
@@ -89,5 +89,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
}
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_Apptivo
}
+5 -1
View File
@@ -81,5 +81,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
results = append(results, s1)
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_ArtifactoryAccessToken
}
+5 -1
View File
@@ -80,5 +80,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_Artsy
}
+5 -1
View File
@@ -70,5 +70,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
results = append(results, s1)
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_AsanaOauth
}
@@ -69,5 +69,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
results = append(results, s1)
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_AsanaPersonalAccessToken
}
+5 -1
View File
@@ -70,5 +70,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
results = append(results, s1)
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_AssemblyAI
}
+5 -1
View File
@@ -70,5 +70,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
results = append(results, s1)
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_Atera
}
+5 -1
View File
@@ -79,5 +79,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
results = append(results, s1)
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_Audd
}
@@ -88,5 +88,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
}
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_Auth0ManagementApiToken
}
+5 -1
View File
@@ -114,5 +114,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
}
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_Auth0oauth
}
+5 -1
View File
@@ -80,5 +80,9 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
}
}
return detectors.CleanResults(results), nil
return results, nil
}
func (s Scanner) Type() detectorspb.DetectorType {
return detectorspb.DetectorType_Autodesk
}

Some files were not shown because too many files have changed in this diff Show More