package analyzers import ( "go/ast" "go/token" "strings" "golang.org/x/tools/go/analysis" ) // HIPAACompletenessAnalyzer flags any switch or if-else statement that checks // compliance_mode == "hipaa" but doesn't verify all six hard-required fields. // This prevents partial HIPAA enforcement from silently passing. var HIPAACompletenessAnalyzer = &analysis.Analyzer{ Name: "hippacomplete", Doc: "flags incomplete HIPAA compliance mode checks", Run: runHIPAACompleteness, } // hipaaRequiredFields are the six fields that must be checked in HIPAA mode var hipaaRequiredFields = []string{ "ConfigHash", "SandboxSeccomp", "SandboxNoNewPrivs", "SandboxNetworkMode", "MaxWorkers", "ComplianceMode", } func runHIPAACompleteness(pass *analysis.Pass) (interface{}, error) { for _, file := range pass.Files { ast.Inspect(file, func(n ast.Node) bool { // Look for if statements ifStmt, ok := n.(*ast.IfStmt) if ok { checkHIPAACondition(pass, ifStmt.Cond, ifStmt.Body) return true } // Look for switch statements switchStmt, ok := n.(*ast.SwitchStmt) if ok { checkHIPAASwitch(pass, switchStmt) return true } return true }) } return nil, nil } // checkHIPAACondition checks if an if condition is checking for HIPAA mode func checkHIPAACondition(pass *analysis.Pass, cond ast.Expr, body *ast.BlockStmt) { // Check if condition checks for "hipaa" string if !containsHIPAACheck(cond) { return } // Check what fields are accessed in the body checkedFields := extractCheckedFields(body) // Report missing fields var missing []string for _, required := range hipaaRequiredFields { found := false for _, checked := range checkedFields { if strings.EqualFold(checked, required) { found = true break } } if !found { missing = append(missing, required) } } // If checking HIPAA mode but not all required fields, report it if len(missing) > 0 && len(missing) < len(hipaaRequiredFields) { // Partial check detected - this is the problematic case pass.Reportf(body.Pos(), "HIPAA compliance mode check is incomplete - missing required fields: %v", missing) } } // checkHIPAASwitch checks switch statements for HIPAA mode handling func checkHIPAASwitch(pass *analysis.Pass, switchStmt *ast.SwitchStmt) { // Check if the switch tag checks compliance mode if switchStmt.Tag == nil { return } if !isComplianceModeCheck(switchStmt.Tag) { return } // Find the "hipaa" case var hipaaCase *ast.CaseClause for _, stmt := range switchStmt.Body.List { caseClause, ok := stmt.(*ast.CaseClause) if !ok { continue } // Check if this case is for "hipaa" for _, val := range caseClause.List { if isHipaaString(val) { hipaaCase = caseClause break } } if hipaaCase != nil { break } } if hipaaCase == nil { return } // Check what fields are accessed in the hipaa case body checkedFields := extractCheckedFieldsFromStmts(hipaaCase.Body) // Report missing fields var missing []string for _, required := range hipaaRequiredFields { found := false for _, checked := range checkedFields { if strings.EqualFold(checked, required) { found = true break } } if !found { missing = append(missing, required) } } if len(missing) > 0 && len(missing) < len(hipaaRequiredFields) { pass.Reportf(hipaaCase.Pos(), "HIPAA case is incomplete - missing required field checks: %v", missing) } } // containsHIPAACheck checks if an expression contains a check for "hipaa" func containsHIPAACheck(expr ast.Expr) bool { switch e := expr.(type) { case *ast.BinaryExpr: // Check for == "hipaa" or != "hipaa" if isHipaaString(e.X) || isHipaaString(e.Y) { return true } // Recursively check both sides return containsHIPAACheck(e.X) || containsHIPAACheck(e.Y) case *ast.CallExpr: // Check for strings.EqualFold(x, "hipaa") or similar return containsHipaaInCall(e) } return false } // isHipaaString checks if an expression is the string literal "hipaa" func isHipaaString(expr ast.Expr) bool { lit, ok := expr.(*ast.BasicLit) if !ok { return false } return lit.Kind == token.STRING && (lit.Value == `"hipaa"` || lit.Value == `"HIPAA"`) } // isComplianceModeCheck checks if an expression is accessing compliance_mode func isComplianceModeCheck(expr ast.Expr) bool { switch e := expr.(type) { case *ast.SelectorExpr: return strings.EqualFold(e.Sel.Name, "ComplianceMode") || strings.EqualFold(e.Sel.Name, "compliance_mode") case *ast.Ident: return strings.EqualFold(e.Name, "complianceMode") || strings.EqualFold(e.Name, "compliance_mode") } return false } // containsHipaaInCall checks if a function call contains "hipaa" as an argument func containsHipaaInCall(call *ast.CallExpr) bool { for _, arg := range call.Args { if isHipaaString(arg) { return true } } return false } // extractCheckedFields extracts field names that are accessed in a block func extractCheckedFields(block *ast.BlockStmt) []string { if block == nil { return nil } return extractCheckedFieldsFromStmts(block.List) } // extractCheckedFieldsFromStmts extracts field names from a list of statements func extractCheckedFieldsFromStmts(stmts []ast.Stmt) []string { var fields []string for _, stmt := range stmts { ast.Inspect(stmt, func(n ast.Node) bool { // Look for selector expressions (field access) sel, ok := n.(*ast.SelectorExpr) if !ok { return true } fieldName := sel.Sel.Name fields = append(fields, fieldName) return true }) } return fields }