scanner

package
v0.1.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 24, 2025 License: Apache-2.0 Imports: 31 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	WellKnownMCPFilenames = []string{

		"managed-settings.json",
		"settings.json",
		"mcp.json",

		"config.yaml",
		".continuerc.json",
		"config.json",

		"librechat.yaml",

		"mcp_config.json",
		"mcp_settings.json",
	}
)

Functions

func GetWellKnownMCPPaths

func GetWellKnownMCPPaths() []string

GetWellKnownMCPPaths returns the appropriate MCP config paths for the current operating system. Paths are expanded (~ and environment variables resolved) for immediate use.

func HumanDuration

func HumanDuration(d time.Duration) string

HumanDuration returns a compact, human-readable duration string. Examples: 850ms, 1.23s, 2m05s, 1h02m.

func PrintFooter

func PrintFooter()

func PrintSummary

func PrintSummary(summary ScanSummary, jsonOutput bool)

PrintSummary outputs the results in the requested format. If jsonOutput is true, it prints machine-readable JSON of the full results. Otherwise, it prints a human-readable summary with ratings and recommendations.

func RunTUIWithRealTimeScanning

func RunTUIWithRealTimeScanning(configPaths []string, scanner *MCPScanner, collector *RatingsCollector) error

RunTUIWithRealTimeScanning starts the TUI immediately and performs real-time scanning.

func RunTUIWithSummary

func RunTUIWithSummary(configPaths []string, summary ScanSummary) error

RunTUIWithSummary starts the TUI and simulates scanning with the provided results.

Types

type ClaudeConfigFile

type ClaudeConfigFile struct {
	MCPServers map[string]Server `json:"mcpServers"`
}

func (*ClaudeConfigFile) GetServers

func (c *ClaudeConfigFile) GetServers() map[string]Server

type ConfigKind

type ConfigKind int
const (
	KindUnknown ConfigKind = iota
	KindClaude
	KindVSCodeConfig
	KindVSCodeMCP
	KindContinue
	KindGoose
	KindLibreChat
)

func (ConfigKind) String

func (k ConfigKind) String() string

type ContinueConfigFile

type ContinueConfigFile struct {
	MCP map[string]Server `yaml:"mcp" json:"mcp"`
}

func (*ContinueConfigFile) GetServers

func (c *ContinueConfigFile) GetServers() map[string]Server

type Detector

type Detector interface {
	Classify(value string) (kind, confidence string, secretFound bool)
}

Detector classifies whether a string looks like a secret and returns its kind and confidence.

type FileResult

type FileResult struct {
	Path           string          `json:"path" validate:"omitempty,filepath"`
	Servers        []ServerConfig  `json:"servers,omitempty"`
	Error          *ScanError      `json:"error,omitempty"`
	SecretFindings []SecretFinding `json:"secret_findings,omitempty"`
}

FileResult represents the scan output for a single config file.

func NewFileResult

func NewFileResult(path string) *FileResult

type FileScanResult

type FileScanResult struct {
	FilePath string
	Servers  []ServerReport
	Error    error
	Complete bool
}

FileScanResult represents a result received from scanning.

type FileStatus

type FileStatus struct {
	Path        string
	State       apigen.ScanTargetStatus
	Spinner     spinner.Model
	Results     []ServerReport
	Errors      []string
	StartedAt   time.Time
	CompletedAt time.Time
}

FileStatus represents the state of a file being scanned.

type FindingSet

type FindingSet struct {
	// contains filtered or unexported fields
}

FindingSet aggregates secret findings by the hash of their raw values, merges occurrences, and can produce a deterministic, normalized list.

func NewFindingSet

func NewFindingSet() *FindingSet

func (*FindingSet) Add

func (s *FindingSet) Add(incoming SecretFinding)

Add merges the incoming finding into the set, grouping by ValueHash and aggregating occurrences. The caller is responsible for setting ValueHash.

func (*FindingSet) ListSorted

func (s *FindingSet) ListSorted() []SecretFinding

ListSorted returns a copy of all findings with de-duplicated, sorted line occurrences per file, ordered deterministically for stable output and tests.

type GooseConfigFile

type GooseConfigFile struct {
	MCPServers map[string]Server `yaml:"mcp_servers" json:"mcp_servers"`
}

func (*GooseConfigFile) GetServers

func (c *GooseConfigFile) GetServers() map[string]Server

type IdentifierExtractor

type IdentifierExtractor struct{}

IdentifierExtractor exposes helpers to derive zero or more TargetIdentifier from a server config. It centralizes heuristics previously scattered in ratings.go.

func NewIdentifierExtractor

func NewIdentifierExtractor() *IdentifierExtractor

NewIdentifierExtractor returns a new extractor instance.

func (*IdentifierExtractor) ExtractIdentifiers

func (x *IdentifierExtractor) ExtractIdentifiers(serverName string, serverConfig interface{}) []apigen.TargetIdentifier

ExtractIdentifiers inspects a single server config and returns zero or more identifiers. The order is deterministic and stable across platforms.

func (*IdentifierExtractor) ExtractIdentifiersFromServers

func (x *IdentifierExtractor) ExtractIdentifiersFromServers(servers map[string]Server) []apigen.TargetIdentifier

ExtractIdentifiersFromServers returns identifiers for all servers in a config map.

type LibreChatConfigFile

type LibreChatConfigFile struct {
	MCP struct {
		Servers map[string]Server `yaml:"servers" json:"servers"`
	} `yaml:"mcp" json:"mcp"`
}

func (*LibreChatConfigFile) GetServers

func (c *LibreChatConfigFile) GetServers() map[string]Server

type MCPConfig

type MCPConfig interface {
	GetServers() map[string]Server
}

type MCPScanner

type MCPScanner struct {
	ScanResult *ScanResult
	// contains filtered or unexported fields
}

func NewMCPScanner

func NewMCPScanner(targets []string, storageFile string) *MCPScanner

func (*MCPScanner) ParseMCPConfigFile

func (s *MCPScanner) ParseMCPConfigFile(path string) (MCPConfig, error)

func (*MCPScanner) Scan

func (s *MCPScanner) Scan() (*ScanResult, error)

func (*MCPScanner) WithRatingsCollector

func (s *MCPScanner) WithRatingsCollector(rc *RatingsCollector) *MCPScanner

WithRatingsCollector sets the ratings collector for live enrichment.

func (*MCPScanner) WithStreamingCallback

func (s *MCPScanner) WithStreamingCallback(callback func(filePath string, fileResult *FileResult, err error)) *MCPScanner

WithStreamingCallback sets a callback for real-time file processing updates.

type RatingsCollector

type RatingsCollector struct {
	// contains filtered or unexported fields
}

RatingsCollector batches identifier submissions to the ratings API and maps them back to servers. It also applies local allowlist decisions immediately.

func NewRatingsCollector

func NewRatingsCollector(ctx context.Context, client api.RatingsClient, st *storage.Storage) *RatingsCollector

NewRatingsCollector creates a new collector. Pass a nil client to operate offline.

func (*RatingsCollector) ApplyToSummary

func (rc *RatingsCollector) ApplyToSummary(summary *ScanSummary)

ApplyToSummary attaches local policies and any available ratings to the summary.

func (*RatingsCollector) FlushAndStop

func (rc *RatingsCollector) FlushAndStop()

FlushAndStop drains pending identifiers and stops workers.

func (*RatingsCollector) IsOffline

func (rc *RatingsCollector) IsOffline() bool

IsOffline reports whether the collector is operating without a remote client.

func (*RatingsCollector) SetClient added in v0.1.5

func (rc *RatingsCollector) SetClient(client api.RatingsClient)

SetClient sets the underlying ratings client after the collector has been created. If there is a pending batch, it will be flushed immediately.

func (*RatingsCollector) Submit

func (rc *RatingsCollector) Submit(serverName string, serverConfig interface{})

Submit records identifiers for a server and schedules a batched flush.

func (*RatingsCollector) WithStageNotifiers

func (rc *RatingsCollector) WithStageNotifiers(submitted func(string), processing func(string), received func(string)) *RatingsCollector

WithStageNotifiers sets optional callbacks for UI to reflect submission stages.

type Redactor

type Redactor func(string) string

type ScanError

type ScanError struct {
	Message string `json:"message,omitempty"`
	// Cause is a serialized error message for JSON friendliness.
	Cause string `json:"cause,omitempty"`
}

type ScanPhase

type ScanPhase int

ScanPhase represents the current phase of the TUI.

const (
	PhaseScanning ScanPhase = iota // Phase 1: Package-manager style file scanning
	PhaseResults                   // Phase 2: Table of servers with spinners
)

type ScanResult

type ScanResult struct {
	Targets        []string        `json:"targets"`
	Files          []FileResult    `json:"files"`
	Servers        []ServerConfig  `json:"servers,omitempty"`
	SecretFindings []SecretFinding `json:"secret_findings,omitempty"`

	StartedAt   time.Time     `json:"started_at"`
	Duration    time.Duration `json:"duration,omitempty"`
	CompletedAt time.Time     `json:"completed_at,omitempty"`

	Summary *ScanSummary `json:"summary,omitempty"`
}

ScanResult represents the results for an entire Scan across all targets.

func NewScanResult

func NewScanResult(targets []string) *ScanResult

type ScanSummary

type ScanSummary struct {
	Servers          []ServerReport  `json:"Servers"`
	Secrets          []SecretFinding `json:"Secrets"`
	TotalServers     int             `json:"TotalServers"`
	TotalFindings    int             `json:"TotalFindings"`
	CriticalFindings int             `json:"CriticalFindings"`
	HighFindings     int             `json:"HighFindings"`
	MediumFindings   int             `json:"MediumFindings"`
	LowFindings      int             `json:"LowFindings"`
	StartedAt        time.Time       `json:"StartedAt"`
	Duration         time.Duration   `json:"Duration"`
	ScannedFiles     int             `json:"ScannedFiles"`
}

ScanSummary provides a high-level summary of scan results.

func GenerateSummary

func GenerateSummary(result ScanResult) ScanSummary

GenerateSummary analyzes a single aggregated scan result and creates a summary.

func NewScanSummary

func NewScanSummary(result ScanResult) ScanSummary

type ScanTUIModel

type ScanTUIModel struct {
	// contains filtered or unexported fields
}

ScanTUIModel represents the main TUI model.

func NewScanTUI

func NewScanTUI(filePaths []string, deadline time.Duration) *ScanTUIModel

NewScanTUI creates a new TUI model.

func RunTUI

func RunTUI(files []string, deadline time.Duration) (*ScanTUIModel, error)

RunTUI starts the Bubble Tea program.

func (ScanTUIModel) Init

func (m ScanTUIModel) Init() tea.Cmd

Init implements tea.Model.

func (*ScanTUIModel) SendResult

func (m *ScanTUIModel) SendResult(result FileScanResult)

SendResult sends a scan result to the TUI.

func (ScanTUIModel) Update

func (m ScanTUIModel) Update(msg tea.Msg) (tea.Model, tea.Cmd)

Update implements tea.Model.

func (ScanTUIModel) View

func (m ScanTUIModel) View() string

View implements tea.Model.

type SecretFinding

type SecretFinding struct {
	Kind        string           `json:"kind"`
	Key         string           `json:"key"`
	Value       string           `json:"value"` // Redacted value
	Occurrences map[string][]int `json:"occurrences"`
	ValueHash   string           `json:"value_hash,omitempty"`
	ServerName  string           `json:"server_name"`
	Confidence  string           `json:"confidence"`
}

SecretFinding represents a detected secret.

func NewSecretFinding

func NewSecretFinding(
	serverName, secretKind, key, rawValue, confidence string,
	filePath string, line int,
) SecretFinding

NewSecretFinding constructs a SecretFinding with automatic value redaction. filePath is recorded for occurrences; pass line > 0 to record a single line.

type SecurityRating

type SecurityRating struct {
	Hash            string    `json:"hash"`
	Name            string    `json:"name"`
	Version         string    `json:"version"`
	Category        string    `json:"category"` // TRUSTED, SUSPICIOUS, UNTRUSTED, MALICIOUS
	RiskScore       float64   `json:"risk_score"`
	Vulnerabilities []string  `json:"vulnerabilities"` // CVE list
	LastUpdated     time.Time `json:"last_updated"`
	Source          string    `json:"source"` // "api", "heuristic", "manual"
}

SecurityRating represents a server's security assessment.

type Server

type Server = map[string]interface{}

Server represents a generic MCP server. Type alias to simplify handling in type switches.

type ServerConfig

type ServerConfig struct {
	Name   string      `json:"name,omitempty"`
	Server interface{} `json:"server"`
}

type ServerReport

type ServerReport struct {
	// TODO: add an id field to match IDs.md
	Name        string          `json:"name"`
	Path        string          `json:"path" validate:"omitempty,filepath"`
	Rating      *SecurityRating `json:"rating,omitempty"`
	Secrets     []SecretFinding `json:"secrets,omitempty"`
	LocalPolicy string          `json:"local_policy,omitempty"` // allowed|denied|unknown
}

ServerReport represents a server with attached rating and findings.

func NewServerReport

func NewServerReport(name string, path string, secrets []SecretFinding, localPolicy string) ServerReport

type ServerResult

type ServerResult struct {
	Name        string
	Sources     []string // Which files this server was found in
	Spinner     spinner.Model
	Stopwatch   stopwatch.Model
	Rating      *apigen.SecurityRating
	State       apigen.ScanTargetStatus
	StartedAt   time.Time
	CompletedAt time.Time
}

ServerResult represents a deduplicated MCP server with aggregated data.

type VSCodeConfigFile

type VSCodeConfigFile struct {
	MCP *VSCodeMCPConfig `json:"mcp"`
}

func (*VSCodeConfigFile) GetServers

func (c *VSCodeConfigFile) GetServers() map[string]Server

type VSCodeMCPConfig

type VSCodeMCPConfig struct {
	Servers map[string]Server `json:"servers"`
}

func (*VSCodeMCPConfig) GetServers

func (c *VSCodeMCPConfig) GetServers() map[string]Server

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL