Skip to content

Commit 4ee7616

Browse files
committed
Fix golangci-lint v2 config; emit govulncheck findings as CI annotations
- Fix .golangci.yml: move G204 exclusion to linters.settings.gosec.excludes (v2 schema dropped issues.exclude-rules in favour of per-linter settings) - Remove now-redundant //nolint:gosec G204 annotations across all call sites - govulncheck: parse JSON output and emit ::warning annotations so findings appear inline in the GitHub Actions UI and PR diff view
1 parent 00e4174 commit 4ee7616

6 files changed

Lines changed: 72 additions & 29 deletions

File tree

.github/workflows/build-and-snapshot.yml

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,35 @@ jobs:
7777
- name: Run govulncheck
7878
run: |
7979
go install golang.org/x/vuln/cmd/govulncheck@latest
80-
# Exit code 3 means vulnerabilities found; we report them but only fail on
81-
# non-stdlib findings (stdlib-only issues require a Go toolchain major bump).
82-
govulncheck -json . 2>&1 | tee govulncheck.json || true
83-
if govulncheck . 2>&1 | grep -q "^Vulnerability"; then
84-
echo "⚠️ govulncheck found vulnerabilities — review govulncheck.json"
85-
govulncheck . 2>&1 || true
86-
fi
80+
# Run in JSON mode and emit GitHub Actions warning annotations for each finding.
81+
# Exit code 3 means vulnerabilities found; remaining findings are stdlib-only
82+
# (require Go 1.25.x) so we warn rather than fail.
83+
govulncheck -json . 2>/dev/null | python3 -c "
84+
import sys, json
85+
for line in sys.stdin:
86+
line = line.strip()
87+
if not line:
88+
continue
89+
try:
90+
obj = json.loads(line)
91+
except json.JSONDecodeError:
92+
continue
93+
finding = obj.get('finding')
94+
if not finding:
95+
continue
96+
osv_id = finding.get('osv', '')
97+
summary = finding.get('summary', osv_id)
98+
traces = finding.get('trace', [])
99+
loc = ''
100+
if traces:
101+
frame = traces[0]
102+
pos = frame.get('position', {})
103+
fname = pos.get('filename', '')
104+
line_no = pos.get('line', '')
105+
if fname:
106+
loc = f'file={fname},line={line_no},'
107+
print(f'::warning {loc}title=govulncheck [{osv_id}]::{summary}')
108+
" || true
87109
88110
- name: Lint and format Go files
89111
run: ./scripts/lint-go.sh ci

.github/workflows/pr-validation.yml

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,35 @@ jobs:
4949
- name: Run govulncheck
5050
run: |
5151
go install golang.org/x/vuln/cmd/govulncheck@latest
52-
# Exit code 3 means vulnerabilities found; we report them but only fail on
53-
# non-stdlib findings (stdlib-only issues require a Go toolchain major bump).
54-
govulncheck -json . 2>&1 | tee govulncheck.json || true
55-
if govulncheck . 2>&1 | grep -q "^Vulnerability"; then
56-
echo "⚠️ govulncheck found vulnerabilities — review govulncheck.json"
57-
govulncheck . 2>&1 || true
58-
fi
52+
# Run in JSON mode and emit GitHub Actions warning annotations for each finding.
53+
# Exit code 3 means vulnerabilities found; remaining findings are stdlib-only
54+
# (require Go 1.25.x) so we warn rather than fail.
55+
govulncheck -json . 2>/dev/null | python3 -c "
56+
import sys, json
57+
for line in sys.stdin:
58+
line = line.strip()
59+
if not line:
60+
continue
61+
try:
62+
obj = json.loads(line)
63+
except json.JSONDecodeError:
64+
continue
65+
finding = obj.get('finding')
66+
if not finding:
67+
continue
68+
osv_id = finding.get('osv', '')
69+
summary = finding.get('summary', osv_id)
70+
traces = finding.get('trace', [])
71+
loc = ''
72+
if traces:
73+
frame = traces[0]
74+
pos = frame.get('position', {})
75+
fname = pos.get('filename', '')
76+
line_no = pos.get('line', '')
77+
if fname:
78+
loc = f'file={fname},line={line_no},'
79+
print(f'::warning {loc}title=govulncheck [{osv_id}]::{summary}')
80+
" || true
5981
6082
- name: Lint Go code
6183
run: ./scripts/lint-go.sh ci

.golangci.yml

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,13 @@ linters:
4545
- gocritic
4646
- gosec # Security-focused linter (shell commands, file perms, crypto)
4747

48+
settings:
49+
gosec:
50+
# exec.Command("cf", ...) — "cf" is a hardcoded binary; only SSH/CF args vary.
51+
# exec.Command(javaPath, ...) — resolved from JAVA_HOME/PATH, not user input.
52+
excludes:
53+
- G204 # Subprocess launched with variable
54+
4855

4956
disable:
5057
# Disabled as requested
@@ -72,11 +79,3 @@ linters:
7279
- cyclop # Check cyclomatic complexity
7380
- funlen # Check function length
7481
- revive # Fast, configurable, extensible linter
75-
76-
issues:
77-
exclude-rules:
78-
# exec.Command("cf", ...) — "cf" is a hardcoded binary name; only args vary.
79-
# exec.Command(javaPath, ...) — javaPath is resolved from JAVA_HOME or PATH, not user input.
80-
# This plugin is by design a command-line wrapper that passes user args to remote tools.
81-
- linters: [gosec]
82-
text: "G204" # Subprocess launched with variable

cf_cli_java_plugin.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ func (c *JavaPlugin) checkSSHConnectivity(appName string, appInstanceIndex int)
185185
testArgs = append(testArgs, "-c", "echo ok")
186186

187187
c.logVerbosef("Checking SSH connectivity to app '%s'", appName)
188-
cmd := exec.Command("cf", testArgs...) //nolint:gosec // "cf" is a hardcoded binary; only SSH args vary
188+
cmd := exec.Command("cf", testArgs...)
189189
output, err := cmd.CombinedOutput()
190190
if err != nil {
191191
c.logVerbosef("SSH connectivity check failed: %v", err)
@@ -1143,7 +1143,7 @@ func (c *JavaPlugin) execute(_ plugin.CliConnection, args []string) (string, err
11431143

11441144
cmdArgs := append([]string{"cf"}, fullCommand...)
11451145
c.logVerbosef("Executing command: %v", cmdArgs)
1146-
cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...) //nolint:gosec // cmdArgs[0] is always "cf"; args are CF SSH arguments
1146+
cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...)
11471147
outputBytes, err := cmd.CombinedOutput()
11481148
output := strings.TrimRight(string(outputBytes), "\n")
11491149
if err != nil {

jstall.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ func (c *JavaPlugin) executeJstall(appName string, jstallArgs string, appInstanc
218218
testArgs = append(testArgs, "--app-instance-index", strconv.Itoa(appInstanceIndex))
219219
}
220220
testArgs = append(testArgs, "-c", "echo ok")
221-
testCmd := exec.Command("cf", testArgs...) //nolint:gosec // "cf" is a hardcoded binary; only SSH args vary
221+
testCmd := exec.Command("cf", testArgs...)
222222
testOutput, testErr := testCmd.CombinedOutput()
223223
if testErr != nil {
224224
outputStr := strings.TrimSpace(string(testOutput))
@@ -229,7 +229,7 @@ func (c *JavaPlugin) executeJstall(appName string, jstallArgs string, appInstanc
229229
}
230230
}
231231

232-
cmd := exec.Command(javaPath, args...) //nolint:gosec // javaPath is resolved from JAVA_HOME or PATH, not user input
232+
cmd := exec.Command(javaPath, args...)
233233
cmd.Stdout = os.Stdout
234234
cmd.Stderr = os.Stderr
235235
cmd.Stdin = os.Stdin

utils/cfutils.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,15 +105,15 @@ func readAppEnv(app string) ([]byte, error) {
105105
return nil, err
106106
}
107107

108-
env, err := exec.Command("cf", "curl", fmt.Sprintf("/v3/apps/%s/env", strings.Trim(string(guid), "\n"))).Output() //nolint:gosec // "cf" is hardcoded; GUID is from CF API output
108+
env, err := exec.Command("cf", "curl", fmt.Sprintf("/v3/apps/%s/env", strings.Trim(string(guid), "\n"))).Output()
109109
if err != nil {
110110
return nil, err
111111
}
112112
return env, nil
113113
}
114114

115115
func checkUserPathAvailability(app string, path string) (bool, error) {
116-
output, err := exec.Command("cf", "ssh", app, "-c", "[[ -d \""+path+"\" && -r \""+path+"\" && -w \""+path+"\" ]] && echo \"exists and read-writeable\"").Output() //nolint:gosec // "cf" is hardcoded; path is user-supplied --container-dir validated by CF SSH
116+
output, err := exec.Command("cf", "ssh", app, "-c", "[[ -d \""+path+"\" && -r \""+path+"\" && -w \""+path+"\" ]] && echo \"exists and read-writeable\"").Output()
117117
if err != nil {
118118
return false, err
119119
}
@@ -160,7 +160,7 @@ func CheckRequiredTools(app string) (bool, error) {
160160
if err != nil {
161161
return false, errors.New(FindReasonForAccessError(app))
162162
}
163-
output, err := exec.Command("cf", "curl", "/v3/apps/"+strings.TrimSuffix(string(guid), "\n")+"/ssh_enabled").Output() //nolint:gosec // "cf" is hardcoded; GUID is from CF API output
163+
output, err := exec.Command("cf", "curl", "/v3/apps/"+strings.TrimSuffix(string(guid), "\n")+"/ssh_enabled").Output()
164164
if err != nil {
165165
return false, err
166166
}

0 commit comments

Comments
 (0)