class GoSecurityTagger

Overview

Go security-middleware tagger.

go_auth already classifies authentication middleware (JWT/session/…). This tagger covers the other security middleware Go web frameworks expose — the protections a reviewer wants mapped onto each endpoint because, unlike Rails, Go frameworks ship none of them on by default. Their presence is the signal: which routes carry CSRF tokens, security headers, a rate limit, or a request-body cap, and (by their absence on a state-changing route) which don't.

Detection mirrors go_auth: a pre-scan records group-level .Use(...) middleware against the group's URL prefix, then each endpoint is matched against inline middleware on its own route call and against the prefix-scoped group middleware. Everything is line-based and best-effort.

Precision over recall: the indirect form (mw := limiter.New(...) then a bare api.Use(mw)) is deliberately not resolved — a false "protected" tag is worse for a security review than a miss, so only middleware named directly at the registration site is tagged. Cross-file middleware factories are likewise out of scope by design.

Defined in:

tagger/framework_taggers/go/go_security.cr

Constant Summary

ASSIGN_GROUP = /(\w+)\s*:?=\s*(\w+)\.Group\s*\(\s*"([^"]*)"/

name := parent.Group("/seg") style group declaration (no closure arg).

CLOSURE_GROUP = /(\w+)\.(?:Group|Route|Party|PartyFunc|Mount)\s*\(\s*"([^"]*)"\s*,\s*func/

parent.Group("/seg", func(...) / .Route / .Party closure group.

ROUTE_DEF = /\b(?:GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD|CONNECT|TRACE|Get|Post|Put|Delete|Patch|Options|Head|Connect|Trace|Any|All|Handle|HandleFunc|Match|Add)\s*\(/

A route-definition call. Used only to exclude route lines from the global-wrapper branch (inline route middleware is handled per-endpoint), so an over-broad verb set here is safe.

SECURITY_MIDDLEWARE = [{pattern: /middleware\.CSRF(?:WithConfig)?\s*\(/, tag: "csrf-protection", desc: "Echo CSRF middleware", wrapper: false}, {pattern: /\bcsrf\.New\s*\(/, tag: "csrf-protection", desc: "Fiber CSRF middleware", wrapper: false}, {pattern: /\bcsrf\.Protect\s*\(/, tag: "csrf-protection", desc: "gorilla/csrf protection", wrapper: true}, {pattern: /\bcsrf\.Middleware\s*\(/, tag: "csrf-protection", desc: "gin-csrf middleware", wrapper: false}, {pattern: /\bnosurf\.New(?:Pure)?\s*\(/, tag: "csrf-protection", desc: "nosurf CSRF middleware", wrapper: true}, {pattern: /middleware\.Secure(?:WithConfig)?\s*\(/, tag: "security-headers", desc: "Echo Secure (security headers) middleware", wrapper: false}, {pattern: /\bhelmet\.New\s*\(/, tag: "security-headers", desc: "Fiber Helmet (security headers) middleware", wrapper: false}, {pattern: /\bsecure\.New\s*\(/, tag: "security-headers", desc: "secure (security headers) middleware", wrapper: true}, {pattern: /middleware\.RateLimiter(?:WithConfig)?\s*\(/, tag: "rate-limit", desc: "Echo RateLimiter middleware", wrapper: false}, {pattern: /middleware\.Throttle(?:Backlog)?\s*\(/, tag: "rate-limit", desc: "go-chi Throttle middleware", wrapper: false}, {pattern: /\blimiter\.New\s*\(/, tag: "rate-limit", desc: "rate-limiter middleware", wrapper: false}, {pattern: /\bhttprate\.(?:Limit|LimitByIP|LimitByRealIP|LimitAll)\s*\(/, tag: "rate-limit", desc: "go-chi/httprate rate limiting", wrapper: false}, {pattern: /\btollbooth\.(?:LimitHandler|LimitFuncHandler|LimitByKeys)\s*\(/, tag: "rate-limit", desc: "tollbooth rate limiting", wrapper: false}, {pattern: /middleware\.BodyLimit\s*\(/, tag: "body-limit", desc: "Echo BodyLimit (request body size cap) middleware", wrapper: false}, {pattern: /\blimits\.RequestSizeLimiter\s*\(/, tag: "body-limit", desc: "gin-contrib/size request body size cap", wrapper: false}, {pattern: /middleware\.Timeout(?:WithConfig)?\s*\(/, tag: "timeout", desc: "request timeout middleware", wrapper: false}, {pattern: /\btimeout\.New(?:WithContext)?\s*\(/, tag: "timeout", desc: "Fiber timeout middleware", wrapper: false}, {pattern: /middleware\.CORS(?:WithConfig)?\s*\(/, tag: "cors", desc: "Echo CORS middleware (review allowed origins/credentials)", wrapper: false}, {pattern: /\bcors\.New\s*\(/, tag: "cors", desc: "CORS middleware (review allowed origins/credentials)", wrapper: true}, {pattern: /\bcors\.Default\s*\(/, tag: "cors", desc: "gin-contrib/cors Default() — permissive: all origins allowed", wrapper: false}, {pattern: /\bcors\.AllowAll\s*\(/, tag: "cors", desc: "rs/cors AllowAll() — permissive: all origins allowed", wrapper: true}, {pattern: /\bhandlers\.CORS\s*\(/, tag: "cors", desc: "gorilla/handlers CORS (review allowed origins/credentials)", wrapper: true}, {pattern: /\bencryptcookie\.New\s*\(/, tag: "secure-cookies", desc: "Fiber encrypted-cookie middleware", wrapper: false}] of NamedTuple(pattern: Regex, tag: String, desc: String, wrapper: Bool)

Security middleware constructors/identifiers, each mapped to the tag it produces. Patterns are tied to the concrete constructor (middleware.CSRF, csrf.New, helmet.New, …) so a plain local called secure or limiter can't trip them. wrapper: true marks the net/http-style helpers (gorilla/csrf, unrolled/secure, nosurf) that wrap the root handler rather than register via .Use — those apply globally.

USE_CALL = /(\w+)\.(?:Use|Pre)\s*\(/

A .Use(...) / .Pre(...) middleware registration call.

Constructors

Class Method Summary

Instance Method Summary

Instance methods inherited from class FrameworkTagger

collect_files_by_extension(extension : String) : Array(String) collect_files_by_extension, read_file(path : String) : String | Nil read_file, read_source_context(endpoint : Endpoint) : Array(SourceContext) read_source_context, static_asset_route?(url : String) : Bool static_asset_route?

Constructor methods inherited from class FrameworkTagger

new(options : Hash(String, YAML::Any)) new

Class methods inherited from class FrameworkTagger

target_techs : Array(String) target_techs

Instance methods inherited from module FileHelper

all_files : Array(String) all_files, get_files_by_extension(extension : String) : Array(String) get_files_by_extension, get_files_by_prefix(prefix : String) : Array(String) get_files_by_prefix, get_files_by_prefix_and_extension(prefix : String, extension : String) : Array(String) get_files_by_prefix_and_extension, get_public_dir_files(base_path : String, folder : String) : Array(String) get_public_dir_files, get_public_files(base_path : String, anchors : Array(String) = ["shard.yml", "Gemfile"]) : Array(String) get_public_files

Instance methods inherited from class Tagger

name : String name, perform(endpoints : Array(Endpoint)) : Array(Endpoint) perform

Constructor methods inherited from class Tagger

new(options : Hash(String, YAML::Any)) new

Constructor Detail

def self.new(options : Hash(String, YAML::Any)) #

[View source]

Class Method Detail

def self.target_techs : Array(String) #

[View source]

Instance Method Detail

def perform(endpoints : Array(Endpoint)) : Array(Endpoint) #

[View source]