Secret Detectors have these two major functions:
- Given some bytes, extract possible secrets, typically using a regex.
- Validate the secrets against the target API, typically using a HTTP client.
The purpose of Secret Detectors is to discover secrets with exceptionally high signal. High rates of false positives are not accepted.
We are interested in detectors for services that meet at least one of these criteria
- host data (they store any sort of data provided)
- have paid services (having a free or trial tier is okay though)
If you think that something should be included outside of these guidelines, please let us know.
- When reasonable, favor using the
net/http
library to make requests instead of bringing in another library. - Use the
common.SaneHttpClient
for thehttp.Client
whenever possible.
- Go 1.17+
- Make
In some instances, services will update their token format, requiring a new regex to properly detect secrets in addition to supporting the previous token format. Accomodating this can be done without adding a net-new detector. We provide a Versioner
interface that can be implemented.
- Create two new directories
v1
andv2
. Move the existing detector and tests intov1
, and add new files tov2
. Ex:<packagename>/<old_files>
-><packagename>/v1/<old_files>
,<packagename>/v2/<new_files>
Note: Be sure to update the tests to reference the new secret values in GSM, or the tests will fail.
-
Implement the
Versioner
interface. GitHub example implementation. -
Add a 'version' field in ExtraData for both existing and new detector versions.
-
Update the existing detector in DefaultDetectors in
/pkg/engine/defaults.go
-
Proceed from step 3 of Creating a new Secret Scanner
-
Add a new Secret Detector enum to the
DetectorType
list here. -
Run
make protos
to update the.pb
files. -
Generate the Secret Detector
go run hack/generate/generate.go detector <DetectorType enum name> example: go run hack/generate/generate.go detector SampleAPI
-
Add the Secret Detector to TruffleHog's Default Detectors
Add the secret scanner to the
pkg/engine/defaults.go
file likegithub.aaakk.us.kg/trufflesecurity/trufflehog/v3/pkg/detectors/<detector_name>
and<detector_name>.Scanner{}
-
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:- Update the pattern regex and keywords. Try iterating with regex101.com.
- Update the verifier code to use a non-destructive API call that can determine whether the secret is valid or not.
- Make sure you understand verification indeterminacy.
- Create a test for the detector.
- Add your new detector to DefaultDetectors in
/pkg/engine/defaults.go
. - Create a pull request for review.
To ensure the quality of your PR, make sure your tests are passing with verified credentials.
-
Create a file called
.env
with this env file format:SECRET_TYPE_ONE=value SECRET_TYPE_ONE_INACTIVE=v@lue
-
Export the
TEST_SECRET_FILE
variable, pointing to the env file:export TEST_SECRET_FILE=".env"
The
.env
file should be in the new detector's directory like this:├── tailscale │ ├── .env │ ├── tailscale.go │ └── tailscale_test.go
Now that a
.env
file is present, the test file can load secrets locally. -
Next, update the tests as necessary. A test file has already been generated by the
go run hack/generate/generate.go
command from earlier. There are 5 cases that have been generated:- Found and verified (using a credential loaded from the .env file)
- Found and unverified (determinately, i.e. the secret is invalid)
- Found and unverified (indeterminately due to timeout)
- Found and unverified (indeterminately due to an unexpected API response)
- Not found
Make any necessary updates to the tests. Note there might not be any changes required as the tests generated by the
go run hack/generate/generate.go
command are pretty good. Here is an exemplary test file for a detector which covers all 5 test cases. -
Now run the tests and check to make sure they are passing ✔️!
go test ./pkg/detectors/<detector> -tags=detectors
If the tests are passing, feel free to open a PR!
There are two types of reasons that secret verification can fail:
- The candidate secret is not actually a valid secret.
- Something went wrong in the process unrelated to the candidate secret, such as a transient network error or an unexpected API response.
In TruffleHog parlance, the first type of verification response is called determinate and the second type is called indeterminate. Verification code should distinguish between the two by returning an error object in the result struct only for indeterminate failures. In general, a verifier should return an error (indicating an indeterminate failure) in all cases that haven't been explicitly identified as determinate failure states.
For example, consider a hypothetical authentication endpoint that returns 200 OK
for valid credentials and 403 Forbidden
for invalid credentials. The verifier for this endpoint could make an HTTP request and use the response status code to decide what to return:
- A
200
response would indicate that verification succeeded. (Or maybe any2xx
response.) - A
403
response would indicate that verification failed determinately and no error object should be returned. - Any other response would indicate that verification failed indeterminately and an error object should be returned.
- Install Ubuntu App in Microsoft Store https://www.microsoft.com/en-us/p/ubuntu/9nblggh4msv6.
- Install Docker Desktop https://www.docker.com/products/docker-desktop. Enable WSL integration to Ubuntu. In Docker app, go to Settings->Resources->WSL INTEGRATION->enable Ubuntu.
- Open Ubuntu cli and install
dos2unix
.sudo apt install dos2unix
- Identify the
trufflehog
local directory and convertscripts/gen_proto.sh
file in Unix format.dos2unix ./scripts/gen_proto.sh
- Open /proto/detectors.proto file and add new detectors then save it. Make sure Docker is running and run this in Ubuntu command line.
make protos