mirror of
https://github.com/securego/gosec.git
synced 2025-11-23 22:15:04 +02:00
* upgrade gemini sdk to google.golang.org/genai v1.25.0 * support newer gemini models * add anthropic claude
76 lines
2.0 KiB
Go
76 lines
2.0 KiB
Go
package autofix
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/securego/gosec/v2/issue"
|
|
)
|
|
|
|
const (
|
|
AIProviderFlagHelp = `AI API provider to generate auto fixes to issues. Valid options are:
|
|
- gemini-2.5-pro, gemini-2.5-flash, gemini-2.5-flash-lite, gemini-2.0-flash, gemini-2.0-flash-lite (gemini, default);
|
|
- claude-sonnet-4-0 (claude, default), claude-opus-4-0, claude-opus-4-1, claude-sonnet-3-7`
|
|
|
|
AIPrompt = `Provide a brief explanation and a solution to fix this security issue
|
|
in Go programming language: %q.
|
|
Answer in markdown format and keep the response limited to 200 words.`
|
|
|
|
timeout = 30 * time.Second
|
|
)
|
|
|
|
type GenAIClient interface {
|
|
GenerateSolution(ctx context.Context, prompt string) (string, error)
|
|
}
|
|
|
|
// GenerateSolution generates a solution for the given issues using the specified AI provider
|
|
func GenerateSolution(model, aiAPIKey string, issues []*issue.Issue) (err error) {
|
|
var client GenAIClient
|
|
|
|
switch {
|
|
case strings.HasPrefix(model, "claude"):
|
|
client, err = NewClaudeClient(model, aiAPIKey)
|
|
case strings.HasPrefix(model, "gemini"):
|
|
client, err = NewGeminiClient(model, aiAPIKey)
|
|
}
|
|
|
|
switch {
|
|
case err != nil:
|
|
return fmt.Errorf("initializing AI client: %w", err)
|
|
case client == nil:
|
|
return fmt.Errorf("unsupported AI backend: %s", model)
|
|
}
|
|
|
|
return generateSolution(client, issues)
|
|
}
|
|
|
|
func generateSolution(client GenAIClient, issues []*issue.Issue) error {
|
|
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
|
defer cancel()
|
|
|
|
cachedAutofix := make(map[string]string)
|
|
for _, issue := range issues {
|
|
if val, ok := cachedAutofix[issue.What]; ok {
|
|
issue.Autofix = val
|
|
continue
|
|
}
|
|
|
|
prompt := fmt.Sprintf(AIPrompt, issue.What)
|
|
resp, err := client.GenerateSolution(ctx, prompt)
|
|
if err != nil {
|
|
return fmt.Errorf("generating autofix with gemini: %w", err)
|
|
}
|
|
|
|
if resp == "" {
|
|
return errors.New("no autofix returned by gemini")
|
|
}
|
|
|
|
issue.Autofix = resp
|
|
cachedAutofix[issue.What] = issue.Autofix
|
|
}
|
|
return nil
|
|
}
|