Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/man/trufflehog.1
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ Specifies which type(s) of results to output: verified (confirmed valid by API),
\fB--no-color\fR
Disable colorized output
.TP
\fB--header=HEADER\fR
Custom header to add to all outbound HTTP requests; repeatable. Format 'Name: value' or 'Name=value'.
.TP
\fB--allow-verification-overlap\fR
Allow verification of similar credentials across detectors
.TP
Expand Down
31 changes: 31 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ var (
results = cli.Flag("results", "Specifies which type(s) of results to output: verified (confirmed valid by API), unknown (verification failed due to error), unverified (detected but not verified), filtered_unverified (unverified but would have been filtered out). Defaults to verified,unverified,unknown.").String()
noColor = cli.Flag("no-color", "Disable colorized output").Bool()
noColour = cli.Flag("no-colour", "Alias for --no-color").Hidden().Bool()
customHeaders = cli.Flag("header", "Custom header to add to all outbound HTTP requests; repeatable. Format 'Name: value' or 'Name=value'.").Strings()

allowVerificationOverlap = cli.Flag("allow-verification-overlap", "Allow verification of similar credentials across detectors").Bool()
filterUnverified = cli.Flag("filter-unverified", "Only output first unverified result per chunk per detector if there are more than one results.").Bool()
Expand Down Expand Up @@ -512,6 +513,36 @@ func run(state overseer.State, logSync func() error) {
feature.UserAgentSuffix.Store(*userAgentSuffix)
}

// Parse and set any custom headers specified via --header
if customHeaders != nil && len(*customHeaders) > 0 {
hdr := http.Header{}
for _, h := range *customHeaders {
var key, val string
colonIdx := strings.Index(h, ":")
equalsIdx := strings.Index(h, "=")
switch {
case colonIdx == -1 && equalsIdx == -1:
logger.V(1).Info("skipping invalid --header format; expected 'Name: value' or 'Name=value'", "header", h)
continue
case colonIdx == -1 || (equalsIdx != -1 && equalsIdx < colonIdx):
key = strings.TrimSpace(h[:equalsIdx])
val = strings.TrimSpace(h[equalsIdx+1:])
default:
key = strings.TrimSpace(h[:colonIdx])
val = strings.TrimSpace(h[colonIdx+1:])
}
if key == "" || val == "" {
logger.V(1).Info("skipping invalid --header with empty key or value", "header", h)
continue
}
hdr.Add(key, val)
}
if len(hdr) > 0 {
feature.CustomHeaders.Store(hdr)
logger.V(2).Info("custom headers configured", "count", len(hdr))
}
}

// OSS Default APK handling on
feature.EnableAPKHandler.Store(true)

Expand Down
12 changes: 12 additions & 0 deletions pkg/common/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,20 @@ func UserAgent() string {
return "TruffleHog"
}

// ApplyCustomHeaders adds any globally configured custom headers to req.
func ApplyCustomHeaders(req *http.Request) {
if hdr := feature.CustomHeaders.Load(); hdr != nil {
for k, vals := range hdr {
for _, v := range vals {
req.Header.Add(k, v)
}
}
}
}

func (t *CustomTransport) RoundTrip(req *http.Request) (*http.Response, error) {
req.Header.Add("User-Agent", UserAgent())
ApplyCustomHeaders(req)
return t.T.RoundTrip(req)
Comment on lines +99 to 113
}

Expand Down
1 change: 1 addition & 0 deletions pkg/detectors/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ type detectorTransport struct {

func (t *detectorTransport) RoundTrip(req *http.Request) (*http.Response, error) {
req.Header.Add("User-Agent", userAgent())
common.ApplyCustomHeaders(req)
return t.T.RoundTrip(req)
}
Comment on lines 76 to 80

Expand Down
2 changes: 1 addition & 1 deletion pkg/detectors/readme/readme.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
}
req.SetBasicAuth(resMatch, "")
req.Header.Add("accept", "application/json")
res, err := http.DefaultClient.Do(req)
res, err := detectors.DetectorHttpClientWithLocalAddresses.Do(req)
if err == nil {
defer res.Body.Close()
if res.StatusCode >= 200 && res.StatusCode < 300 {
Expand Down
20 changes: 20 additions & 0 deletions pkg/feature/feature.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package feature

import (
"net/http"
"sync/atomic"
)

Expand All @@ -16,6 +17,7 @@ var (
GitlabProjectsPerPage atomic.Int64
UseGithubGraphQLAPI atomic.Bool // use github graphql api to fetch issues, pr's and comments
HTMLDecoderEnabled atomic.Bool
CustomHeaders AtomicHeader
)

type AtomicString struct {
Expand All @@ -41,3 +43,21 @@ func (as *AtomicString) Swap(newValue string) string {
as.Store(newValue)
return oldValue
}

// AtomicHeader stores an http.Header atomically for global access.
type AtomicHeader struct {
value atomic.Value
}

// Load returns the current http.Header value; may be nil if unset.
func (ah *AtomicHeader) Load() http.Header {
if v := ah.value.Load(); v != nil {
return v.(http.Header)
}
return nil
}

// Store sets the http.Header value.
func (ah *AtomicHeader) Store(h http.Header) {
ah.value.Store(h)
Comment on lines +52 to +62
}
4 changes: 3 additions & 1 deletion pkg/sources/huggingface/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"time"

"github.com/trufflesecurity/trufflehog/v3/pkg/context"
"github.com/trufflesecurity/trufflehog/v3/pkg/common"
)

// Maps for API and HTML paths
Expand Down Expand Up @@ -125,7 +126,8 @@ func NewHFClient(baseURL, apiKey string, timeout time.Duration) *HFClient {
BaseURL: baseURL,
APIKey: apiKey,
HTTPClient: &http.Client{
Timeout: timeout,
Timeout: timeout,
Transport: common.NewInstrumentedTransport(common.NewCustomTransport(nil)),
},
}
}
Expand Down
Loading