Skip to content

Commit 6a65b72

Browse files
authored
Merge branch 'main' into fix/lfp-empty-non-http-urls
2 parents e0e5696 + 0727106 commit 6a65b72

3 files changed

Lines changed: 72 additions & 0 deletions

File tree

pkg/parser/pomxml_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package parser
22

33
import (
4+
"strings"
45
"testing"
56

67
"github.com/stretchr/testify/assert"
@@ -13,9 +14,31 @@ var deps = []string{
1314
"org.opentest4j:opentest4j", // Transitive
1415
}
1516

17+
// skipIfMavenRegistryUnavailable skips a test that depends on resolving
18+
// dependencies live from Maven Central when the registry is unreachable or
19+
// rate-limits the request (HTTP 429). CI runners share egress IPs that are
20+
// frequently rate-limited by Maven Central - an external, non-deterministic
21+
// condition unrelated to the code under test. Any other error still fails the
22+
// test so genuine parsing/resolution regressions are caught.
23+
func skipIfMavenRegistryUnavailable(t *testing.T, err error) {
24+
t.Helper()
25+
26+
msg := err.Error()
27+
for _, signal := range []string{
28+
"failed to fetch Maven project", // resolver could not retrieve a POM
29+
"failed to load parent from remote", // remote parent fetch failed
30+
"Maven registry query", // wraps non-200 (e.g. 429) and transport errors
31+
} {
32+
if strings.Contains(msg, signal) {
33+
t.Skipf("skipping: Maven registry unavailable or rate-limited: %v", err)
34+
}
35+
}
36+
}
37+
1638
func Test_MavenPomXmlParser_Simple(t *testing.T) {
1739
manifest, err := parseMavenPomXmlFile("./fixtures/java/pom.xml", &ParserConfig{})
1840
if err != nil {
41+
skipIfMavenRegistryUnavailable(t, err)
1942
t.Fatal(err)
2043
}
2144

@@ -30,6 +53,7 @@ func Test_MavenPomXmlParser_ChildParentRelation(t *testing.T) {
3053
// <relativePath>../parent/pom.xml</relativePath>
3154
manifest, err := parseMavenPomXmlFile("./fixtures/java/child/pom.xml", &ParserConfig{})
3255
if err != nil {
56+
skipIfMavenRegistryUnavailable(t, err)
3357
t.Fatal(err)
3458
}
3559

@@ -42,6 +66,7 @@ func Test_MavenPomXmlParser_ChildParentRelation(t *testing.T) {
4266
func Test_MavenPomXmlParser_RemoteParent(t *testing.T) {
4367
manifest, err := parseMavenPomXmlFile("./fixtures/java/remote/pom.xml", &ParserConfig{})
4468
if err != nil {
69+
skipIfMavenRegistryUnavailable(t, err)
4570
t.Fatal(err)
4671
}
4772

pkg/readers/dir_reader_test.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,53 @@ package readers
22

33
import (
44
"errors"
5+
"os"
6+
"path/filepath"
7+
"strings"
58
"testing"
69

710
"github.com/stretchr/testify/assert"
811

912
"github.com/safedep/vet/pkg/models"
13+
"github.com/safedep/vet/pkg/parser"
1014
)
1115

16+
// mavenResolutionAvailable resolves a fixture pom.xml through the same parser
17+
// the directory reader uses, and reports whether Maven dependency resolution
18+
// is currently working. It returns false when Maven Central is unreachable or
19+
// rate-limiting (HTTP 429) - an external, non-deterministic condition (CI
20+
// runners share egress IPs frequently throttled by Maven Central) that should
21+
// not turn the build red. Cases that enumerate a pom.xml are skipped in that
22+
// situation. Doing a full resolution (rather than a single HTTP probe) makes
23+
// the signal representative of what the test cases actually do, so we don't run
24+
// the cases only to have the resolution burst fail partway.
25+
func mavenResolutionAvailable() bool {
26+
const pom = "./fixtures/java-multi/pom.xml"
27+
28+
p, err := parser.FindParser(pom, "pom.xml")
29+
if err != nil {
30+
return true // cannot probe; let the test run and report the real error
31+
}
32+
33+
if _, err := p.Parse(pom); err != nil {
34+
msg := err.Error()
35+
if strings.Contains(msg, "failed to fetch Maven project") ||
36+
strings.Contains(msg, "failed to load parent from remote") ||
37+
strings.Contains(msg, "Maven registry query") {
38+
return false
39+
}
40+
}
41+
42+
return true
43+
}
44+
45+
// dirContainsPomXML reports whether the fixture directory has a pom.xml, which
46+
// means enumerating it requires live Maven dependency resolution.
47+
func dirContainsPomXML(dir string) bool {
48+
_, err := os.Stat(filepath.Join(dir, "pom.xml"))
49+
return err == nil
50+
}
51+
1252
func TestNewDirectoryReader(t *testing.T) {
1353
cases := []struct {
1454
name string
@@ -131,8 +171,14 @@ func TestDirectoryReaderEnumPackages(t *testing.T) {
131171
},
132172
}
133173

174+
mavenOK := mavenResolutionAvailable()
175+
134176
for _, test := range cases {
135177
t.Run(test.name, func(t *testing.T) {
178+
if !mavenOK && dirContainsPomXML(test.path) {
179+
t.Skipf("skipping: Maven Central unavailable or rate-limited; %s requires live pom.xml resolution", test.path)
180+
}
181+
136182
reader, _ := NewDirectoryReader(DirectoryReaderConfig{
137183
Path: test.path,
138184
Exclusions: test.exclusions,

test/scenarios/scenario-11-code-csvreport.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ PyPI,*,*,flask,1.0.4,cli-filter,flask,flask,PYSEC-2023-62,CVE-2023-30861,,,1,$E2
3535
PyPI,*,*,langchain,0.2.1,cli-filter,langchain,langchain,GHSA-3hjh-jh2h-vrg6,CVE-2024-2965,MEDIUM,Denial of service in langchain-community,0,
3636
PyPI,*,*,langchain,0.2.1,cli-filter,langchain,langchain,PYSEC-2024-118,CVE-2024-2965,MEDIUM,,0,
3737
PyPI,*,*,langchain,0.2.1,cli-filter,langchain,langchain,GHSA-3644-q5cj-c5c7,CVE-2026-45134,HIGH,LangSmith SDK: Public prompt pull deserializes untrusted manifests without trust boundary warning,0,
38+
PyPI,*,*,langchain,0.2.1,cli-filter,langchain,langchain,GHSA-gr75-jv2w-4656,,MEDIUM,LangChain: Path traversal and sandbox escape in LangChain file-search middleware and loaders,0,
3839
EOL
3940

4041
# Process CSV files to exclude environment-dependent fields

0 commit comments

Comments
 (0)