Skip to content
Merged
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
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.1.0
0.1.2
2 changes: 1 addition & 1 deletion checks.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
// check prompt.
//
// Returns an empty slice (not an error) if the directory does not exist.
func LoadChecks(dir string) ([]CustomCheck, error) {

Check failure on line 41 in checks.go

View workflow job for this annotation

GitHub Actions / deadcode

unreachable func: LoadChecks
entries, err := os.ReadDir(dir)
if err != nil {
if os.IsNotExist(err) {
Expand All @@ -57,7 +57,7 @@
}

path := filepath.Join(dir, entry.Name())
data, err := os.ReadFile(path)
data, err := os.ReadFile(path) // #nosec G304 -- path is joined from the checks directory being loaded (typically ".sight/checks/") and an entry name from os.ReadDir on that same directory, not raw user input
if err != nil {
continue
}
Expand All @@ -72,14 +72,14 @@

// LoadChecksFromRepo is a convenience that looks for .sight/checks/ relative
// to the given repository root directory.
func LoadChecksFromRepo(repoDir string) ([]CustomCheck, error) {

Check failure on line 75 in checks.go

View workflow job for this annotation

GitHub Actions / deadcode

unreachable func: LoadChecksFromRepo
return LoadChecks(filepath.Join(repoDir, ".sight", "checks"))
}

// CustomChecksToConcerns converts loaded custom checks into internal Concern
// values suitable for the review pipeline. Only enabled checks are included.
// If languages is non-empty, the concern prompt notes which languages apply.
func CustomChecksToConcerns(checks []CustomCheck) []review.Concern {

Check failure on line 82 in checks.go

View workflow job for this annotation

GitHub Actions / deadcode

unreachable func: CustomChecksToConcerns
var concerns []review.Concern
for _, c := range checks {
if !c.Enabled {
Expand All @@ -105,7 +105,7 @@
// additional concerns to the review. This is the primary integration point:
//
// sight.Review(ctx, diff, sight.WithCustomChecks(".sight/checks"))
func WithCustomChecks(dir string) Option {

Check failure on line 108 in checks.go

View workflow job for this annotation

GitHub Actions / deadcode

unreachable func: WithCustomChecks
return optFunc(func(c *config) {
checks, err := LoadChecks(dir)
if err != nil || len(checks) == 0 {
Expand All @@ -120,7 +120,7 @@
}

// WithCustomChecksFromRepo loads checks from .sight/checks/ within the repo root.
func WithCustomChecksFromRepo(repoDir string) Option {

Check failure on line 123 in checks.go

View workflow job for this annotation

GitHub Actions / deadcode

unreachable func: WithCustomChecksFromRepo
return WithCustomChecks(filepath.Join(repoDir, ".sight", "checks"))
}

Expand Down
15 changes: 14 additions & 1 deletion config.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ type FileConfig struct {
Reflection *bool `json:"reflection"`
Parallel *bool `json:"parallel"`
Prompts map[string]string `json:"prompts"`
Graph *bool `json:"graph"`
Audit *string `json:"audit"` // "none", "hooks", "mcp", "full"
}

// LoadConfigFile reads .sight.toml from the given directory (or parents).
Expand All @@ -38,7 +40,7 @@ func LoadConfigFile(dir string) (*FileConfig, error) {
return nil, fmt.Errorf("config file %s is too large (%d bytes, max %d bytes)", path, info.Size(), maxConfigSize)
}

data, err := os.ReadFile(path)
data, err := os.ReadFile(path) // #nosec G304 -- path comes from findConfigFile(dir), which searches for .sight.toml in the project directory being reviewed or its parents, not attacker-controlled input
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -78,6 +80,12 @@ func ApplyFileConfig(fc *FileConfig) []Option {
if len(fc.Exclude) > 0 {
opts = append(opts, WithExclude(fc.Exclude...))
}
if fc.Graph != nil {
opts = append(opts, WithGraph(*fc.Graph))
}
if fc.Audit != nil {
opts = append(opts, WithAuditMode(ParseAuditMode(*fc.Audit)))
}

return opts
}
Expand Down Expand Up @@ -152,6 +160,11 @@ func parseTOMLConfig(content string) (*FileConfig, error) {
case "parallel":
b := value == "true"
cfg.Parallel = &b
case "graph":
b := value == "true"
cfg.Graph = &b
case "audit":
cfg.Audit = &value
}
}

Expand Down
86 changes: 86 additions & 0 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,89 @@ srv.ServeHTTP("127.0.0.1:8080") // 🌐 streamable HTTP transport, served at /mc
**30+ built-in rules** run without LLM overhead — hardcoded secret patterns, SQL injection sinks, unsafe deserialization, etc. Fused with LLM results.

**Taint analysis** (exposed via the `sight_taint` MCP tool and the taint-analysis API) uses SSA-based cross-function tracking to detect source→sink data flows. Sources, sinks, and sanitizers are configurable.

---

## 🔗 Structural Dependency Graph

The `internal/graph` package provides **optional structural dependency analysis** for code reviews:

**Key capabilities:**
- Parse Go AST to build structural dependency graph
- Blast-radius analysis: identify all files affected by changes
- Transitive dependency tracking
- Impact scoring based on depth and number of dependents
- SQLite persistence for incremental updates

**Usage:**
```go
// Enable graph-backed review
g := graph.New()
// ... build graph or load from SQLite ...

// Run blast radius analysis
result := g.GetBlastRadius([]string{"file.go"})
fmt.Printf("Direct: %d, Transitive: %d\n", result.Direct, result.Transitive)
```

**Tools exposed via MCP:** `sight_graph_blastRadius`, `sight_graph_query`, `sight_graph_stats`

---

## 🔒 Security Auditing

The `internal/audit` package provides **agent surface security auditing**:

**Key capabilities:**
- Concurrent security scanning of multiple targets
- Filter findings by severity (critical, high, medium, low) or category
- Integration with MCP hooks, permissions, and endpoints
- Webhook validation and test requests
- JSON-serializable audit findings

**Usage:**
```go
// Create audit scope
auditScope := &audit.AuditScope{
Targets: []audit.AuditTarget{
{Type: audit.AuditTargetHooks, Path: "/hooks/webhook"},
{Type: audit.AuditTargetEndpoints, Path: "/api/endpoint"},
},
Rules: []string{"detect_unauthenticated_endpoints", "detect_hardcoded_secrets"},
}

// Run audit
report, err := audit.Audit(ctx, auditScope)
if report.Count() > 0 {
fmt.Printf("Found %d security issues\n", report.Count())
}
```

---

## 🌐 Browser Automation Tools

The `internal/tool` package provides **HTTP-based browser automation** capabilities:

**Key capabilities:**
- HTTP client with configurable timeouts and redirects
- Browser tool with GET, POST, and header management
- Response parsing with JSON support
- Webhook testing: send test payloads and validate responses
- Formatter for structured output

**Usage:**
```go
// Create browser tool
browser := tool.NewBrowserTool()

// Make requests
resp, err := browser.Get(ctx, "https://example.com")
if err == nil && resp.IsSuccess() {
fmt.Printf("Status: %d\n", resp.StatusCode)
}

// Test webhooks
webhook := tool.NewWebhookTester()
resp, err := webhook.SendTestRequest(ctx, "https://webhook.example.com", payload)
```
2 changes: 1 addition & 1 deletion eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ func RunEval(ctx context.Context, suite *EvalSuite, opts ...Option) ([]EvalResul

// LoadEvalSuite loads eval cases from a JSON file.
func LoadEvalSuite(path string) (*EvalSuite, error) {
data, err := os.ReadFile(path)
data, err := os.ReadFile(path) // #nosec G304 -- path is a caller-supplied eval suite file location (this tool's own eval fixtures), not attacker-controlled input
if err != nil {
return nil, fmt.Errorf("loading eval suite: %w", err)
}
Expand Down
Loading
Loading