fix(mcp): CORS-aware scaffold, cors.wildcard rule, server-not-appended FP; v1.1.2
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
package rules
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// The web/mw CORS convention: mw.CORS uses exact-origin matching and rejects "*"
|
||||
// at construction (panic). Passing "*" is the trap this rule catches before runtime —
|
||||
// allow-all is done with mw.CORSAllowAll(), gated by env in application code.
|
||||
func init() {
|
||||
registered = append(registered,
|
||||
Rule{
|
||||
ID: "cors.wildcard-noop",
|
||||
Severity: SeverityError,
|
||||
Module: "web",
|
||||
Check: checkCORSWildcard,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// checkCORSWildcard flags any call to <pkg>.CORS(...) whose arguments contain a
|
||||
// "*" string literal — which mw.CORS rejects (panics) at boot.
|
||||
func checkCORSWildcard(c *Context) []Finding {
|
||||
var hits []Finding
|
||||
ast.Inspect(c.File, func(n ast.Node) bool {
|
||||
call, ok := n.(*ast.CallExpr)
|
||||
if !ok || !strings.HasSuffix(exprName(call.Fun), ".CORS") {
|
||||
return true
|
||||
}
|
||||
for _, arg := range call.Args {
|
||||
ast.Inspect(arg, func(m ast.Node) bool {
|
||||
lit, ok := m.(*ast.BasicLit)
|
||||
if ok && lit.Kind == token.STRING && strings.Trim(lit.Value, `"`) == "*" {
|
||||
hits = append(hits, Finding{
|
||||
Message: `mw.CORS with "*" panics at construction — "*" matches no real origin (exact-match only)`,
|
||||
Hint: "Use mw.CORSAllowAll() for local development, or list explicit origins.",
|
||||
Line: c.Fset.Position(call.Pos()).Line,
|
||||
})
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
return true
|
||||
})
|
||||
return hits
|
||||
}
|
||||
Reference in New Issue
Block a user