Files
wehub-resource-sync a06f331eb8
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:33:42 +08:00

140 lines
5.3 KiB
Go

package astquery
// Cross-language hygiene rules. Lower severity than SAST proper —
// these are debugging-print / dev-debugger leftovers / dead asserts.
// Category is CategoryHygiene so an agent can run `analyze sast` and
// keep them out of the security bundle when they don't want noise.
func init() {
registerHygieneJSConsoleLog()
registerHygieneJSDebugger()
registerHygienePyPrint()
registerHygienePyPdbSetTrace()
registerHygienePyBreakpoint()
registerHygieneRubyByebug()
registerHygieneFmtPrintln()
registerHygienePhpVarDump()
registerHygieneJavaStackTrace()
}
func registerHygieneJSConsoleLog() {
pat := `((call_expression
function: (member_expression object: (identifier) @obj property: (property_identifier) @fn)) @match
(#eq? @obj "console") (#match? @fn "^(log|debug|info)$"))`
mustRegisterSAST(sastRule{
Name: "hygiene-js-console-log",
Description: "`console.log(...)` / `console.debug` / `console.info` in non-test source — leaks debug payloads to production. Use a structured logger.",
Severity: "info",
Category: CategoryHygiene,
Tags: []string{"hygiene", "debug-leftover"},
Pat: map[string]string{"javascript": pat, "typescript": pat},
})
}
func registerHygieneJSDebugger() {
pat := `(debugger_statement) @match`
mustRegisterSAST(sastRule{
Name: "hygiene-js-debugger",
Description: "`debugger;` statement in non-test source — pauses execution when devtools are open. Never ship.",
Severity: "warning",
Category: CategoryHygiene,
Tags: []string{"hygiene", "debug-leftover"},
Pat: map[string]string{"javascript": pat, "typescript": pat},
})
}
func registerHygienePyPrint() {
mustRegisterSAST(sastRule{
Name: "hygiene-py-print",
Description: "`print(...)` in non-test source — debug leftover. Use a logger.",
Severity: "info",
Category: CategoryHygiene,
Tags: []string{"hygiene", "debug-leftover"},
Pat: map[string]string{
"python": `((call function: (identifier) @fn) @match (#eq? @fn "print"))`,
},
})
}
func registerHygienePyPdbSetTrace() {
mustRegisterSAST(sastRule{
Name: "hygiene-py-pdb-set-trace",
Description: "`pdb.set_trace()` / `ipdb.set_trace()` / `pudb.set_trace()` — debugger entrypoint left in source. Crashes production on hit.",
Severity: "error",
Category: CategoryHygiene,
Tags: []string{"hygiene", "debug-leftover"},
Pat: map[string]string{
"python": `((call function: (attribute object: (identifier) @mod attribute: (identifier) @fn)) @match
(#match? @mod "^(pdb|ipdb|pudb|pdbpp)$") (#eq? @fn "set_trace"))`,
},
})
}
func registerHygienePyBreakpoint() {
mustRegisterSAST(sastRule{
Name: "hygiene-py-breakpoint",
Description: "`breakpoint()` — the 3.7+ shortcut for `pdb.set_trace()`. Crashes production on hit unless `PYTHONBREAKPOINT=0`.",
Severity: "warning",
Category: CategoryHygiene,
Tags: []string{"hygiene", "debug-leftover"},
Pat: map[string]string{
"python": `((call function: (identifier) @fn) @match (#eq? @fn "breakpoint"))`,
},
})
}
func registerHygieneRubyByebug() {
mustRegisterSAST(sastRule{
Name: "hygiene-ruby-byebug",
Description: "`byebug` / `binding.pry` — debugger entrypoint. Crashes production on hit (or worse, leaks an interactive shell over stderr).",
Severity: "error",
Category: CategoryHygiene,
Tags: []string{"hygiene", "debug-leftover"},
Pat: map[string]string{
"ruby": `((call method: (identifier) @fn) @match (#match? @fn "^(byebug|pry)$"))
((call receiver: (call method: (identifier) @b) method: (identifier) @fn) @match
(#eq? @b "binding") (#match? @fn "^(pry|irb)$"))`,
},
})
}
func registerHygieneFmtPrintln() {
mustRegisterSAST(sastRule{
Name: "hygiene-go-fmt-println",
Description: "`fmt.Println(...)` / `fmt.Printf(...)` in non-test Go source — debug leftover. Use a structured logger (`slog`, `zap`).",
Severity: "info",
Category: CategoryHygiene,
Tags: []string{"hygiene", "debug-leftover"},
Pat: map[string]string{
"go": `((call_expression function: (selector_expression operand: (identifier) @pkg field: (field_identifier) @fn)) @match
(#eq? @pkg "fmt") (#match? @fn "^(Println|Printf|Print)$"))`,
},
})
}
func registerHygienePhpVarDump() {
mustRegisterSAST(sastRule{
Name: "hygiene-php-var-dump",
Description: "`var_dump($x)` / `print_r($x)` / `var_export($x)` — debug-dump functions. Leaks structure / credentials to the response in production.",
Severity: "warning",
Category: CategoryHygiene,
Tags: []string{"hygiene", "debug-leftover"},
Pat: map[string]string{
"php": `((function_call_expression function: (name) @fn) @match (#match? @fn "^(var_dump|print_r|var_export|debug_print_backtrace)$"))`,
},
})
}
func registerHygieneJavaStackTrace() {
mustRegisterSAST(sastRule{
Name: "hygiene-java-printstacktrace",
Description: "`e.printStackTrace()` in non-test Java source — writes to stderr only; production loggers miss the entry. Use a logger.",
Severity: "info",
Category: CategoryHygiene,
Tags: []string{"hygiene", "debug-leftover"},
Pat: map[string]string{
"java": `((method_invocation name: (identifier) @fn) @match (#eq? @fn "printStackTrace"))`,
},
})
}