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
28 changes: 28 additions & 0 deletions pkg/analysis/passes/gosec/gosec.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/json"
"errors"
"fmt"
"io/fs"
"os/exec"
"path/filepath"
"strings"
Expand Down Expand Up @@ -62,6 +63,17 @@ func run(pass *analysis.Pass) (interface{}, error) {
return nil, err
}

// gosec exits 1 without output when it finds no Go files, which is indistinguishable from a failed scan.
hasGo, err := hasGoFiles(sourceCodeDir)
if err != nil {
pass.ReportIncomplete("Could not inspect source code for Go files: " + err.Error())
return nil, nil
}
if !hasGo {
logme.Debugln("no Go files in source code, skipping gosec analysis")
return nil, nil
}

// gosec resolves relative file paths against the module root.
goSecCommand := exec.Command(
goSecBin,
Expand Down Expand Up @@ -132,3 +144,19 @@ func run(pass *analysis.Pass) (interface{}, error) {

return nil, nil
}

func hasGoFiles(dir string) (bool, error) {
found := false
err := filepath.WalkDir(dir, func(_ string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
if d.IsDir() || filepath.Ext(d.Name()) != ".go" {
return nil
}

found = true
return fs.SkipAll
})
return found, err
}
22 changes: 22 additions & 0 deletions pkg/analysis/passes/gosec/incomplete_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ func TestIncompleteScan(t *testing.T) {
t.Run(script, func(t *testing.T) {
directory := t.TempDir()
require.NoError(t, os.WriteFile(filepath.Join(directory, "gosec"), []byte("#!/bin/sh\n"+script+"\n"), 0755))
require.NoError(t, os.WriteFile(filepath.Join(directory, "main.go"), []byte("package main\n"), 0644))
t.Setenv("PATH", directory)
var interceptor testpassinterceptor.TestPassInterceptor
pass := &analysis.Pass{AnalyzerName: Analyzer.Name, ResultOf: map[*analysis.Analyzer]any{sourcecode.Analyzer: directory}, Report: interceptor.ReportInterceptor()}
Expand All @@ -30,6 +31,7 @@ func TestIncompleteScan(t *testing.T) {
func TestQuietSuccessfulScan(t *testing.T) {
directory := t.TempDir()
require.NoError(t, os.WriteFile(filepath.Join(directory, "gosec"), []byte("#!/bin/sh\nexit 0\n"), 0755))
require.NoError(t, os.WriteFile(filepath.Join(directory, "main.go"), []byte("package main\n"), 0644))
t.Setenv("PATH", directory)
var interceptor testpassinterceptor.TestPassInterceptor
pass := &analysis.Pass{
Expand All @@ -41,3 +43,23 @@ func TestQuietSuccessfulScan(t *testing.T) {
require.NoError(t, err)
require.Empty(t, interceptor.Diagnostics)
}

// gosec exits 1 without output when the source tree has no Go files.
func TestSourceWithoutGoFiles(t *testing.T) {
binDir := t.TempDir()
require.NoError(t, os.WriteFile(filepath.Join(binDir, "gosec"), []byte("#!/bin/sh\nexit 1\n"), 0755))
t.Setenv("PATH", binDir)

sourceDir := t.TempDir()
require.NoError(t, os.WriteFile(filepath.Join(sourceDir, "index.ts"), []byte("export const a = 1;\n"), 0644))

var interceptor testpassinterceptor.TestPassInterceptor
pass := &analysis.Pass{
AnalyzerName: Analyzer.Name,
ResultOf: map[*analysis.Analyzer]any{sourcecode.Analyzer: sourceDir},
Report: interceptor.ReportInterceptor(),
}
_, err := run(pass)
require.NoError(t, err)
require.Empty(t, interceptor.Diagnostics)
}
Loading