Skip to content

Conversation

@michaelm-jf
Copy link

@michaelm-jf michaelm-jf commented Nov 25, 2025

  • The pull request is targeting the dev branch.
  • The code has been validated to compile successfully by running go vet ./....
  • The code has been formatted properly using go fmt ./....
  • All static analysis checks passed.
  • All tests have passed. If this feature is not already covered by the tests, new tests have been added.
  • Updated the Contributing page / ReadMe page / CI Workflow files if needed.
  • All changes are detailed at the description. if not already covered at JFrog Documentation, new documentation have been added.

Depends on:

  • Updated the gradle-dep-tree plugin, which has a new "use included builds" param
  • Added support to configure the above param
  • Updated the 'DepTreeNode' json structure to match the plugin output
  • Added a UT that uses the new param, and a sample gradle project that uses composite builds

# Conflicts:
#	commands/audit/auditbasicparams.go
#	commands/audit/auditparams.go
#	sca/bom/buildinfo/technologies/common.go
#	sca/bom/buildinfo/technologies/java/gradle.go
#	sca/bom/buildinfo/technologies/java/resources/gradle-dep-tree.jar
@michaelm-jf michaelm-jf marked this pull request as ready for review November 27, 2025 11:33
@attiasas attiasas added new feature Automatically generated release notes safe to test Approve running integration tests on a pull request labels Nov 30, 2025
@github-actions github-actions bot removed the safe to test Approve running integration tests on a pull request label Nov 30, 2025
Copy link
Contributor

@attiasas attiasas left a comment

Choose a reason for hiding this comment

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

Nice work, check out my comments

  1. You should create the new flag in the flag maps and attach it to the related command (similar to other flags in the file)
  2. I released the new version of the plugin with your changes. make sure you update and run the script that the v3.2.0 will be used and the embedded plugins test will pass
  3. make sure all tests are passing

Exclusions = "exclusions"
IncludeDirs = "include-dirs"
UseWrapper = "use-wrapper"
UseIncludedBuilds = "use-included-builds"
Copy link
Contributor

Choose a reason for hiding this comment

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

make sure to define the flag and assign it to the related command (similar to other flags in the file)

Copy link
Author

Choose a reason for hiding this comment

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

Added it to the 'flagsMap'

Copy link
Contributor

Choose a reason for hiding this comment

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

should be added to commandFlags as well

Comment on lines +166 to +167
"-Dcom.jfrog.includeAllBuildFiles=true",
fmt.Sprintf("-Dcom.jfrog.includeIncludedBuilds=%t", gdt.useIncludedBuilds)}
Copy link
Contributor

Choose a reason for hiding this comment

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

There are no issue using both flags, right?

Copy link
Author

Choose a reason for hiding this comment

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

You mean 'includeAllBuildFiles' and 'includeIncludedBuilds' ? They're not exactly related, 'includeAllBuildFiles' was already present before my change. It's used for for the gradle subprojects not for gradle included builds

Comment on lines +13 to +14
Unresolved bool `json:"unresolved,omitempty"`
Configurations *[]string `json:"configurations,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a use for them here other than the logs? do we want to skip unresolved?
please make sure Xray can scan those dependencies by adding a test scan on a similar project and making sure Xray can handle those deps

Copy link
Author

Choose a reason for hiding this comment

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

'Configurations' is used to determine the dependency scope (direct, transitive, etc.). It contains values like 'compileOnly', 'testImplementaion', etc. which are in the Gradle spec.

'Unresolved' is not being used yet, I just added it to the struct in case we will want to take it into account.
I want to stress that those values are outputted by the gradle plugin but we just didn't unmarshall them into the struct

@attiasas attiasas added the safe to test Approve running integration tests on a pull request label Dec 8, 2025
@github-actions github-actions bot removed the safe to test Approve running integration tests on a pull request label Dec 8, 2025
@attiasas attiasas added the safe to test Approve running integration tests on a pull request label Dec 11, 2025
@github-actions github-actions bot removed the safe to test Approve running integration tests on a pull request label Dec 11, 2025
@attiasas attiasas added the safe to test Approve running integration tests on a pull request label Dec 15, 2025
@github-actions github-actions bot removed the safe to test Approve running integration tests on a pull request label Dec 15, 2025
Copy link
Contributor

@attiasas attiasas left a comment

Choose a reason for hiding this comment

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

Nice Work!, check out my comments and:

  1. Do we want to add this option to audit curation as well?
  2. Make sure all tests are passing

Exclusions = "exclusions"
IncludeDirs = "include-dirs"
UseWrapper = "use-wrapper"
UseIncludedBuilds = "use-included-builds"
Copy link
Contributor

Choose a reason for hiding this comment

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

should be added to commandFlags as well

// NuGet params
SolutionFilePath string
SolutionFilePath string
UseIncludedBuilds bool
Copy link
Contributor

Choose a reason for hiding this comment

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

move to be below UseWrapper

"github.com/stretchr/testify/assert"

"github.com/jfrog/jfrog-cli-core/v2/utils/tests"

Copy link
Contributor

Choose a reason for hiding this comment

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

remove unrelated change

Comment on lines +1 to +3
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
Copy link
Contributor

Choose a reason for hiding this comment

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

unrelated change?

Comment on lines +2 to +3
artifactory_user=admin
artifactory_password=password
Copy link
Contributor

Choose a reason for hiding this comment

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

do we need it here? remove if possiable, add ignore for security scan if needed

Comment on lines +2 to +3
artifactory_user=admin
artifactory_password=password
Copy link
Contributor

Choose a reason for hiding this comment

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

do we need it here? remove if possiable, add ignore for security scan if needed

Comment on lines +2 to +3
artifactory_user=admin
artifactory_password=password
Copy link
Contributor

Choose a reason for hiding this comment

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

do we need it here? remove if possiable, add ignore for security scan if needed

@github-actions
Copy link

🚨 Frogbot scanned this pull request and found the below:

📗 Scan Summary

  • Frogbot scanned for vulnerabilities and found 2 issues
Scan Category Status Security Issues
Software Composition Analysis ℹ️ Not Scanned -
Contextual Analysis ℹ️ Not Scanned -
Static Application Security Testing (SAST) ✅ Done
2 Issues Found 1 Medium
1 Low
Secrets ✅ Done -
Infrastructure as Code (IaC) ✅ Done Not Found

@github-actions
Copy link

os.ReadFile(strings.TrimSpace(path))

at sca/bom/buildinfo/technologies/java/deptreemanager.go (line 109)

🎯 Static Application Security Testing (SAST) Vulnerability

Severity Finding
medium
Medium
Untrusted stored input used in file paths, allowing access to unintended files.
Full description

Vulnerability Details

Rule ID: go-stored-path-traversal

Overview

Stored Path Traversal is a type of vulnerability that arises when user-controlled
input, such as file names or paths, is stored by the application and later used
without proper validation or sanitization to perform file operations. This can
allow an attacker to traverse directories and access or overwrite sensitive files
on the filesystem, potentially compromising the security and integrity of the
application or system.

Vulnerable example

func serveFile(w http.ResponseWriter, r *http.Request) {
    row := db.QueryRow("SELECT file_path FROM files WHERE id = 12")
    row.Scan(&filePath)
    http.ServeFile(w, r, filePath)
}

In this example, the serveFile function serves a file based on the file query
parameter provided by the user. However, in a real-world scenario, the filePath
variable might be retrieved from a stored source, such as a database or configuration
file, instead of being directly obtained from the request URL. The vulnerability
arises if the stored filePath is not properly validated or sanitized before being
used to serve files. Attackers could manipulate the stored filePath to perform
directory traversal attacks, potentially accessing sensitive files outside the
intended directory structure.

Remediation

To mitigate stored path traversal vulnerabilities, it is essential to validate
and sanitize user-controlled input before using it to construct file paths or
perform file operations. In this example, we can validate the file name to ensure
it does not contain directory traversal sequences before serving the file.

func serveFile(w http.ResponseWriter, r *http.Request) {
    row := db.QueryRow("SELECT file_path FROM files WHERE id = ?", r.URL.Query().Get("id"))
    row.Scan(&filePath)
+    // Validate file path to prevent directory traversal
+    if strings.Contains(filePath, "..") {
+        http.Error(w, "Invalid file path", http.StatusBadRequest)
+        return
+    }
    http.ServeFile(w, r, filePath)
}
Code Flows
Vulnerable data flow analysis result

↘️ os.ReadFile(mavenDepTreePath) (at sca/bom/buildinfo/technologies/java/mvn.go line 148)

↘️ mavenDepTreeOutput (at sca/bom/buildinfo/technologies/java/mvn.go line 148)

↘️ mavenDepTreeOutput (at sca/bom/buildinfo/technologies/java/mvn.go line 152)

↘️ string(mavenDepTreeOutput) (at sca/bom/buildinfo/technologies/java/mvn.go line 152)

↘️ return string(mavenDepTreeOutput), nil (at sca/bom/buildinfo/technologies/java/mvn.go line 152)

↘️ (string, error) (at sca/bom/buildinfo/technologies/java/mvn.go line 138)

↘️ mdt.runTreeCmd(depTreeExecDir) (at sca/bom/buildinfo/technologies/java/mvn.go line 133)

↘️ return mdt.runTreeCmd(depTreeExecDir) (at sca/bom/buildinfo/technologies/java/mvn.go line 133)

↘️ (string, error) (at sca/bom/buildinfo/technologies/java/mvn.go line 131)

↘️ mdt.execMavenDepTree(depTreeExecDir) (at sca/bom/buildinfo/technologies/java/mvn.go line 103)

↘️ depTreeOutput (at sca/bom/buildinfo/technologies/java/mvn.go line 103)

↘️ `func (mdt *MavenDepTreeManager) RunMavenDepTree() (depTreeOutput string, clearMavenDepTreeRun func() error, err error) {
// depTreeExecDir is a temp directory for all the files that are required for the maven-dep-tree run
depTreeExecDir, clearMavenDepTreeRun, err := mdt.CreateTempDirWithSettingsXmlIfNeeded()
if err != nil {
return
}
if err = mdt.installMavenDepTreePlugin(depTreeExecDir); err != nil {
return
}

depTreeOutput, err = mdt.execMavenDepTree(depTreeExecDir)
if err != nil {
	return
}
return

}` (at sca/bom/buildinfo/technologies/java/mvn.go line 93)

↘️ (depTreeOutput string, clearMavenDepTreeRun func() error, err error) (at sca/bom/buildinfo/technologies/java/mvn.go line 93)

↘️ manager.RunMavenDepTree() (at sca/bom/buildinfo/technologies/java/mvn.go line 77)

↘️ outputFilePaths (at sca/bom/buildinfo/technologies/java/mvn.go line 77)

↘️ outputFilePaths (at sca/bom/buildinfo/technologies/java/mvn.go line 87)

↘️ outputFilePaths (at sca/bom/buildinfo/technologies/java/deptreemanager.go line 56)

↘️ outputFilePaths (at sca/bom/buildinfo/technologies/java/deptreemanager.go line 57)

↘️ jsonFilePaths (at sca/bom/buildinfo/technologies/java/deptreemanager.go line 95)

↘️ jsonFilePaths (at sca/bom/buildinfo/technologies/java/deptreemanager.go line 96)

↘️ strings.TrimSpace(jsonFilePaths) (at sca/bom/buildinfo/technologies/java/deptreemanager.go line 96)

↘️ strings.Split(strings.TrimSpace(jsonFilePaths), "\n") (at sca/bom/buildinfo/technologies/java/deptreemanager.go line 96)

↘️ outputFilePaths (at sca/bom/buildinfo/technologies/java/deptreemanager.go line 98)

↘️ path (at sca/bom/buildinfo/technologies/java/deptreemanager.go line 98)

↘️ path (at sca/bom/buildinfo/technologies/java/deptreemanager.go line 99)

↘️ path (at sca/bom/buildinfo/technologies/java/deptreemanager.go line 108)

↘️ path (at sca/bom/buildinfo/technologies/java/deptreemanager.go line 109)

↘️ strings.TrimSpace(path) (at sca/bom/buildinfo/technologies/java/deptreemanager.go line 109)

↘️ os.ReadFile(strings.TrimSpace(path)) (at sca/bom/buildinfo/technologies/java/deptreemanager.go line 109)

Vulnerable data flow analysis result

↘️ os.ReadFile(outputFilePath) (at sca/bom/buildinfo/technologies/java/gradle.go line 181)

↘️ outputFileContent (at sca/bom/buildinfo/technologies/java/gradle.go line 181)

↘️ `func (gdt *gradleDepTreeManager) execGradleDepTree(depTreeDir string) (outputFileContent []byte, err error) {

gradleExecPath, err := build.GetGradleExecPath(gdt.useWrapper)
if err != nil {
	err = errorutils.CheckError(err)
	return
}
outputFilePath := filepath.Join(depTreeDir, gradleDepTreeOutputFile)
tasks := []string{
	"clean",
	"generateDepTrees", "-I", filepath.Join(depTreeDir, gradleDepTreeInitFile),
	"-q",
	gradleNoCacheFlag,
	fmt.Sprintf("-Dcom.jfrog.depsTreeOutputFile=%s", outputFilePath),
	"-Dcom.jfrog.includeAllBuildFiles=true",
	fmt.Sprintf("-Dcom.jfrog.includeIncludedBuilds=%t", gdt.useIncludedBuilds)}

// Add curation audit mode for pass-through functionality if this is a curation command
if gdt.isCurationCmd {
	tasks = append(tasks, "-Dcom.jfrog.curationAuditMode=true")
}

log.Info("Running gradle deps tree command:", gradleExecPath, strings.Join(tasks, " "))
if output, err := exec.Command(gradleExecPath, tasks...).CombinedOutput(); err != nil {
	return nil, errorutils.CheckErrorf("error running gradle-dep-tree: %s\n%s", err.Error(), string(output))
}
defer func() {
	err = errors.Join(err, errorutils.CheckError(os.Remove(outputFilePath)))
}()
outputFileContent, err = os.ReadFile(outputFilePath)
err = errorutils.CheckError(err)
return

}` (at sca/bom/buildinfo/technologies/java/gradle.go line 152)

↘️ (outputFileContent []byte, err error) (at sca/bom/buildinfo/technologies/java/gradle.go line 152)

↘️ gdt.execGradleDepTree(depTreeDir) (at sca/bom/buildinfo/technologies/java/gradle.go line 93)

↘️ output (at sca/bom/buildinfo/technologies/java/gradle.go line 93)

↘️ output (at sca/bom/buildinfo/technologies/java/gradle.go line 97)

↘️ string(output) (at sca/bom/buildinfo/technologies/java/gradle.go line 97)

↘️ return string(output), nil (at sca/bom/buildinfo/technologies/java/gradle.go line 97)

↘️ (string, error) (at sca/bom/buildinfo/technologies/java/gradle.go line 76)

↘️ manager.runGradleDepTree() (at sca/bom/buildinfo/technologies/java/deptreemanager_test.go line 57)

↘️ outputFileContent (at sca/bom/buildinfo/technologies/java/deptreemanager_test.go line 57)

↘️ outputFileContent (at sca/bom/buildinfo/technologies/java/deptreemanager_test.go line 59)

↘️ outputFilePaths (at sca/bom/buildinfo/technologies/java/deptreemanager.go line 56)

↘️ outputFilePaths (at sca/bom/buildinfo/technologies/java/deptreemanager.go line 57)

↘️ jsonFilePaths (at sca/bom/buildinfo/technologies/java/deptreemanager.go line 95)

↘️ jsonFilePaths (at sca/bom/buildinfo/technologies/java/deptreemanager.go line 96)

↘️ strings.TrimSpace(jsonFilePaths) (at sca/bom/buildinfo/technologies/java/deptreemanager.go line 96)

↘️ strings.Split(strings.TrimSpace(jsonFilePaths), "\n") (at sca/bom/buildinfo/technologies/java/deptreemanager.go line 96)

↘️ outputFilePaths (at sca/bom/buildinfo/technologies/java/deptreemanager.go line 98)

↘️ path (at sca/bom/buildinfo/technologies/java/deptreemanager.go line 98)

↘️ path (at sca/bom/buildinfo/technologies/java/deptreemanager.go line 99)

↘️ path (at sca/bom/buildinfo/technologies/java/deptreemanager.go line 108)

↘️ path (at sca/bom/buildinfo/technologies/java/deptreemanager.go line 109)

↘️ strings.TrimSpace(path) (at sca/bom/buildinfo/technologies/java/deptreemanager.go line 109)

↘️ os.ReadFile(strings.TrimSpace(path)) (at sca/bom/buildinfo/technologies/java/deptreemanager.go line 109)




@github-actions
Copy link

password

at cli/docs/flags.go (line 244)

🎯 Static Application Security Testing (SAST) Vulnerability

Severity Finding
low
Low
Credentials for restricted resources included directly in source code
Full description

Vulnerability Details

Rule ID: go-hardcoded-credentials

Overview

Hardcoded credentials are usernames, passwords, API keys, or other secrets
embedded directly in source code. This practice, identified by CWE-798, is
highly insecure because it makes it easy for anyone with access to the code to
discover and misuse the credentials. If the code is publicly released, shared,
or leaked, the credentials will be exposed to unauthorized parties.

Vulnerable example

In this example, the database username and password for the frog pond are
hardcoded directly in the source code as string literals. This is a major
security risk, as anyone who can read this file can steal the credentials and
gain unauthorized access to the database.

package main

import (
	"database/sql"
	"fmt"
	"log"

	_ "[github.com/go-sql-driver/mysql](https://github.com/go-sql-driver/mysql)"
)

func main() {
	// VULNERABLE: Hardcoded database credentials for the frog pond.
	frogUser := "pond_admin"
	frogPassword := "LeapFlog123!"
	pondName := "lilypad_db"

	connStr := fmt.Sprintf("%s:%s@tcp(127.0.0.1:3306)/%s",
		frogUser, frogPassword, pondName)

	lilypadDB, err := sql.Open("mysql", connStr)
	if err != nil {
		log.Fatalf("Error opening database: %v", err)
	}
	defer lilypadDB.Close()

	err = lilypadDB.Ping()
	if err != nil {
		log.Fatalf("Error pinging database: %v", err)
	}
	fmt.Println("Successfully connected to the frog pond.")
}

Remediation

The remediated code retrieves the database credentials from environment
variables instead of hardcoding them. This is a much more secure approach, as
it separates the secrets from the source code. This allows credentials to be
managed securely by deployment systems and rotated without changing the code.

package main

import (
	"database/sql"
	"fmt"
	"log"
	"os"

	_ "[github.com/go-sql-driver/mysql](https://github.com/go-sql-driver/mysql)"
)

func main() {
	// SECURE: Retrieve credentials from environment variables.
	frogUser := os.Getenv("FROG_DB_USER")
	frogPassword := os.Getenv("FROG_DB_PASS")
	pondName := os.Getenv("FROG_DB_NAME")

	if frogUser == "" || frogPassword == "" || pondName == "" {
		log.Fatal("DB credentials are not set in environment variables.")
	}

	connStr := fmt.Sprintf("%s:%s@tcp(127.0.0.1:3306)/%s",
		frogUser, frogPassword, pondName)

	lilypadDB, err := sql.Open("mysql", connStr)
	if err != nil {
		log.Fatalf("Error opening database: %v", err)
	}
	defer lilypadDB.Close()

	err = lilypadDB.Ping()
	if err != nil {
		log.Fatalf("Error pinging database: %v", err)
	}
	fmt.Println("Successfully connected to the frog pond.")
}
Code Flows
Vulnerable data flow analysis result

↘️ "password" (at cli/docs/flags.go line 80)

↘️ password (at cli/docs/flags.go line 80)

↘️ password (at cli/docs/flags.go line 244)




Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

new feature Automatically generated release notes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants