Skip to content

Commit a1f975d

Browse files
updated the fibery detector regexes (#4385)
Co-authored-by: Kashif Khan <[email protected]>
1 parent 836ed28 commit a1f975d

File tree

3 files changed

+64
-41
lines changed

3 files changed

+64
-41
lines changed

pkg/detectors/fibery/fibery.go

Lines changed: 58 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ package fibery
33
import (
44
"context"
55
"fmt"
6+
"io"
67
"net/http"
7-
"strings"
88
"time"
99

1010
regexp "github.com/wasilibs/go-re2"
@@ -14,66 +14,64 @@ import (
1414
)
1515

1616
type Scanner struct {
17+
client *http.Client
1718
detectors.DefaultMultiPartCredentialProvider
1819
}
1920

2021
// Ensure the Scanner satisfies the interface at compile time.
2122
var _ detectors.Detector = (*Scanner)(nil)
2223

2324
var (
24-
client = detectors.DetectorHttpClientWithNoLocalAddresses
25+
defaultClient = detectors.DetectorHttpClientWithNoLocalAddresses
2526

2627
// Make sure that your group is surrounded in boundary characters such as below to reduce false positives.
27-
keyPat = regexp.MustCompile(detectors.PrefixRegex([]string{"fibery"}) + `\b([0-9a-f]{8}.[0-9a-f]{35})\b`)
28-
domainPat = regexp.MustCompile(detectors.PrefixRegex([]string{"fibery", "domain"}) + `\b([0-9A-Za-z]{2,40})\b`)
28+
keyPat = regexp.MustCompile(detectors.PrefixRegex([]string{"fibery"}) + `\b([0-9a-f]{8}\.[0-9a-f]{35})\b`)
29+
domainPat = regexp.MustCompile(`(?:https?:\/\/)?([a-zA-Z0-9-]{1,63})\.fibery\.io(?:\/.*)?`)
2930
)
3031

3132
// Keywords are used for efficiently pre-filtering chunks.
3233
// Use identifiers in the secret preferably, or the provider name.
3334
func (s Scanner) Keywords() []string {
34-
return []string{"fibery"}
35+
return []string{".fibery.io"}
3536
}
3637

3738
// Description returns a description for the result being detected
3839
func (s Scanner) Description() string {
3940
return "Fibery is a work management platform that combines various tools for project management, knowledge management, and software development. Fibery API tokens can be used to access and modify data within a Fibery workspace."
4041
}
4142

43+
func (s Scanner) getClient() *http.Client {
44+
if s.client != nil {
45+
return s.client
46+
}
47+
return defaultClient
48+
}
49+
4250
// FromData will find and optionally verify Fibery secrets in a given set of bytes.
4351
func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (results []detectors.Result, err error) {
4452
dataStr := string(data)
4553

46-
matches := keyPat.FindAllStringSubmatch(dataStr, -1)
47-
domainMatches := domainPat.FindAllStringSubmatch(dataStr, -1)
48-
49-
for _, match := range matches {
50-
resMatch := strings.TrimSpace(match[1])
54+
uniqueSecrets := make(map[string]struct{})
55+
uniqueDomains := make(map[string]struct{})
5156

52-
for _, domainMatch := range domainMatches {
53-
54-
resDomainMatch := strings.TrimSpace(domainMatch[1])
57+
for _, match := range keyPat.FindAllStringSubmatch(dataStr, -1) {
58+
uniqueSecrets[match[1]] = struct{}{}
59+
}
60+
for _, match := range domainPat.FindAllStringSubmatch(dataStr, -1) {
61+
uniqueDomains[match[1]] = struct{}{}
62+
}
5563

64+
for secret := range uniqueSecrets {
65+
for domain := range uniqueDomains {
5666
s1 := detectors.Result{
5767
DetectorType: detectorspb.DetectorType_Fibery,
58-
Raw: []byte(resMatch),
68+
Raw: []byte(secret),
5969
}
6070

6171
if verify {
62-
timeout := 10 * time.Second
63-
client.Timeout = timeout
64-
req, err := http.NewRequestWithContext(ctx, "POST", fmt.Sprintf("https://%s.fibery.io/api/commands", resDomainMatch), nil)
65-
if err != nil {
66-
continue
67-
}
68-
req.Header.Add("Content-Type", "application/json")
69-
req.Header.Add("Authorization", fmt.Sprintf("Token %s", resMatch))
70-
res, err := client.Do(req)
71-
if err == nil {
72-
defer res.Body.Close()
73-
if res.StatusCode >= 200 && res.StatusCode < 300 {
74-
s1.Verified = true
75-
}
76-
}
72+
isVerified, verificationErr := verifyMatch(ctx, s.getClient(), secret, domain)
73+
s1.Verified = isVerified
74+
s1.SetVerificationError(verificationErr, secret, domain)
7775
}
7876

7977
results = append(results, s1)
@@ -83,6 +81,37 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
8381
return results, nil
8482
}
8583

84+
func verifyMatch(ctx context.Context, client *http.Client, secret, domain string) (bool, error) {
85+
timeout := 10 * time.Second
86+
client.Timeout = timeout
87+
url := fmt.Sprintf("https://%s.fibery.io/api/commands", domain)
88+
req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, http.NoBody)
89+
if err != nil {
90+
return false, err
91+
}
92+
93+
req.Header.Add("Content-Type", "application/json")
94+
req.Header.Add("Authorization", fmt.Sprintf("Token %s", secret))
95+
res, err := client.Do(req)
96+
if err != nil {
97+
return false, err
98+
}
99+
100+
defer func() {
101+
_, _ = io.Copy(io.Discard, res.Body)
102+
_ = res.Body.Close()
103+
}()
104+
105+
switch res.StatusCode {
106+
case http.StatusOK:
107+
return true, nil
108+
case http.StatusUnauthorized:
109+
return false, nil
110+
default:
111+
return false, fmt.Errorf("unexpected status code: %d", res.StatusCode)
112+
}
113+
}
114+
86115
func (s Scanner) Type() detectorspb.DetectorType {
87116
return detectorspb.DetectorType_Fibery
88117
}

pkg/detectors/fibery/fibery_integration_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@ import (
1919
func TestFibery_FromChunk(t *testing.T) {
2020
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
2121
defer cancel()
22-
testSecrets, err := common.GetSecret(ctx, "trufflehog-testing", "detectors3")
22+
testSecrets, err := common.GetSecret(ctx, "trufflehog-testing", "detectors6")
2323
if err != nil {
2424
t.Fatalf("could not get test secrets from GCP: %s", err)
2525
}
26-
secret := testSecrets.MustGetField("FIBERY")
26+
secret := testSecrets.MustGetField("FIBERY_SECRET")
2727
domain := testSecrets.MustGetField("FIBERY_DOMAIN")
2828
inactiveSecret := testSecrets.MustGetField("FIBERY_INACTIVE")
2929

pkg/detectors/fibery/fibery_test.go

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,16 @@ var (
1717
"type": "Detector",
1818
"api": true,
1919
"authentication_type": "",
20-
"verification_url": "https://%s.fibery.io/example",
20+
"verification_url": "https://detector.fibery.io/example",
2121
"domain": "nonprod",
2222
"test_secrets": {
23-
"fibery_secret": "42b2eda8{3fe6b086bb21be7e3548368626d01aaf2cd"
23+
"fibery_secret": "42b2eda8.3fe6b086bb21be7e3548368626d01aaf2cd"
2424
},
2525
"expected_response": "200",
2626
"method": "GET",
2727
"deprecated": false
2828
}]`
29-
secrets = []string{
30-
// TODO: Domain pattern matches more than expected and the current logic create result for each secret&domain combination
31-
"42b2eda8{3fe6b086bb21be7e3548368626d01aaf2cd",
32-
"42b2eda8{3fe6b086bb21be7e3548368626d01aaf2cd",
33-
"42b2eda8{3fe6b086bb21be7e3548368626d01aaf2cd",
34-
"42b2eda8{3fe6b086bb21be7e3548368626d01aaf2cd",
35-
}
29+
secret = "42b2eda8.3fe6b086bb21be7e3548368626d01aaf2cd"
3630
)
3731

3832
func TestFibery_Pattern(t *testing.T) {
@@ -47,7 +41,7 @@ func TestFibery_Pattern(t *testing.T) {
4741
{
4842
name: "valid pattern",
4943
input: validPattern,
50-
want: secrets,
44+
want: []string{secret},
5145
},
5246
}
5347

0 commit comments

Comments
 (0)