[Feat] Added Mux API Analyzer (#4128)

* added mux analyzer

* updated mux analyzer print function and mux detector

* updated mux analyzer test expected output
This commit is contained in:
Nabeel Alam
2025-05-16 01:47:06 +05:00
committed by GitHub
parent f7b6d7d9e2
commit 8da58156fd
13 changed files with 940 additions and 0 deletions
+2
View File
@@ -98,6 +98,7 @@ const (
AnalyzerTypeFastly
AnalyzerTypeMonday
AnalyzerTypeNgrok
AnalyzerTypeMux
// Add new items here with AnalyzerType prefix
)
@@ -141,6 +142,7 @@ var analyzerTypeStrings = map[AnalyzerType]string{
AnalyzerTypeFastly: "Fastly",
AnalyzerTypeMonday: "Monday",
AnalyzerTypeNgrok: "Ngrok",
AnalyzerTypeMux: "Mux",
// Add new mappings here
}
File diff suppressed because one or more lines are too long
+142
View File
@@ -0,0 +1,142 @@
package mux
import (
"fmt"
"net/http"
)
type ResourceType string
const (
ResourceTypeVideo ResourceType = "video"
ResourceTypeData ResourceType = "data"
ResourceTypeSystem ResourceType = "system"
)
type permissionTestConfig struct {
Tests []permissionTest `json:"tests"`
}
type permissionTest struct {
ResourceType ResourceType `json:"resource_type"`
Permission string `json:"permission"`
Endpoint string `json:"endpoint"`
Method string `json:"method"`
ValidStatusCode int `json:"valid_status_code"`
}
func (test permissionTest) testPermission(client *http.Client, key string, secret string) (bool, error) {
_, statusCode, err := makeAPIRequest(client, key, secret, test.Method, test.Endpoint)
if err != nil {
return false, err
}
switch statusCode {
case test.ValidStatusCode:
return true, nil
case http.StatusNotFound:
return false, nil
default:
return false, fmt.Errorf("unexpected status code: %d", statusCode)
}
}
type secretInfo struct {
Permissions map[ResourceType]Permission
Assets []asset
Annotations []annotation
SigningKeys []signingKey
}
func (info *secretInfo) addPermission(resourceType ResourceType, permission string) {
if info.Permissions == nil {
info.Permissions = map[ResourceType]Permission{}
}
if perm := info.Permissions[resourceType]; perm == FullAccess {
return
}
if permission == "read" {
info.Permissions[resourceType] = Read
} else if permission == "write" {
info.Permissions[resourceType] = FullAccess
}
}
func (info *secretInfo) hasPermission(resourceType ResourceType, permission Permission) bool {
perm, exists := info.Permissions[resourceType]
if !exists {
return false
}
return perm == permission || perm == FullAccess
}
// Resource structs
type track struct {
ID string `json:"id"`
Name string `json:"name"`
Type string `json:"type"`
Duration float64 `json:"duration"`
Status string `json:"status"`
Primary bool `json:"primary"`
TextType string `json:"text_type"`
TextSource string `json:"text_source"`
LanguageCode string `json:"language_code"`
MaxWidth int `json:"max_width"`
MaxHeight int `json:"max_height"`
MaxFrameRate float64 `json:"max_frame_rate"`
MaxChannels int `json:"max_channels"`
}
type playbackID struct {
ID string `json:"id"`
Policy string `json:"policy"`
}
type meta struct {
Title string `json:"title"`
ExternalID string `json:"external_id"`
CreatorID string `json:"creator_id"`
}
type asset struct {
ID string `json:"id"`
Duration float64 `json:"duration"`
Status string `json:"status"`
VideoQuality string `json:"video_quality"`
MP4Support string `json:"mp4_support"`
AspectRatio string `json:"aspect_ratio"`
Tracks []track `json:"tracks"`
PlaybackIDs []playbackID `json:"playback_ids"`
Meta meta `json:"meta"`
CreatedAt string `json:"created_at"`
}
type annotation struct {
SubPropertyID string `json:"sub_property_id"`
Note string `json:"note"`
ID string `json:"id"`
Date string `json:"date"`
}
type signingKey struct {
ID string `json:"id"`
CreatedAt string `json:"created_at"`
}
// API response structs
type assetListResponse struct {
Data []asset `json:"data"`
}
type annotationListResponse struct {
Data []annotation `json:"data"`
}
type signingKeyListResponse struct {
Data []signingKey `json:"data"`
}
+319
View File
@@ -0,0 +1,319 @@
//go:generate generate_permissions permissions.yaml permissions.go mux
package mux
import (
"encoding/json"
"errors"
"fmt"
"os"
"github.com/fatih/color"
"github.com/jedib0t/go-pretty/v6/table"
_ "embed"
"github.com/trufflesecurity/trufflehog/v3/pkg/analyzer/analyzers"
"github.com/trufflesecurity/trufflehog/v3/pkg/analyzer/config"
"github.com/trufflesecurity/trufflehog/v3/pkg/context"
)
var _ analyzers.Analyzer = (*Analyzer)(nil)
type Analyzer struct {
Cfg *config.Config
}
//go:embed tests.json
var testsConfig []byte
func readTestsConfig() (*permissionTestConfig, error) {
var config permissionTestConfig
if err := json.Unmarshal(testsConfig, &config); err != nil {
return nil, fmt.Errorf("failed to unmarshal tests config: %w", err)
}
return &config, nil
}
func (a Analyzer) Type() analyzers.AnalyzerType {
return analyzers.AnalyzerTypeMux
}
func (a Analyzer) Analyze(_ context.Context, credInfo map[string]string) (*analyzers.AnalyzerResult, error) {
key, exist := credInfo["key"]
if !exist {
return nil, errors.New("key not found in credentials info")
}
secret, exist := credInfo["secret"]
if !exist {
return nil, errors.New("secret not found in credentials info")
}
info, err := AnalyzePermissions(a.Cfg, key, secret)
if err != nil {
return nil, err
}
return secretInfoToAnalyzerResult(info), nil
}
func AnalyzeAndPrintPermissions(cfg *config.Config, key string, secret string) {
info, err := AnalyzePermissions(cfg, key, secret)
if err != nil {
color.Red("[x] Invalid Mux Key or Secret\n")
color.Red("[x] Error : %s", err.Error())
return
}
if info == nil {
color.Red("[x] Error : %s", "No information found")
return
}
color.Green("[i] Valid Mux API Key and Secret\n")
printResourcesAndPermissions(info)
}
func AnalyzePermissions(cfg *config.Config, key string, secret string) (*secretInfo, error) {
client := analyzers.NewAnalyzeClientUnrestricted(cfg)
secretInfo := &secretInfo{}
if err := testAllPermissions(client, secretInfo, key, secret); err != nil {
return nil, err
}
if err := populateAllResources(client, secretInfo, key, secret); err != nil {
return nil, err
}
return secretInfo, nil
}
func secretInfoToAnalyzerResult(info *secretInfo) *analyzers.AnalyzerResult {
if info == nil {
return nil
}
bindings := []analyzers.Binding{}
readAccessPermission := analyzers.Permission{
Value: PermissionStrings[Read],
}
fullAccessPermission := analyzers.Permission{
Value: PermissionStrings[FullAccess],
}
videoResourcePermission := readAccessPermission
if info.hasPermission(ResourceTypeVideo, FullAccess) {
videoResourcePermission = fullAccessPermission
}
dataResourcePermission := readAccessPermission
if info.hasPermission(ResourceTypeData, FullAccess) {
dataResourcePermission = fullAccessPermission
}
systemResourcePermission := readAccessPermission
if info.hasPermission(ResourceTypeSystem, FullAccess) {
systemResourcePermission = fullAccessPermission
}
// Binding all Mux Video Assets
for _, asset := range info.Assets {
assetResource := createAssetResource(asset)
trackResources := createAssetTrackResources(asset, &assetResource)
playbackIDResources := createAssetPlaybackIDResources(asset, &assetResource)
for _, resource := range trackResources {
bindings = append(bindings, createBinding(&resource, videoResourcePermission))
}
for _, resource := range playbackIDResources {
bindings = append(bindings, createBinding(&resource, videoResourcePermission))
}
bindings = append(bindings, createBinding(&assetResource, videoResourcePermission))
}
// Binding all Mux Data Annotations
for _, annotation := range info.Annotations {
annotationResource := createAnnotationResource(annotation)
bindings = append(bindings, createBinding(&annotationResource, dataResourcePermission))
}
// Binding all Mux System Signing Keys
for _, signingKey := range info.SigningKeys {
signingKeyResource := createSigningKeyResource(signingKey)
bindings = append(bindings, createBinding(&signingKeyResource, systemResourcePermission))
}
result := analyzers.AnalyzerResult{
AnalyzerType: analyzers.AnalyzerTypeMux,
Metadata: nil,
Bindings: bindings,
}
return &result
}
func createBinding(resource *analyzers.Resource, permission analyzers.Permission) analyzers.Binding {
return analyzers.Binding{
Resource: *resource,
Permission: permission,
}
}
func printResourcesAndPermissions(info *secretInfo) {
color.Yellow("\n[i] Permissions:")
t1 := table.NewWriter()
t1.AppendHeader(table.Row{"Resource Category", "Access Level", "Resource List"})
for idx, resource := range muxResourcesMap[ResourceTypeVideo] {
category, access := "", ""
if idx == 0 {
category = "Mux Video"
access = getAccessLevelStringFromPermission(info.Permissions[ResourceTypeVideo])
}
t1.AppendRow(table.Row{
color.GreenString(category),
color.GreenString(access),
color.GreenString(resource),
})
}
t1.AppendSeparator()
for idx, resource := range muxResourcesMap[ResourceTypeData] {
category, access := "", ""
if idx == 0 {
category = "Mux Data"
access = getAccessLevelStringFromPermission(info.Permissions[ResourceTypeData])
}
t1.AppendRow(table.Row{
color.GreenString(category),
color.GreenString(access),
color.GreenString(resource),
})
}
t1.AppendSeparator()
for idx, resource := range muxResourcesMap[ResourceTypeSystem] {
category, access := "", ""
if idx == 0 {
category = "Mux System"
access = getAccessLevelStringFromPermission(info.Permissions[ResourceTypeSystem])
}
t1.AppendRow(table.Row{
color.GreenString(category),
color.GreenString(access),
color.GreenString(resource),
})
}
t1.SetOutputMirror(os.Stdout)
t1.Render()
color.Yellow("\n[i] Resources:")
if info.hasPermission(ResourceTypeVideo, Read) {
printMuxVideoResources(info)
}
if info.hasPermission(ResourceTypeData, Read) {
printMuxDataResources(info)
}
if info.hasPermission(ResourceTypeSystem, Read) {
printMuxSystemResources(info)
}
fmt.Printf("%s: https://www.mux.com/docs/api-reference\n\n", color.GreenString("Ref"))
}
func printMuxVideoResources(info *secretInfo) {
t1 := table.NewWriter()
t1.SetTitle("Assets")
t1.AppendHeader(table.Row{"ID", "Title", "Duration", "Status", "Creator ID", "External ID", "Created At"})
t2 := table.NewWriter()
t2.SetTitle("Asset Tracks")
t2.AppendHeader(table.Row{"Asset ID", "ID", "Name", "Type", "Duration", "Status", "Primary"})
t3 := table.NewWriter()
t3.SetTitle("Asset Playback IDs")
t3.AppendHeader(table.Row{"Asset ID", "ID", "Policy"})
for _, asset := range info.Assets {
t1.AppendRow(table.Row{
color.GreenString(asset.ID),
color.GreenString(asset.Meta.Title),
color.GreenString(fmt.Sprintf("%.2fs", asset.Duration)),
color.GreenString(asset.Status),
color.GreenString(asset.Meta.CreatorID),
color.GreenString(asset.Meta.ExternalID),
color.GreenString(asset.CreatedAt),
})
t1.AppendSeparator()
for _, track := range asset.Tracks {
t2.AppendRow(table.Row{
color.GreenString(asset.ID),
color.GreenString(track.ID),
color.GreenString(track.Name),
color.GreenString(track.Type),
color.GreenString(fmt.Sprintf("%.2fs", track.Duration)),
color.GreenString(track.Status),
color.GreenString(fmt.Sprintf("%t", track.Primary)),
})
t2.AppendSeparator()
}
for _, playbackID := range asset.PlaybackIDs {
t3.AppendRow(table.Row{
color.GreenString(asset.ID),
color.GreenString(playbackID.ID),
color.GreenString(playbackID.Policy),
})
t3.AppendSeparator()
}
}
t1.SetOutputMirror(os.Stdout)
t1.Render()
t2.SetOutputMirror(os.Stdout)
t2.Render()
t3.SetOutputMirror(os.Stdout)
t3.Render()
}
func printMuxDataResources(info *secretInfo) {
t1 := table.NewWriter()
t1.SetTitle("Annotations")
t1.AppendHeader(table.Row{"ID", "Note", "Date", "Sub Property ID"})
for _, annotation := range info.Annotations {
t1.AppendRow(table.Row{
color.GreenString(annotation.ID),
color.GreenString(annotation.Note),
color.GreenString(annotation.Date),
color.GreenString(annotation.SubPropertyID),
})
}
t1.SetOutputMirror(os.Stdout)
t1.Render()
}
func printMuxSystemResources(info *secretInfo) {
t1 := table.NewWriter()
t1.SetTitle("Signing Keys")
t1.AppendHeader(table.Row{"ID", "Created At"})
for _, signingKey := range info.SigningKeys {
t1.AppendRow(table.Row{
color.GreenString(signingKey.ID),
color.GreenString(signingKey.CreatedAt),
})
}
t1.SetOutputMirror(os.Stdout)
t1.Render()
}
func getAccessLevelStringFromPermission(permission Permission) string {
switch permission {
case Read:
return "Read"
case FullAccess:
return "Read & Write"
default:
return "None"
}
}
+78
View File
@@ -0,0 +1,78 @@
package mux
import (
_ "embed"
"encoding/json"
"testing"
"time"
"github.com/trufflesecurity/trufflehog/v3/pkg/analyzer/config"
"github.com/trufflesecurity/trufflehog/v3/pkg/common"
"github.com/trufflesecurity/trufflehog/v3/pkg/context"
)
//go:embed expected_output.json
var expectedOutput []byte
func TestAnalyzer_Analyze(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), time.Minute*5)
defer cancel()
testSecrets, err := common.GetSecret(ctx, "trufflehog-testing", "analyzers1")
if err != nil {
t.Fatalf("could not get test secrets from GCP: %s", err)
}
key := testSecrets.MustGetField("MUX_KEY")
secret := testSecrets.MustGetField("MUX_SECRET")
tests := []struct {
name string
key string
secret string
want string
wantErr bool
}{
{
name: "valid mux credentials",
key: key,
secret: secret,
want: string(expectedOutput),
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
a := Analyzer{Cfg: &config.Config{}}
got, err := a.Analyze(ctx, map[string]string{
"key": tt.key,
"secret": tt.secret,
})
if (err != nil) != tt.wantErr {
t.Errorf("Analyzer.Analyze() error = %v, wantErr %v", err, tt.wantErr)
return
}
// marshal the actual result to JSON
gotJSON, err := json.Marshal(got)
if err != nil {
t.Fatalf("could not marshal got to JSON: %s", err)
}
// compare the JSON strings
if string(gotJSON) != string(tt.want) {
// pretty-print both JSON strings for easier comparison
var gotIndented, wantIndented []byte
gotIndented, err = json.MarshalIndent(got, "", " ")
if err != nil {
t.Fatalf("could not marshal got to indented JSON: %s", err)
}
wantIndented, err = json.MarshalIndent(tt.want, "", " ")
if err != nil {
t.Fatalf("could not marshal want to indented JSON: %s", err)
}
t.Errorf("Analyzer.Analyze() = %s, want %s", gotIndented, wantIndented)
}
})
}
}
+66
View File
@@ -0,0 +1,66 @@
// Code generated by go generate; DO NOT EDIT.
package mux
import "errors"
type Permission int
const (
Invalid Permission = iota
Read Permission = iota
FullAccess Permission = iota
)
var (
PermissionStrings = map[Permission]string{
Read: "read",
FullAccess: "full_access",
}
StringToPermission = map[string]Permission{
"read": Read,
"full_access": FullAccess,
}
PermissionIDs = map[Permission]int{
Read: 1,
FullAccess: 2,
}
IdToPermission = map[int]Permission{
1: Read,
2: FullAccess,
}
)
// ToString converts a Permission enum to its string representation
func (p Permission) ToString() (string, error) {
if str, ok := PermissionStrings[p]; ok {
return str, nil
}
return "", errors.New("invalid permission")
}
// ToID converts a Permission enum to its ID
func (p Permission) ToID() (int, error) {
if id, ok := PermissionIDs[p]; ok {
return id, nil
}
return 0, errors.New("invalid permission")
}
// PermissionFromString converts a string representation to its Permission enum
func PermissionFromString(s string) (Permission, error) {
if p, ok := StringToPermission[s]; ok {
return p, nil
}
return 0, errors.New("invalid permission string")
}
// PermissionFromID converts an ID to its Permission enum
func PermissionFromID(id int) (Permission, error) {
if p, ok := IdToPermission[id]; ok {
return p, nil
}
return 0, errors.New("invalid permission ID")
}
@@ -0,0 +1,3 @@
permissions:
- read
- full_access
+148
View File
@@ -0,0 +1,148 @@
package mux
import (
"encoding/json"
"fmt"
"io"
"net/http"
)
const muxAPIBaseURL = "https://api.mux.com"
func makeAPIRequest(client *http.Client, key, secret, method, endpoint string) ([]byte, int, error) {
req, err := http.NewRequest(method, muxAPIBaseURL+"/"+endpoint, nil)
if err != nil {
return nil, 0, err
}
req.SetBasicAuth(key, secret)
res, err := client.Do(req)
if err != nil {
return nil, 0, err
}
defer func() {
_, _ = io.Copy(io.Discard, res.Body)
_ = res.Body.Close()
}()
body, err := io.ReadAll(res.Body)
if err != nil {
return nil, 0, err
}
return body, res.StatusCode, nil
}
func testAllPermissions(client *http.Client, info *secretInfo, key string, secret string) error {
testsConfig, err := readTestsConfig()
if err != nil {
return err
}
for _, test := range testsConfig.Tests {
hasPermission, err := test.testPermission(client, key, secret)
if err != nil {
return err
}
if !hasPermission {
continue
}
info.addPermission(test.ResourceType, test.Permission)
}
return nil
}
func populateAllResources(client *http.Client, info *secretInfo, key string, secret string) error {
if info.hasPermission(ResourceTypeVideo, Read) {
if err := populateAssets(client, info, key, secret); err != nil {
return err
}
}
if info.hasPermission(ResourceTypeData, Read) {
if err := populateAnnotations(client, info, key, secret); err != nil {
return err
}
}
if info.hasPermission(ResourceTypeSystem, Read) {
if err := populateSigningKeys(client, info, key, secret); err != nil {
return err
}
}
return nil
}
func populateAssets(client *http.Client, info *secretInfo, key string, secret string) error {
const limit = 100
for page := 1; ; page++ {
url := fmt.Sprintf("/video/v1/assets?limit=%d&page=%d&timeframe[]=100:days", limit, page)
body, statusCode, err := makeAPIRequest(client, key, secret, http.MethodGet, url)
if err != nil {
return err
}
if statusCode != http.StatusOK {
return fmt.Errorf("unexpected status code: %d", statusCode)
}
resp := assetListResponse{}
if err := json.Unmarshal(body, &resp); err != nil {
return fmt.Errorf("failed to unmarshal data: %w", err)
}
if len(resp.Data) == 0 {
break
}
info.Assets = append(info.Assets, resp.Data...)
}
return nil
}
func populateAnnotations(client *http.Client, info *secretInfo, key string, secret string) error {
const limit = 100
for page := 1; ; page++ {
url := fmt.Sprintf("/data/v1/annotations?limit=%d&page=%d&timeframe[]=100:days", limit, page)
body, statusCode, err := makeAPIRequest(client, key, secret, http.MethodGet, url)
if err != nil {
return err
}
if statusCode != http.StatusOK {
return fmt.Errorf("unexpected status code: %d", statusCode)
}
resp := annotationListResponse{}
if err := json.Unmarshal(body, &resp); err != nil {
return fmt.Errorf("failed to unmarshal data: %w", err)
}
if len(resp.Data) == 0 {
break
}
info.Annotations = append(info.Annotations, resp.Data...)
}
return nil
}
func populateSigningKeys(client *http.Client, info *secretInfo, key string, secret string) error {
const limit = 100
for page := 1; ; page++ {
url := fmt.Sprintf("/system/v1/signing-keys?limit=%d&page=%d&timeframe[]=100:days", limit, page)
body, statusCode, err := makeAPIRequest(client, key, secret, http.MethodGet, url)
if err != nil {
return err
}
if statusCode != http.StatusOK {
return fmt.Errorf("unexpected status code: %d", statusCode)
}
resp := signingKeyListResponse{}
if err := json.Unmarshal(body, &resp); err != nil {
return fmt.Errorf("failed to unmarshal data: %w", err)
}
if len(resp.Data) == 0 {
break
}
info.SigningKeys = append(info.SigningKeys, resp.Data...)
}
return nil
}
+115
View File
@@ -0,0 +1,115 @@
package mux
import "github.com/trufflesecurity/trufflehog/v3/pkg/analyzer/analyzers"
var muxResourcesMap map[ResourceType][]string
func init() {
muxResourcesMap = map[ResourceType][]string{
ResourceTypeVideo: {
"Transcription Vocabularies",
"Web Inputs",
"Assets",
"Live Streams",
"Uploads",
"Playback Restrictions",
"DRM Configurations",
},
ResourceTypeData: {
"Video Views",
"Filters",
"Dimensions",
"Export",
"Metrics",
"Monitoring",
"Realtime",
"Incidents",
"Annotations",
},
ResourceTypeSystem: {
"Signing Keys",
},
}
}
func createAssetResource(asset asset) analyzers.Resource {
return analyzers.Resource{
Name: asset.ID,
FullyQualifiedName: "asset/" + asset.ID,
Type: "asset",
Metadata: map[string]any{
"duration": asset.Duration,
"status": asset.Status,
"videoQuality": asset.VideoQuality,
"mp4Support": asset.MP4Support,
"aspectRatio": asset.AspectRatio,
"createdAt": asset.CreatedAt,
},
}
}
func createAssetTrackResources(asset asset, parent *analyzers.Resource) []analyzers.Resource {
trackResources := []analyzers.Resource{}
for _, track := range asset.Tracks {
trackResources = append(trackResources, analyzers.Resource{
Name: track.ID,
FullyQualifiedName: "asset/" + asset.ID + "/track/" + track.ID,
Type: "track",
Metadata: map[string]any{
"name": track.Name,
"type": track.Type,
"duration": track.Duration,
"status": track.Status,
"primary": track.Primary,
"textType": track.TextType,
"textSource": track.TextSource,
"languageCode": track.LanguageCode,
"maxWidth": track.MaxWidth,
"maxHeight": track.MaxHeight,
"maxFrameRate": track.MaxFrameRate,
"maxChannels": track.MaxChannels,
},
Parent: parent,
})
}
return trackResources
}
func createAssetPlaybackIDResources(asset asset, parent *analyzers.Resource) []analyzers.Resource {
playbackIDResources := []analyzers.Resource{}
for _, playbackID := range asset.PlaybackIDs {
playbackIDResources = append(playbackIDResources, analyzers.Resource{
Name: playbackID.ID,
FullyQualifiedName: "asset/" + asset.ID + "/playback_id/" + playbackID.ID,
Type: "playback_id",
Metadata: map[string]any{
"policy": playbackID.Policy,
},
Parent: parent,
})
}
return playbackIDResources
}
func createAnnotationResource(annotation annotation) analyzers.Resource {
return analyzers.Resource{
Name: annotation.ID,
FullyQualifiedName: "annotation/" + annotation.ID,
Type: "annotation",
Metadata: map[string]any{
"subPropertyID": annotation.SubPropertyID,
"note": annotation.Note,
"date": annotation.Date,
},
}
}
func createSigningKeyResource(signingKey signingKey) analyzers.Resource {
return analyzers.Resource{
Name: signingKey.ID,
FullyQualifiedName: "signing_key/" + signingKey.ID,
Type: "signing_key",
Metadata: map[string]any{
"createdAt": signingKey.CreatedAt,
},
}
}
+46
View File
@@ -0,0 +1,46 @@
{
"tests": [
{
"resource_type": "video",
"permission": "read",
"endpoint": "/video/v1/assets?limit=1",
"method": "GET",
"valid_status_code": 200
},
{
"resource_type": "video",
"permission": "write",
"endpoint": "/video/v1/assets",
"method": "POST",
"valid_status_code": 400
},
{
"resource_type": "data",
"permission": "read",
"endpoint": "/data/v1/annotations?limit=1",
"method": "GET",
"valid_status_code": 200
},
{
"resource_type": "data",
"permission": "write",
"endpoint": "/data/v1/annotations",
"method": "POST",
"valid_status_code": 400
},
{
"resource_type": "system",
"permission": "read",
"endpoint": "/system/v1/signing-keys?limit=1",
"method": "GET",
"valid_status_code": 200
},
{
"resource_type": "system",
"permission": "write",
"endpoint": "/system/v1/signing-keys",
"method": "DELETE",
"valid_status_code": 400
}
]
}
+3
View File
@@ -24,6 +24,7 @@ import (
"github.com/trufflesecurity/trufflehog/v3/pkg/analyzer/analyzers/mailchimp"
"github.com/trufflesecurity/trufflehog/v3/pkg/analyzer/analyzers/mailgun"
"github.com/trufflesecurity/trufflehog/v3/pkg/analyzer/analyzers/monday"
"github.com/trufflesecurity/trufflehog/v3/pkg/analyzer/analyzers/mux"
"github.com/trufflesecurity/trufflehog/v3/pkg/analyzer/analyzers/mysql"
"github.com/trufflesecurity/trufflehog/v3/pkg/analyzer/analyzers/netlify"
"github.com/trufflesecurity/trufflehog/v3/pkg/analyzer/analyzers/ngrok"
@@ -133,5 +134,7 @@ func Run(keyType string, secretInfo SecretInfo) {
monday.AnalyzeAndPrintPermissions(secretInfo.Cfg, secretInfo.Parts["key"])
case "ngrok":
ngrok.AnalyzeAndPrintPermissions(secretInfo.Cfg, secretInfo.Parts["key"])
case "mux":
mux.AnalyzeAndPrintPermissions(secretInfo.Cfg, secretInfo.Parts["key"], secretInfo.Parts["secret"])
}
}
+6
View File
@@ -66,6 +66,12 @@ func (s Scanner) FromData(ctx context.Context, verify bool, data []byte) (result
s1.Verified = true
}
}
if s1.Verified {
s1.AnalysisInfo = map[string]string{
"key": resMatch,
"secret": resSecretMatch,
}
}
}
results = append(results, s1)
@@ -95,6 +95,17 @@ func New(c common.Common, keyType string) *AnalyzeForm {
Required: true,
RedactInput: true,
}}
case "mux":
inputs = []textinputs.InputConfig{{
Label: "Secret",
Key: "secret",
Required: true,
RedactInput: true,
}, {
Label: "Key",
Key: "key",
Required: true,
}}
default:
inputs = []textinputs.InputConfig{{
Label: "Secret",