Summary
The new hardcodedfilepath linter (#38742) is intended to skip format-template strings — ADR docs/adr/38742-...md states it "skips const-declaration sites and format-template strings." The implementation that enforces this, hasFormatVerb, is an incomplete substring check, so several real format templates that look path-like slip through and are falsely reported as hard-coded paths to extract.
Evidence — pkg/linters/hardcodedfilepath/hardcodedfilepath.go:88-93
func hasFormatVerb(val string) bool {
return strings.ContainsAny(val, "%") &&
(strings.Contains(val, "%s") || strings.Contains(val, "%d") ||
strings.Contains(val, "%v") || strings.Contains(val, "%q") ||
strings.Contains(val, "%w") || strings.Contains(val, "%f"))
}
Two gaps:
- Flag/width/precision verbs evade detection. The check looks for the literal substrings
%s/%d/etc., so a verb with a flag, width, or precision does not match:
"/tmp/run-%05d/out" — strings.Contains("...%05d...", "%d") is false ⇒ not treated as a template ⇒ flagged (prefix /tmp/, len ≥ 8).
"/var/log/%-10s.log", "/home/%8.2f", "/etc/%+d.conf" — same failure.
- Nine verb letters are omitted entirely:
%x %X %t %c %b %o %e %E %g %G %p %U. e.g. "/tmp/cache-%x/blob" (hash hex), "/var/run/%p.sock" are templates but get flagged.
Both gaps cause false positives: a fmt.Sprintf/fmt.Fprintf template argument is reported as a literal path that should become a named constant, which is nonsensical (you cannot const a template that contains runtime values).
Impact
- The linter is actively run by automation (e.g. the lint-monster "Extract hard-coded file paths to constants (120 instances)" issues), so FP noise lands in real triage queues.
- Directly contradicts the ADR's stated design that format-template strings are skipped.
- No current production violation matches the regex today (latent), so this is a safe, pre-emptive precision fix before the linter is enforced in CI.
Recommendation
Replace the substring heuristic with a verb-aware scan that recognizes the standard fmt verb grammar %[flags][width][.precision]<verb-letter> while ignoring escaped %%. A compiled package-level regexp is the smallest change:
// matches a real fmt verb: %, optional flags/width/precision, then a verb letter.
var fmtVerbRe = regexp.MustCompile(`%[-+# 0]*[0-9]*(?:\.[0-9]+)?[vTtbcdoqxXUeEfFgGsp]`)
func hasFormatVerb(val string) bool {
// strip escaped percent signs so "100%%done" is not seen as a verb
return fmtVerbRe.MatchString(strings.ReplaceAll(val, "%%", ""))
}
(Compile the regexp once at package level so it does not trip the sibling regexpcompileinfunction linter.) Add testdata cases: /tmp/run-%05d/out, /var/log/%-10s.log, /tmp/cache-%x/blob, and a true positive like /tmp/gh-aw/agent plus a literal-percent path /tmp/100%%/x (should still flag).
Validation checklist
Effort: Small — single function + testdata.
References
Generated by 🤖 Sergo - Serena Go Expert · 290.8 AIC · ⌖ 12.6 AIC · ⊞ 6.3K · ◷
Summary
The new
hardcodedfilepathlinter (#38742) is intended to skip format-template strings — ADRdocs/adr/38742-...mdstates it "skips const-declaration sites and format-template strings." The implementation that enforces this,hasFormatVerb, is an incomplete substring check, so several real format templates that look path-like slip through and are falsely reported as hard-coded paths to extract.Evidence —
pkg/linters/hardcodedfilepath/hardcodedfilepath.go:88-93Two gaps:
%s/%d/etc., so a verb with a flag, width, or precision does not match:"/tmp/run-%05d/out"—strings.Contains("...%05d...", "%d")is false ⇒ not treated as a template ⇒ flagged (prefix/tmp/, len ≥ 8)."/var/log/%-10s.log","/home/%8.2f","/etc/%+d.conf"— same failure.%x %X %t %c %b %o %e %E %g %G %p %U. e.g."/tmp/cache-%x/blob"(hash hex),"/var/run/%p.sock"are templates but get flagged.Both gaps cause false positives: a
fmt.Sprintf/fmt.Fprintftemplate argument is reported as a literal path that should become a named constant, which is nonsensical (you cannot const a template that contains runtime values).Impact
Recommendation
Replace the substring heuristic with a verb-aware scan that recognizes the standard
fmtverb grammar%[flags][width][.precision]<verb-letter>while ignoring escaped%%. A compiled package-level regexp is the smallest change:(Compile the regexp once at package level so it does not trip the sibling
regexpcompileinfunctionlinter.) Add testdata cases:/tmp/run-%05d/out,/var/log/%-10s.log,/tmp/cache-%x/blob, and a true positive like/tmp/gh-aw/agentplus a literal-percent path/tmp/100%%/x(should still flag).Validation checklist
%x/%t/%ctemplates are NOT reported.%%-only literals still reported (not treated as a template).go test ./pkg/linters/hardcodedfilepath/...passes.Effort: Small — single function + testdata.
References