-
Notifications
You must be signed in to change notification settings - Fork 10
Pluto 1390 semgrep installation and running #73
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
3faf5b0
1aed4c6
094d3ed
a191751
36886e5
bf0dcf4
90d4e4f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,3 +6,4 @@ tools: | |
| - [email protected] | ||
| - [email protected] | ||
| - [email protected] | ||
| - [email protected] | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| name: semgrep | ||
| description: Static Analysis Security Testing (SAST) tool | ||
| runtime: python | ||
| runtime_binaries: | ||
| package_manager: python3 | ||
| execution: python3 | ||
| binaries: | ||
| - name: python | ||
| path: "venv/bin/python3" | ||
| formatters: | ||
| - name: json | ||
| flag: "--json" | ||
| output_options: | ||
| file_flag: "--output" | ||
| analysis_options: | ||
| default_path: "." |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| package tools | ||
|
|
||
| import ( | ||
| "codacy/cli-v2/config" | ||
| "codacy/cli-v2/plugins" | ||
| "fmt" | ||
| "os" | ||
| "os/exec" | ||
| "path/filepath" | ||
| ) | ||
|
|
||
| // RunSemgrep executes Semgrep analysis on the specified directory | ||
| func RunSemgrep(workDirectory string, toolInfo *plugins.ToolInfo, files []string, outputFile string, outputFormat string) error { | ||
| // Construct base command with -m semgrep to run semgrep module | ||
| cmdArgs := []string{"scan"} | ||
|
|
||
| // Add output format if specified | ||
| if outputFormat == "sarif" { | ||
| cmdArgs = append(cmdArgs, "--sarif") | ||
| } | ||
|
|
||
| // Define possible Semgrep config file names | ||
| semgrepConfigFiles := []string{".semgrep.yml", ".semgrep.yaml", ".semgrep/semgrep.yml"} | ||
|
|
||
| // Check if a config file exists in the expected location and use it if present | ||
| if configFile, exists := ConfigFileExists(config.Config, semgrepConfigFiles...); exists { | ||
| cmdArgs = append(cmdArgs, "--config", configFile) | ||
| } else { | ||
| // add --config auto only if no config file exists | ||
| cmdArgs = append(cmdArgs, "--config", "auto") | ||
| } | ||
|
|
||
| // Add files to analyze - if no files specified, analyze current directory | ||
| if len(files) > 0 { | ||
| cmdArgs = append(cmdArgs, files...) | ||
| } else { | ||
| cmdArgs = append(cmdArgs, ".") | ||
| } | ||
|
|
||
| cmdArgs = append(cmdArgs, "--disable-version-check") | ||
|
|
||
| // Get Semgrep binary from the specified installation path | ||
| semgrepPath := filepath.Join(toolInfo.InstallDir, "venv", "bin", "semgrep") | ||
|
|
||
| // Create Semgrep command | ||
| cmd := exec.Command(semgrepPath, cmdArgs...) | ||
|
Check failure on line 46 in tools/semgrepRunner.go
|
||
| cmd.Dir = workDirectory | ||
|
|
||
| if outputFile != "" { | ||
| // If output file is specified, create it and redirect output | ||
| var outputWriter *os.File | ||
| var err error | ||
| outputWriter, err = os.Create(filepath.Clean(outputFile)) | ||
| if err != nil { | ||
| return fmt.Errorf("failed to create output file: %w", err) | ||
| } | ||
| defer outputWriter.Close() | ||
| cmd.Stdout = outputWriter | ||
| } else { | ||
| cmd.Stdout = os.Stdout | ||
| } | ||
| cmd.Stderr = os.Stderr | ||
|
|
||
| // Run Semgrep | ||
| if err := cmd.Run(); err != nil { | ||
| // Semgrep returns non-zero exit code when it finds issues, which is expected | ||
| if _, ok := err.(*exec.ExitError); !ok { | ||
| return fmt.Errorf("failed to run semgrep: %w", err) | ||
| } | ||
| } | ||
|
|
||
| return nil | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| package tools | ||
|
|
||
| import ( | ||
| "codacy/cli-v2/plugins" | ||
| "os" | ||
| "path/filepath" | ||
| "testing" | ||
|
|
||
| "github.com/stretchr/testify/assert" | ||
| ) | ||
|
|
||
| func TestRunSemgrepWithSpecificFiles(t *testing.T) { | ||
| homeDirectory, err := os.UserHomeDir() | ||
| if err != nil { | ||
| t.Fatalf("Failed to get home directory: %v", err) | ||
| } | ||
| currentDirectory, err := os.Getwd() | ||
| if err != nil { | ||
| t.Fatalf("Failed to get current directory: %v", err) | ||
| } | ||
|
|
||
| // Set up test directories and files | ||
| testDirectory := filepath.Join(currentDirectory, "testdata", "repositories", "semgrep") | ||
| tempResultFile := filepath.Join(os.TempDir(), "semgrep-specific.sarif") | ||
| defer os.Remove(tempResultFile) | ||
|
|
||
| // Create tool info for semgrep | ||
| toolInfo := &plugins.ToolInfo{ | ||
| InstallDir: filepath.Join(homeDirectory, ".cache/codacy/tools/[email protected]"), | ||
| } | ||
|
|
||
| // Specify files to analyze | ||
| filesToAnalyze := []string{"sample.js"} | ||
|
|
||
| // Run Semgrep analysis on specific files | ||
| err = RunSemgrep(testDirectory, toolInfo, filesToAnalyze, tempResultFile, "sarif") | ||
| if err != nil { | ||
| t.Fatalf("Failed to run semgrep on specific files: %v", err) | ||
| } | ||
|
|
||
| // Verify file exists and has content | ||
| fileInfo, err := os.Stat(tempResultFile) | ||
| assert.NoError(t, err, "Failed to stat output file") | ||
| assert.Greater(t, fileInfo.Size(), int64(0), "Output file should not be empty") | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| { | ||
| "version": "2.1.0", | ||
| "$schema": "http://json.schemastore.org/sarif-2.1.0-rtm.5", | ||
| "runs": [ | ||
| { | ||
| "tool": { | ||
| "driver": { | ||
| "name": "Semgrep", | ||
| "version": "1.41.0", | ||
| "informationUri": "https://semgrep.dev", | ||
| "rules": [ | ||
| { | ||
| "id": "hardcoded-credentials", | ||
| "name": "Hardcoded Credentials", | ||
| "shortDescription": { | ||
| "text": "Hardcoded API key detected" | ||
| }, | ||
| "fullDescription": { | ||
| "text": "Found hardcoded API key. This is a security risk." | ||
| }, | ||
| "defaultConfiguration": { | ||
| "level": "warning" | ||
| }, | ||
| "help": { | ||
| "text": "API keys and other credentials should not be hardcoded in source files. Use environment variables or secure credential storage instead." | ||
| } | ||
| } | ||
| ] | ||
| } | ||
| }, | ||
| "artifacts": [ | ||
| { | ||
| "location": { | ||
| "uri": "testdata/repositories/semgrep/sample.js" | ||
| } | ||
| } | ||
| ], | ||
| "results": [ | ||
| { | ||
| "ruleId": "hardcoded-credentials", | ||
| "level": "warning", | ||
| "message": { | ||
| "text": "Hardcoded API key detected" | ||
| }, | ||
| "locations": [ | ||
| { | ||
| "physicalLocation": { | ||
| "artifactLocation": { | ||
| "uri": "testdata/repositories/semgrep/sample.js" | ||
| }, | ||
| "region": { | ||
| "startLine": 3, | ||
| "startColumn": 16, | ||
| "endLine": 3, | ||
| "endColumn": 32 | ||
| } | ||
| } | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| // Sample JavaScript file for Semgrep testing | ||
|
|
||
| const API_KEY = "1234567890abcdef"; // Hardcoded credential for testing | ||
|
Check notice on line 3 in tools/testdata/repositories/semgrep/sample.js
|
||
|
|
||
| function helloWorld() { | ||
| console.log("Hello, world!"); | ||
| console.log("Using API Key:", API_KEY); | ||
| } | ||
|
|
||
| helloWorld(); | ||
Uh oh!
There was an error while loading. Please reload this page.