Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
1 change: 0 additions & 1 deletion .codacy/cli-config.yaml

This file was deleted.

2 changes: 1 addition & 1 deletion .codacy/codacy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ runtimes:
- [email protected]
- [email protected]
tools:
- eslint@9.3.0
- eslint@8.57.0
- [email protected]
- [email protected]
- [email protected]
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,8 @@ go.work.sum
.idea/
.vscode/

# Codacy CLI
cli-v2
.codacy/cli-config.yaml
.codacy/tools-configs
.codacy/tools-configs/*
4 changes: 1 addition & 3 deletions cmd/analyze.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ var outputFormat string
var sarifPath string
var commitUuid string
var projectToken string
var pmdRulesetFile string

type Sarif struct {
Runs []struct {
Expand Down Expand Up @@ -96,7 +95,6 @@ func init() {
analyzeCmd.Flags().StringVarP(&toolToAnalyze, "tool", "t", "", "Which tool to run analysis with")
analyzeCmd.Flags().StringVar(&outputFormat, "format", "", "Output format (use 'sarif' for SARIF format)")
analyzeCmd.Flags().BoolVar(&autoFix, "fix", false, "Apply auto fix to your issues when available")
analyzeCmd.Flags().StringVar(&pmdRulesetFile, "rulesets", "", "Path to PMD ruleset file")
rootCmd.AddCommand(analyzeCmd)
}

Expand Down Expand Up @@ -209,7 +207,7 @@ func runPmdAnalysis(workDirectory string, pathsToCheck []string, outputFile stri
pmd := config.Config.Tools()["pmd"]
pmdBinary := pmd.Binaries["pmd"]

err := tools.RunPmd(workDirectory, pmdBinary, pathsToCheck, outputFile, outputFormat, pmdRulesetFile)
err := tools.RunPmd(workDirectory, pmdBinary, pathsToCheck, outputFile, outputFormat, "")
if err != nil {
log.Fatalf("Error running PMD: %v", err)
}
Expand Down
40 changes: 24 additions & 16 deletions cmd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"log"
"net/http"
"os"
"path/filepath"
"time"

"github.com/spf13/cobra"
Expand Down Expand Up @@ -142,6 +143,13 @@
fmt.Println("Building repository configuration files ...")
fmt.Println("Fetching repository configuration from codacy ...")

toolsConfigDir := config.Config.ToolsConfigDirectory()

// Create tools-configs directory if it doesn't exist
if err := os.MkdirAll(toolsConfigDir, 0777); err != nil {

Check warning on line 149 in cmd/init.go

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

cmd/init.go#L149

Detected file permissions that are set to more than `0600` (user/owner can read and write). Setting file permissions to higher than `0600` is most likely unnecessary and violates the principle of least privilege.

Check warning on line 149 in cmd/init.go

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

cmd/init.go#L149

The application was found setting directory permissions to overly permissive values.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trying to give less permission seems cool

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done, added constants

return fmt.Errorf("failed to create tools-configs directory: %w", err)
}

// API call to fetch settings
url := CodacyApiBase + "/2.0/project/analysis/configuration"

Expand Down Expand Up @@ -198,7 +206,7 @@
eslintDomainConfiguration := convertAPIToolConfigurationToDomain(*eslintApiConfiguration)
eslintConfigurationString := tools.CreateEslintConfig(eslintDomainConfiguration)

eslintConfigFile, err := os.Create("eslint.config.mjs")
eslintConfigFile, err := os.Create(filepath.Join(toolsConfigDir, "eslint.config.mjs"))
if err != nil {
return fmt.Errorf("failed to create eslint config file: %v", err)
}
Expand All @@ -210,7 +218,7 @@
}
fmt.Println("ESLint configuration created based on Codacy settings")
} else {
err = createDefaultEslintConfigFile()
err = createDefaultEslintConfigFile(toolsConfigDir)
if err != nil {
return fmt.Errorf("failed to create default ESLint config: %v", err)
}
Expand All @@ -220,13 +228,13 @@
// Trivy configuration
trivyApiConfiguration := extractTrivyConfiguration(apiToolConfigurations)
if trivyApiConfiguration != nil {
err = createTrivyConfigFile(*trivyApiConfiguration)
err = createTrivyConfigFile(*trivyApiConfiguration, toolsConfigDir)
if err != nil {
return fmt.Errorf("failed to create Trivy config: %v", err)
}
fmt.Println("Trivy configuration created based on Codacy settings")
} else {
err = createDefaultTrivyConfigFile()
err = createDefaultTrivyConfigFile(toolsConfigDir)
if err != nil {
return fmt.Errorf("failed to create default Trivy config: %v", err)
}
Expand All @@ -236,13 +244,13 @@
// PMD configuration
pmdApiConfiguration := extractPMDConfiguration(apiToolConfigurations)
if pmdApiConfiguration != nil {
err = createPMDConfigFile(*pmdApiConfiguration)
err = createPMDConfigFile(*pmdApiConfiguration, toolsConfigDir)
if err != nil {
return fmt.Errorf("failed to create PMD config: %v", err)
}
fmt.Println("PMD configuration created based on Codacy settings")
} else {
err = createDefaultPMDConfigFile()
err = createDefaultPMDConfigFile(toolsConfigDir)
if err != nil {
return fmt.Errorf("failed to create default PMD config: %v", err)
}
Expand Down Expand Up @@ -318,16 +326,16 @@
return nil
}

func createPMDConfigFile(config CodacyToolConfiguration) error {
func createPMDConfigFile(config CodacyToolConfiguration, toolsConfigDir string) error {
pmdDomainConfiguration := convertAPIToolConfigurationToDomain(config)
pmdConfigurationString := tools.CreatePmdConfig(pmdDomainConfiguration)
return os.WriteFile("pmd-ruleset.xml", []byte(pmdConfigurationString), 0644)
return os.WriteFile(filepath.Join(toolsConfigDir, "pmd-ruleset.xml"), []byte(pmdConfigurationString), 0644)

Check warning on line 332 in cmd/init.go

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

cmd/init.go#L332

The application was found setting file permissions to overly permissive values.
}

func createDefaultPMDConfigFile() error {
func createDefaultPMDConfigFile(toolsConfigDir string) error {
emptyConfig := tools.ToolConfiguration{}
content := tools.CreatePmdConfig(emptyConfig)
return os.WriteFile("pmd-ruleset.xml", []byte(content), 0644)
return os.WriteFile(filepath.Join(toolsConfigDir, "pmd-ruleset.xml"), []byte(content), 0644)

Check warning on line 338 in cmd/init.go

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

cmd/init.go#L338

The application was found setting file permissions to overly permissive values.
}

type CodacyToolConfiguration struct {
Expand All @@ -347,15 +355,15 @@
}

// createTrivyConfigFile creates a trivy.yaml configuration file based on the API configuration
func createTrivyConfigFile(config CodacyToolConfiguration) error {
func createTrivyConfigFile(config CodacyToolConfiguration, toolsConfigDir string) error {
// Convert CodacyToolConfiguration to tools.ToolConfiguration
trivyDomainConfiguration := convertAPIToolConfigurationForTrivy(config)

// Use the shared CreateTrivyConfig function to generate the config content
trivyConfigurationString := tools.CreateTrivyConfig(trivyDomainConfiguration)

// Write to file
return os.WriteFile("trivy.yaml", []byte(trivyConfigurationString), 0644)
return os.WriteFile(filepath.Join(toolsConfigDir, "trivy.yaml"), []byte(trivyConfigurationString), 0644)

Check warning on line 366 in cmd/init.go

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

cmd/init.go#L366

The application was found setting file permissions to overly permissive values.
}

// convertAPIToolConfigurationForTrivy converts API tool configuration to domain model for Trivy
Expand Down Expand Up @@ -399,21 +407,21 @@
}

// createDefaultTrivyConfigFile creates a default trivy.yaml configuration file
func createDefaultTrivyConfigFile() error {
func createDefaultTrivyConfigFile(toolsConfigDir string) error {
// Use empty tool configuration to get default settings
emptyConfig := tools.ToolConfiguration{}
content := tools.CreateTrivyConfig(emptyConfig)

// Write to file
return os.WriteFile("trivy.yaml", []byte(content), 0644)
return os.WriteFile(filepath.Join(toolsConfigDir, "trivy.yaml"), []byte(content), 0644)

Check warning on line 416 in cmd/init.go

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

cmd/init.go#L416

The application was found setting file permissions to overly permissive values.
}

// createDefaultEslintConfigFile creates a default eslint.config.mjs configuration file
func createDefaultEslintConfigFile() error {
func createDefaultEslintConfigFile(toolsConfigDir string) error {
// Use empty tool configuration to get default settings
emptyConfig := tools.ToolConfiguration{}
content := tools.CreateEslintConfig(emptyConfig)

// Write to file
return os.WriteFile("eslint.config.mjs", []byte(content), 0644)
return os.WriteFile(filepath.Join(toolsConfigDir, "eslint.config.mjs"), []byte(content), 0644)

Check warning on line 426 in cmd/init.go

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

cmd/init.go#L426

The application was found setting file permissions to overly permissive values.
}
6 changes: 6 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
runtimesDirectory string
toolsDirectory string
localCodacyDirectory string
toolsConfigDirectory string
projectConfigFile string
cliConfigFile string

Expand Down Expand Up @@ -88,11 +89,16 @@
return nil
}

func (c *ConfigType) ToolsConfigDirectory() string {

Check notice on line 92 in config/config.go

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

config/config.go#L92

exported method ConfigType.ToolsConfigDirectory should have comment or be unexported
return c.toolsConfigDirectory
}

func (c *ConfigType) setupCodacyPaths() {
c.globalCacheDirectory = filepath.Join(c.homePath, ".cache", "codacy")
c.runtimesDirectory = filepath.Join(c.globalCacheDirectory, "runtimes")
c.toolsDirectory = filepath.Join(c.globalCacheDirectory, "tools")
c.localCodacyDirectory = ".codacy"
c.toolsConfigDirectory = filepath.Join(c.localCodacyDirectory, "tools-configs")

c.projectConfigFile = filepath.Join(c.localCodacyDirectory, "codacy.yaml")
c.cliConfigFile = filepath.Join(c.localCodacyDirectory, "cli-config.yaml")
Expand Down
1 change: 0 additions & 1 deletion tools/eslintConfigCreator.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ func CreateEslintConfig(configuration ToolConfiguration) string {

for _, patternConfiguration := range configuration.PatternsConfiguration {
rule := strings.TrimPrefix(patternConfiguration.PatternId, "ESLint8_")
fmt.Println("Rule:", rule)

const tempstring = "TEMPORARYSTRING"
rule = strings.ReplaceAll(rule, "__", tempstring)
Expand Down
9 changes: 9 additions & 0 deletions tools/eslintRunner.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ func RunEslint(repositoryToAnalyseDirectory string, eslintInstallationDirectory
eslintJsPath := filepath.Join(eslintInstallationNodeModules, ".bin", "eslint")

cmd := exec.Command(nodeBinary, eslintJsPath)

// For Eslint compatibility with version 8.
// https://eslint.org/docs/v8.x/use/configure/configuration-files-new
cmd.Env = append(cmd.Env, "ESLINT_USE_FLAT_CONFIG=true")

// Add config file from tools-configs directory
configFile := filepath.Join(".codacy", "tools-configs", "eslint.config.mjs")
cmd.Args = append(cmd.Args, "-c", configFile)

if autoFix {
cmd.Args = append(cmd.Args, "--fix")
}
Expand Down
37 changes: 25 additions & 12 deletions tools/pmdRunner.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,52 @@
import (
"os"
"os/exec"
"path/filepath"
"strings"
)

// RunPmd executes PMD static code analyzer with the specified options
//
// Parameters:
// - repositoryToAnalyseDirectory: The root directory of the repository to analyze
// - pmdBinary: Path to the PMD executable
// - pathsToCheck: List of specific paths to analyze, if empty analyzes whole repository
// - outputFile: Path where analysis results should be written
// - outputFormat: Format for the output (e.g. "sarif")
// - rulesetFile: Path to custom ruleset XML file, if empty uses default ruleset
//
// Returns:
// - error: nil if analysis succeeds or violations found, error otherwise
func RunPmd(repositoryToAnalyseDirectory string, pmdBinary string, pathsToCheck []string, outputFile string, outputFormat string, rulesetFile string) error {
cmdArgs := []string{"pmd"}
cmd := exec.Command(pmdBinary, "pmd")

Check failure on line 23 in tools/pmdRunner.go

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

tools/pmdRunner.go#L23

Detected non-static command inside Command.

Check failure on line 23 in tools/pmdRunner.go

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

tools/pmdRunner.go#L23

OS command injection is a critical vulnerability that can lead to a full system compromise as it may allow an adversary to pass in arbitrary commands or arguments to be executed.

// Add config file from tools-configs directory if not specified
if rulesetFile == "" {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that we pass always "" is this a WIP, or suppose to be like this on the scope of this PR? I see you removed a setting witch was PMD only (which makes sense for me to be removed). So maybe we don't even want this argument if this if is just a fake?

Meaning, instead of deciding this here, assuming that we were passing some kind of default, is to generate a file with the defaults as needed?

Copy link
Contributor Author

@andrzej-janczak andrzej-janczak Apr 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not always, in test I use a specific file and In this case it's ok.

Generally, If in future we want to be able to pass smth like analyze --config xyz.file - like ovveride, then it can stay.
If not we can delete 🤷‍♂️

configFile := filepath.Join(".codacy", "tools-configs", "pmd-ruleset.xml")
cmd.Args = append(cmd.Args, "-R", configFile)
} else {
cmd.Args = append(cmd.Args, "-R", rulesetFile)
}

// Add source directories (comma-separated list for PMD)
if len(pathsToCheck) > 0 {
dirArg := strings.Join(pathsToCheck, ",")
cmdArgs = append(cmdArgs, "-d", dirArg)
cmd.Args = append(cmd.Args, "-d", dirArg)
} else {
// Fall back to whole repo if no specific paths given
cmdArgs = append(cmdArgs, "-d", repositoryToAnalyseDirectory)
}

// Add ruleset
if rulesetFile != "" {
cmdArgs = append(cmdArgs, "-R", rulesetFile)
cmd.Args = append(cmd.Args, "-d", repositoryToAnalyseDirectory)
}

// Format
if outputFormat != "" {
cmdArgs = append(cmdArgs, "-f", outputFormat)
cmd.Args = append(cmd.Args, "-f", outputFormat)
}

// Output file
if outputFile != "" {
cmdArgs = append(cmdArgs, "-r", outputFile)
cmd.Args = append(cmd.Args, "-r", outputFile)
}

cmd := exec.Command(pmdBinary, cmdArgs...)

cmd.Dir = repositoryToAnalyseDirectory
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
Expand Down
2 changes: 1 addition & 1 deletion tools/testdata/repositories/test1/expected.sarif
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"artifacts": [
{
"location": {
"uri": "testdata/repositories/test1/src/eslint.config.mjs"
"uri": "testdata/repositories/test1/src/.codacy/tools-configs/eslint.config.mjs"
}
},
{
Expand Down
5 changes: 5 additions & 0 deletions tools/trivyRunner.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,17 @@ package tools
import (
"os"
"os/exec"
"path/filepath"
)

// RunTrivy executes Trivy vulnerability scanner with the specified options
func RunTrivy(repositoryToAnalyseDirectory string, trivyBinary string, pathsToCheck []string, outputFile string, outputFormat string) error {
cmd := exec.Command(trivyBinary, "fs")

// Add config file from tools-configs directory
configFile := filepath.Join(".codacy", "tools-configs", "trivy.yaml")
cmd.Args = append(cmd.Args, "--config", configFile)

// Add format options
if outputFile != "" {
cmd.Args = append(cmd.Args, "--output", outputFile)
Expand Down
Loading