[INS-402] Add Jira Data Center PAT Detector (#4872)
* add jira data center pat detector * fix lint and engine test * fix merge * make protos and fix imports after merge * tighten regex * bugbot fix * embed DefaultMultiPartCredentialProvider * make protos * add improvements and bugbot fixes * make protos after merge * deduplicate tokens and use DetectorHttpClientWithNoLocalAddresses * incorporated comments * added extra endpoint at the right place * bugbot fixes * bugbot fix
This commit is contained in:
@@ -0,0 +1,192 @@
|
||||
package jiradatacenterpat
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
regexp "github.com/wasilibs/go-re2"
|
||||
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/detector_typepb"
|
||||
)
|
||||
|
||||
type Scanner struct {
|
||||
client *http.Client
|
||||
detectors.EndpointSetter
|
||||
detectors.DefaultMultiPartCredentialProvider
|
||||
}
|
||||
|
||||
// Ensure the Scanner satisfies the interfaces at compile time.
|
||||
var (
|
||||
_ detectors.Detector = (*Scanner)(nil)
|
||||
_ detectors.EndpointCustomizer = (*Scanner)(nil)
|
||||
_ detectors.MultiPartCredentialProvider = (*Scanner)(nil)
|
||||
)
|
||||
|
||||
var (
|
||||
defaultClient = detectors.DetectorHttpClientWithNoLocalAddresses
|
||||
|
||||
// PATs are base64-encoded strings of the form <12-digit-id>:<20-random-bytes> (33 bytes, 44 chars, no padding).
|
||||
// Since the first byte is always an ASCII digit (0x30–0x39), the first base64 character is always M, N, or O.
|
||||
// This is also verified by generating 25+ tokens.
|
||||
// The trailing boundary (?:[^A-Za-z0-9+/=]|\z) is used instead of \b to correctly handle tokens ending in + or /.
|
||||
patPat = regexp.MustCompile(detectors.PrefixRegex([]string{"jira", "atlassian"}) + `\b([MNO][A-Za-z0-9+/]{43})(?:[^A-Za-z0-9+/=]|\z)`)
|
||||
urlPat = regexp.MustCompile(detectors.PrefixRegex([]string{"jira", "atlassian"}) + `(https?://[A-Za-z0-9][A-Za-z0-9.\-]*(?::\d{1,5})?)`)
|
||||
)
|
||||
|
||||
func (s Scanner) getClient() *http.Client {
|
||||
if s.client != nil {
|
||||
return s.client
|
||||
}
|
||||
return defaultClient
|
||||
}
|
||||
|
||||
// Keywords are used for efficiently pre-filtering chunks.
|
||||
func (s Scanner) Keywords() []string {
|
||||
return []string{"jira", "atlassian"}
|
||||
}
|
||||
|
||||
// FromData will find and optionally verify Jira Data Center PAT 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)
|
||||
|
||||
tokens := make(map[string]struct{})
|
||||
for _, match := range patPat.FindAllStringSubmatch(dataStr, -1) {
|
||||
if isStructuralPAT(match[1]) {
|
||||
tokens[match[1]] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
uniqueURLs := make(map[string]struct{})
|
||||
for _, match := range urlPat.FindAllStringSubmatch(dataStr, -1) {
|
||||
uniqueURLs[match[1]] = struct{}{}
|
||||
}
|
||||
foundURLs := make([]string, 0, len(uniqueURLs))
|
||||
for url := range uniqueURLs {
|
||||
foundURLs = append(foundURLs, url)
|
||||
}
|
||||
endpoints := make(map[string]struct{})
|
||||
for _, endpoint := range s.Endpoints(foundURLs...) {
|
||||
endpoints[endpoint] = struct{}{}
|
||||
}
|
||||
|
||||
for token := range tokens {
|
||||
if len(endpoints) == 0 {
|
||||
results = append(results, detectors.Result{
|
||||
DetectorType: detector_typepb.DetectorType_JiraDataCenterPAT,
|
||||
Raw: []byte(token),
|
||||
Redacted: token[:3] + "..." + token[len(token)-3:],
|
||||
ExtraData: map[string]string{"message": "No Jira Data Center URL was found or configured. To verify this token, set the Jira instance base URL as a custom endpoint."},
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
||||
for endpoint := range endpoints {
|
||||
s1 := detectors.Result{
|
||||
DetectorType: detector_typepb.DetectorType_JiraDataCenterPAT,
|
||||
Raw: []byte(token),
|
||||
RawV2: []byte(token + ":" + endpoint),
|
||||
Redacted: token[:3] + "..." + token[len(token)-3:],
|
||||
}
|
||||
|
||||
if verify {
|
||||
isVerified, extraData, verificationErr := verifyPAT(ctx, s.getClient(), endpoint, token)
|
||||
s1.Verified = isVerified
|
||||
s1.ExtraData = extraData
|
||||
s1.SetVerificationError(verificationErr, token)
|
||||
}
|
||||
|
||||
results = append(results, s1)
|
||||
|
||||
if s1.Verified {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
// verifyPAT checks whether the token is valid by calling the /rest/api/2/myself endpoint,
|
||||
// which returns the currently authenticated user.
|
||||
// Docs: https://developer.atlassian.com/server/jira/platform/rest/v10002/api-group-myself/#api-api-2-myself-get
|
||||
func verifyPAT(ctx context.Context, client *http.Client, baseURL, token string) (bool, map[string]string, error) {
|
||||
u, err := detectors.ParseURLAndStripPathAndParams(baseURL)
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
u.Path = "/rest/api/2/myself"
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), http.NoBody)
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("Accept", "application/json")
|
||||
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
|
||||
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
defer func() {
|
||||
_, _ = io.Copy(io.Discard, resp.Body)
|
||||
_ = resp.Body.Close()
|
||||
}()
|
||||
|
||||
switch resp.StatusCode {
|
||||
case http.StatusOK:
|
||||
var result map[string]any
|
||||
extraData := map[string]string{
|
||||
"endpoint": baseURL,
|
||||
}
|
||||
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
|
||||
// 200 confirms the token is valid; failing to decode only means we can't extract extra data.
|
||||
return true, extraData, nil
|
||||
}
|
||||
if name, ok := result["displayName"].(string); ok {
|
||||
extraData["display_name"] = name
|
||||
}
|
||||
if email, ok := result["emailAddress"].(string); ok {
|
||||
extraData["email_address"] = email
|
||||
}
|
||||
return true, extraData, nil
|
||||
case http.StatusUnauthorized:
|
||||
return false, nil, nil
|
||||
default:
|
||||
return false, nil, fmt.Errorf("unexpected HTTP response status %d", resp.StatusCode)
|
||||
}
|
||||
}
|
||||
|
||||
// isStructuralPAT decodes a candidate base64 string and checks that it matches
|
||||
// the "<numeric id>:<random bytes>" structure used by Jira DC PATs:
|
||||
// one or more ASCII digits, a colon, then at least one more byte.
|
||||
func isStructuralPAT(candidate string) bool {
|
||||
raw, err := base64.StdEncoding.DecodeString(candidate)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
colon := bytes.IndexByte(raw, ':')
|
||||
if colon <= 0 || colon == len(raw)-1 {
|
||||
return false
|
||||
}
|
||||
for _, b := range raw[:colon] {
|
||||
if b < '0' || b > '9' {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (s Scanner) Type() detector_typepb.DetectorType {
|
||||
return detector_typepb.DetectorType_JiraDataCenterPAT
|
||||
}
|
||||
|
||||
func (s Scanner) Description() string {
|
||||
return "Jira Data Center is a self-hosted version of Jira. Personal Access Tokens (PATs) are used to authenticate API requests to Jira Data Center instances."
|
||||
}
|
||||
@@ -0,0 +1,345 @@
|
||||
package jiradatacenterpat
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gopkg.in/h2non/gock.v1"
|
||||
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/common"
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors"
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/engine/ahocorasick"
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/detector_typepb"
|
||||
)
|
||||
|
||||
const (
|
||||
testToken = "NTg4OTI1Mzk1OTA1OiBb9S4WPEoK6cmOe6pq6VO0lt6M"
|
||||
testEndpoint = "http://jira.example.com"
|
||||
)
|
||||
|
||||
func TestJiraDataCenterPAT_Pattern(t *testing.T) {
|
||||
d := Scanner{}
|
||||
_ = d.SetConfiguredEndpoints("https://jira.example.com")
|
||||
d.UseFoundEndpoints(true)
|
||||
ahoCorasickCore := ahocorasick.NewAhoCorasickCore([]detectors.Detector{d})
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
want []string
|
||||
}{
|
||||
{
|
||||
name: "valid PAT",
|
||||
input: `jira_token: NTg4OTI1Mzk1OTA1OiBb9S4WPEoK6cmOe6pq6VO0lt6M`,
|
||||
want: []string{"NTg4OTI1Mzk1OTA1OiBb9S4WPEoK6cmOe6pq6VO0lt6M:https://jira.example.com"},
|
||||
},
|
||||
{
|
||||
name: "URL found near jira keyword",
|
||||
input: `# jira server: http://jira.internal:8080` + "\n" + `jira token: NTg4OTI1Mzk1OTA1OiBb9S4WPEoK6cmOe6pq6VO0lt6M`,
|
||||
want: []string{
|
||||
"NTg4OTI1Mzk1OTA1OiBb9S4WPEoK6cmOe6pq6VO0lt6M:http://jira.internal:8080",
|
||||
"NTg4OTI1Mzk1OTA1OiBb9S4WPEoK6cmOe6pq6VO0lt6M:https://jira.example.com",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "URL found near atlassian keyword",
|
||||
input: `# atlassian server: http://jira.internal:8080` + "\n" + `atlassian token: NTg4OTI1Mzk1OTA1OiBb9S4WPEoK6cmOe6pq6VO0lt6M`,
|
||||
want: []string{
|
||||
"NTg4OTI1Mzk1OTA1OiBb9S4WPEoK6cmOe6pq6VO0lt6M:http://jira.internal:8080",
|
||||
"NTg4OTI1Mzk1OTA1OiBb9S4WPEoK6cmOe6pq6VO0lt6M:https://jira.example.com",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid PAT ending with +",
|
||||
input: `jira_token: MzE3MjgzNDMyNTczOmTaXorACdDy8aVJU6FotdRcz2y+`,
|
||||
want: []string{"MzE3MjgzNDMyNTczOmTaXorACdDy8aVJU6FotdRcz2y+:https://jira.example.com"},
|
||||
},
|
||||
{
|
||||
name: "not a match - invalid first character",
|
||||
input: `jira_token: ATg4OTI1Mzk1OTA1OiBb9S4WPEoK6cmOe6pq6VO0lt6M`,
|
||||
want: []string{},
|
||||
},
|
||||
{
|
||||
name: "not a match - substring of longer base64 string",
|
||||
input: `jira_token: MzE3MjgzNDMyNTczOmTaXorACdDy8aVJU6FotdRcz2y+AAAA`,
|
||||
want: []string{},
|
||||
},
|
||||
{
|
||||
name: "not a match - followed by base64 padding",
|
||||
input: `jira_token: NTg4OTI1Mzk1OTA1OiBb9S4WPEoK6cmOe6pq6VO0lt6M=`,
|
||||
want: []string{},
|
||||
},
|
||||
{
|
||||
name: "too short - not a match",
|
||||
input: `jira_token: NTg4OTI1Mzk1OTA1OiBb9S4WPEoK6cmOe6pq6VO0`,
|
||||
want: []string{},
|
||||
},
|
||||
{
|
||||
// Passes the regex (44 chars, starts with M) but decodes to "0a:xxx..."
|
||||
// where the byte before the colon is not purely digits.
|
||||
name: "not a match - fails structural check",
|
||||
input: `jira_token: MGE6eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4`,
|
||||
want: []string{},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
matchedDetectors := ahoCorasickCore.FindDetectorMatches([]byte(test.input))
|
||||
if len(test.want) > 0 && len(matchedDetectors) == 0 {
|
||||
t.Errorf("keywords '%v' not matched by: %s", d.Keywords(), test.input)
|
||||
return
|
||||
}
|
||||
|
||||
results, err := d.FromData(context.Background(), false, []byte(test.input))
|
||||
if err != nil {
|
||||
t.Errorf("error = %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(results) != len(test.want) {
|
||||
if len(results) == 0 {
|
||||
t.Errorf("did not receive result")
|
||||
} else {
|
||||
t.Errorf("expected %d results, only received %d", len(test.want), len(results))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
actual := make(map[string]struct{}, len(results))
|
||||
for _, r := range results {
|
||||
if len(r.RawV2) > 0 {
|
||||
actual[string(r.RawV2)] = struct{}{}
|
||||
} else {
|
||||
actual[string(r.Raw)] = struct{}{}
|
||||
}
|
||||
}
|
||||
expected := make(map[string]struct{}, len(test.want))
|
||||
for _, v := range test.want {
|
||||
expected[v] = struct{}{}
|
||||
}
|
||||
|
||||
if diff := cmp.Diff(expected, actual); diff != "" {
|
||||
t.Errorf("%s diff: (-want +got)\n%s", test.name, diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestJiraDataCenterPAT_FromData(t *testing.T) {
|
||||
client := common.SaneHttpClient()
|
||||
|
||||
d := Scanner{client: client}
|
||||
_ = d.SetConfiguredEndpoints(testEndpoint)
|
||||
d.UseFoundEndpoints(false)
|
||||
|
||||
defer gock.Off()
|
||||
defer gock.RestoreClient(client)
|
||||
gock.InterceptClient(client)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
setup func()
|
||||
data string
|
||||
verify bool
|
||||
wantResults int
|
||||
wantVerified bool
|
||||
wantVerificationErr bool
|
||||
wantExtraData map[string]string
|
||||
}{
|
||||
{
|
||||
name: "found, verified",
|
||||
setup: func() {
|
||||
gock.New(testEndpoint).
|
||||
Get("/rest/api/2/myself").
|
||||
MatchHeader("Authorization", fmt.Sprintf("Bearer %s", testToken)).
|
||||
Reply(http.StatusOK).
|
||||
JSON(map[string]any{
|
||||
"displayName": "Test User",
|
||||
"emailAddress": "[email protected]",
|
||||
"endpoint": testEndpoint,
|
||||
})
|
||||
},
|
||||
data: fmt.Sprintf("jira token: %s", testToken),
|
||||
verify: true,
|
||||
wantResults: 1,
|
||||
wantVerified: true,
|
||||
wantExtraData: map[string]string{
|
||||
"display_name": "Test User",
|
||||
"email_address": "[email protected]",
|
||||
"endpoint": testEndpoint,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "found, verified - invalid json body",
|
||||
setup: func() {
|
||||
gock.New(testEndpoint).
|
||||
Get("/rest/api/2/myself").
|
||||
Reply(http.StatusOK).
|
||||
BodyString("not json")
|
||||
},
|
||||
data: fmt.Sprintf("jira token: %s", testToken),
|
||||
verify: true,
|
||||
wantResults: 1,
|
||||
wantVerified: true,
|
||||
},
|
||||
{
|
||||
name: "found, unverified (401)",
|
||||
setup: func() {
|
||||
gock.New(testEndpoint).
|
||||
Get("/rest/api/2/myself").
|
||||
Reply(http.StatusUnauthorized)
|
||||
},
|
||||
data: fmt.Sprintf("jira token: %s", testToken),
|
||||
verify: true,
|
||||
wantResults: 1,
|
||||
wantVerified: false,
|
||||
},
|
||||
{
|
||||
name: "not found",
|
||||
setup: func() {},
|
||||
data: "jira config: nothing here",
|
||||
verify: true,
|
||||
wantResults: 0,
|
||||
},
|
||||
{
|
||||
name: "found, verification error on unexpected status",
|
||||
setup: func() {
|
||||
gock.New(testEndpoint).
|
||||
Get("/rest/api/2/myself").
|
||||
Reply(http.StatusInternalServerError)
|
||||
},
|
||||
data: fmt.Sprintf("jira token: %s", testToken),
|
||||
verify: true,
|
||||
wantResults: 1,
|
||||
wantVerified: false,
|
||||
wantVerificationErr: true,
|
||||
},
|
||||
{
|
||||
name: "found, verification error on timeout",
|
||||
setup: func() {
|
||||
gock.New(testEndpoint).
|
||||
Get("/rest/api/2/myself").
|
||||
Reply(http.StatusOK).
|
||||
Delay(2 * time.Second)
|
||||
},
|
||||
data: fmt.Sprintf("jira token: %s", testToken),
|
||||
verify: true,
|
||||
wantResults: 1,
|
||||
wantVerified: false,
|
||||
wantVerificationErr: true,
|
||||
},
|
||||
{
|
||||
name: "found, no verify",
|
||||
setup: func() {},
|
||||
data: fmt.Sprintf("jira token: %s", testToken),
|
||||
verify: false,
|
||||
wantResults: 1,
|
||||
wantVerified: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
gock.Flush()
|
||||
tt.setup()
|
||||
|
||||
ctx := context.Background()
|
||||
if tt.wantVerificationErr {
|
||||
var cancel context.CancelFunc
|
||||
ctx, cancel = context.WithTimeout(ctx, 100*time.Millisecond)
|
||||
defer cancel()
|
||||
}
|
||||
|
||||
results, err := d.FromData(ctx, tt.verify, []byte(tt.data))
|
||||
require.NoError(t, err)
|
||||
require.Len(t, results, tt.wantResults)
|
||||
|
||||
for _, result := range results {
|
||||
assert.Equal(t, detector_typepb.DetectorType_JiraDataCenterPAT, result.DetectorType)
|
||||
assert.NotEmpty(t, result.Raw)
|
||||
assert.Equal(t, tt.wantVerified, result.Verified)
|
||||
assert.Equal(t, tt.wantVerificationErr, result.VerificationError() != nil)
|
||||
if tt.wantExtraData != nil {
|
||||
assert.Equal(t, tt.wantExtraData, result.ExtraData)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsStructuralPAT(t *testing.T) {
|
||||
encode := func(b []byte) string { return base64.StdEncoding.EncodeToString(b) }
|
||||
|
||||
// helper to build a 33-byte payload with a numeric id and random suffix
|
||||
numericIDPayload := func(id, suffix string) []byte {
|
||||
return []byte(id + ":" + suffix)
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
candidate string
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "valid real token",
|
||||
candidate: testToken,
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "valid - digits before colon",
|
||||
candidate: encode(numericIDPayload("123456789012", "01234567890123456789")),
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "invalid base64",
|
||||
candidate: "!!!not-base64!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "no colon",
|
||||
candidate: encode([]byte("588925395905012345678901234567890")),
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "colon at position 0",
|
||||
candidate: encode([]byte(":01234567890123456789012345678901")),
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "colon at last position",
|
||||
candidate: encode([]byte("58892539590501234567890123456789:")),
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "non-digit before colon",
|
||||
// decodes to "0a:xxx..." — 'a' is not a digit
|
||||
candidate: "MGE6eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4",
|
||||
want: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert.Equal(t, tt.want, isStructuralPAT(tt.candidate))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestJiraDataCenterPAT_NoURL(t *testing.T) {
|
||||
d := Scanner{client: common.SaneHttpClient()}
|
||||
|
||||
results, err := d.FromData(context.Background(), true, []byte(fmt.Sprintf("jira token: %s", testToken)))
|
||||
require.NoError(t, err)
|
||||
require.Len(t, results, 1)
|
||||
assert.False(t, results[0].Verified)
|
||||
assert.Equal(t, map[string]string{"message": "No Jira Data Center URL was found or configured. To verify this token, set the Jira instance base URL as a custom endpoint."}, results[0].ExtraData)
|
||||
assert.Empty(t, results[0].RawV2)
|
||||
}
|
||||
@@ -397,6 +397,7 @@ import (
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/ipquality"
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/ipstack"
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/jdbc"
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/jiradatacenterpat"
|
||||
jiratokenv1 "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/jiratoken/v1"
|
||||
jiratokenv2 "github.com/trufflesecurity/trufflehog/v3/pkg/detectors/jiratoken/v2"
|
||||
"github.com/trufflesecurity/trufflehog/v3/pkg/detectors/jotform"
|
||||
@@ -1274,6 +1275,7 @@ func buildDetectorList() []detectors.Detector {
|
||||
&ipquality.Scanner{},
|
||||
&ipstack.Scanner{},
|
||||
&jdbc.Scanner{},
|
||||
&jiradatacenterpat.Scanner{},
|
||||
&jiratokenv1.Scanner{},
|
||||
&jiratokenv2.Scanner{},
|
||||
&jotform.Scanner{},
|
||||
|
||||
@@ -1379,6 +1379,7 @@ func TestEngineInitializesCloudProviderDetectors(t *testing.T) {
|
||||
detector_typepb.DetectorType_ArtifactoryReferenceToken: {},
|
||||
detector_typepb.DetectorType_TableauPersonalAccessToken: {},
|
||||
detector_typepb.DetectorType_HashiCorpVaultAuth: {},
|
||||
detector_typepb.DetectorType_JiraDataCenterPAT: {},
|
||||
// these do not have any cloud endpoint
|
||||
}
|
||||
|
||||
|
||||
@@ -1099,6 +1099,7 @@ const (
|
||||
DetectorType_DatadogApikey DetectorType = 1043
|
||||
DetectorType_ShopifyOAuth DetectorType = 1044
|
||||
DetectorType_BitbucketDataCenter DetectorType = 1045
|
||||
DetectorType_JiraDataCenterPAT DetectorType = 1046
|
||||
)
|
||||
|
||||
// Enum value maps for DetectorType.
|
||||
@@ -2146,6 +2147,7 @@ var (
|
||||
1043: "DatadogApikey",
|
||||
1044: "ShopifyOAuth",
|
||||
1045: "BitbucketDataCenter",
|
||||
1046: "JiraDataCenterPAT",
|
||||
}
|
||||
DetectorType_value = map[string]int32{
|
||||
"Alibaba": 0,
|
||||
@@ -3190,6 +3192,7 @@ var (
|
||||
"DatadogApikey": 1043,
|
||||
"ShopifyOAuth": 1044,
|
||||
"BitbucketDataCenter": 1045,
|
||||
"JiraDataCenterPAT": 1046,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -3225,7 +3228,7 @@ var File_detector_type_proto protoreflect.FileDescriptor
|
||||
var file_detector_type_proto_rawDesc = []byte{
|
||||
0x0a, 0x13, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x2e,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0d, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x5f,
|
||||
0x74, 0x79, 0x70, 0x65, 0x2a, 0xd9, 0x87, 0x01, 0x0a, 0x0c, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74,
|
||||
0x74, 0x79, 0x70, 0x65, 0x2a, 0xf1, 0x87, 0x01, 0x0a, 0x0c, 0x44, 0x65, 0x74, 0x65, 0x63, 0x74,
|
||||
0x6f, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x41, 0x6c, 0x69, 0x62, 0x61, 0x62,
|
||||
0x61, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x41, 0x4d, 0x51, 0x50, 0x10, 0x01, 0x12, 0x07, 0x0a,
|
||||
0x03, 0x41, 0x57, 0x53, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x7a, 0x75, 0x72, 0x65, 0x10,
|
||||
@@ -4311,11 +4314,13 @@ var file_detector_type_proto_rawDesc = []byte{
|
||||
0x79, 0x10, 0x93, 0x08, 0x12, 0x11, 0x0a, 0x0c, 0x53, 0x68, 0x6f, 0x70, 0x69, 0x66, 0x79, 0x4f,
|
||||
0x41, 0x75, 0x74, 0x68, 0x10, 0x94, 0x08, 0x12, 0x18, 0x0a, 0x13, 0x42, 0x69, 0x74, 0x62, 0x75,
|
||||
0x63, 0x6b, 0x65, 0x74, 0x44, 0x61, 0x74, 0x61, 0x43, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x10, 0x95,
|
||||
0x08, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
|
||||
0x74, 0x72, 0x75, 0x66, 0x66, 0x6c, 0x65, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x2f,
|
||||
0x74, 0x72, 0x75, 0x66, 0x66, 0x6c, 0x65, 0x68, 0x6f, 0x67, 0x2f, 0x76, 0x33, 0x2f, 0x70, 0x6b,
|
||||
0x67, 0x2f, 0x70, 0x62, 0x2f, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x74, 0x79,
|
||||
0x70, 0x65, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x08, 0x12, 0x16, 0x0a, 0x11, 0x4a, 0x69, 0x72, 0x61, 0x44, 0x61, 0x74, 0x61, 0x43, 0x65, 0x6e,
|
||||
0x74, 0x65, 0x72, 0x50, 0x41, 0x54, 0x10, 0x96, 0x08, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74,
|
||||
0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x72, 0x75, 0x66, 0x66, 0x6c, 0x65, 0x73,
|
||||
0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x2f, 0x74, 0x72, 0x75, 0x66, 0x66, 0x6c, 0x65, 0x68,
|
||||
0x6f, 0x67, 0x2f, 0x76, 0x33, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x62, 0x2f, 0x64, 0x65, 0x74,
|
||||
0x65, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
@@ -1047,4 +1047,5 @@ enum DetectorType {
|
||||
DatadogApikey = 1043;
|
||||
ShopifyOAuth = 1044;
|
||||
BitbucketDataCenter = 1045;
|
||||
JiraDataCenterPAT = 1046;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user