mirror of
https://github.com/trufflesecurity/trufflehog.git
synced 2026-06-15 13:24:37 +00:00
Mechanical rename of the detectors.Result.AnalysisInfo field to SecretParts to prepare for its replacement for Raw.
97 lines
2.8 KiB
Go
97 lines
2.8 KiB
Go
package github
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
regexp "github.com/wasilibs/go-re2"
|
|
|
|
"github.com/trufflesecurity/trufflehog/v3/pkg/common"
|
|
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
|
|
v1 "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/github/v1"
|
|
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/detector_typepb"
|
|
)
|
|
|
|
type Scanner struct {
|
|
v1.Scanner
|
|
}
|
|
|
|
// Ensure the Scanner satisfies the interfaces at compile time.
|
|
var _ detectors.Detector = (*Scanner)(nil)
|
|
var _ detectors.Versioner = (*Scanner)(nil)
|
|
var _ detectors.EndpointCustomizer = (*Scanner)(nil)
|
|
var _ detectors.CloudProvider = (*Scanner)(nil)
|
|
|
|
func (s Scanner) Version() int {
|
|
return 2
|
|
}
|
|
func (Scanner) CloudEndpoint() string { return "https://api.github.com" }
|
|
|
|
var (
|
|
// Oauth token
|
|
// https://developer.github.com/v3/#oauth2-token-sent-in-a-header
|
|
// Token type list:
|
|
// https://github.blog/2021-04-05-behind-githubs-new-authentication-token-formats/
|
|
// https://github.blog/changelog/2022-10-18-introducing-fine-grained-personal-access-tokens/
|
|
keyPat = regexp.MustCompile(`\b((?:ghp|gho|ghu|ghs|ghr|github_pat)_[a-zA-Z0-9_]{36,255})\b`)
|
|
|
|
// TODO: Oauth2 client_id and client_secret
|
|
// https://developer.github.com/v3/#oauth2-keysecret
|
|
)
|
|
|
|
// 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{"ghp_", "gho_", "ghu_", "ghs_", "ghr_", "github_pat_"}
|
|
}
|
|
|
|
// FromData will find and optionally verify GitHub 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)
|
|
|
|
matches := keyPat.FindAllStringSubmatch(dataStr, -1)
|
|
|
|
for _, match := range matches {
|
|
// First match is entire regex, second is the first group.
|
|
|
|
token := match[1]
|
|
|
|
s1 := detectors.Result{
|
|
DetectorType: detector_typepb.DetectorType_Github,
|
|
Raw: []byte(token),
|
|
ExtraData: map[string]string{
|
|
"rotation_guide": "https://howtorotate.com/docs/tutorials/github/",
|
|
"version": fmt.Sprintf("%d", s.Version()),
|
|
},
|
|
SecretParts: map[string]string{"key": token},
|
|
}
|
|
|
|
if verify {
|
|
client := common.SaneHttpClient()
|
|
|
|
isVerified, userResponse, headers, err := s.VerifyGithub(ctx, client, token)
|
|
s1.Verified = isVerified
|
|
s1.SetVerificationError(err, token)
|
|
|
|
if userResponse != nil {
|
|
v1.SetUserResponse(userResponse, &s1)
|
|
}
|
|
if headers != nil {
|
|
v1.SetHeaderInfo(headers, &s1)
|
|
}
|
|
}
|
|
|
|
results = append(results, s1)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (s Scanner) Type() detector_typepb.DetectorType {
|
|
return detector_typepb.DetectorType_Github
|
|
}
|
|
|
|
func (s Scanner) Description() string {
|
|
return "GitHub is a platform for version control and collaboration. Personal access tokens (PATs) can be used to access and modify repositories and other resources."
|
|
}
|