class SpringSecurityTagger
- SpringSecurityTagger
- FrameworkTagger
- Tagger
- Reference
- Object
Overview
Spring-specific security tagger.
spring_auth already classifies authentication/authorization
(@PreAuthorize/@Secured/@RolesAllowed annotations and HttpSecurity URL
rules). This tagger covers the other Spring security signals a reviewer
cares about — the protections Spring ships and the deviations from its
secure defaults — that map cleanly onto an endpoint:
- csrf-protection — Spring Security CSRF-protects every state-changing
request by default. We flag the state-changing endpoints
(POST/PUT/PATCH/DELETE) where that is turned off, either wholesale for
a filter chain (
csrf().disable(),csrf(AbstractHttpConfigurer::disable), Kotlincsrf { disable() }) or selectively for specific paths (csrf(c -> c.ignoringRequestMatchers("/api/**"))). Common and often intentional for token/stateless APIs, but always worth surfacing. - cors — a
@CrossOriginannotation on the handler/controller, or a globalWebMvcConfigurerCORS mapping (addMapping(...).allowedOrigins("*")), opts the endpoint out of the browser same-origin default. Wildcard origins (*), especially combined with credentials, are permissive. - security-headers — Spring Security adds a sensible default header set
(X-Frame-Options DENY, X-Content-Type-Options, Cache-Control, …). We
flag the endpoints where those are weakened: clickjacking protection
off (
frameOptions().disable()) or the whole header writer disabled (headers().disable()/headers(HeadersConfigurer::disable)). - input-validation —
@Valid/@Validatedon the handler applies Bean Validation to the request payload, the primary Spring input-validation control. Surfacing where it IS applied also makes the gaps — handlers taking a body without it — visible by their absence.
CSRF / security-headers / config CORS are detected from the security,
MVC, and WebSocket config (pre-scanned once, like spring_auth's URL rules). The
@CrossOrigin and input-validation signals are per-endpoint, line-based
walks of the handler the endpoint maps to. Cross-file concerns (a custom
Filter bean, a bespoke CorsConfigurationSource) are out of scope.
Defined in:
tagger/framework_taggers/java/spring_security.crConstant Summary
-
CSRF_DISABLE =
/csrf\s*(?:\(\s*\)\s*\.\s*disable\b|\([^)]*\bdisable|\{[^}]*\bdisable)/ -
csrf().disable()(fluent),csrf(csrf -> csrf.disable())/csrf(AbstractHttpConfigurer::disable)(lambda/method-ref), and Kotlincsrf { disable() }. Whole-chain disable. -
FRAME_OPTIONS_DISABLE =
/frameOptions\s*(?:\(\s*\)\s*\.\s*disable\b|\([^)]*\bdisable|\{[^}]*\bdisable)/ -
Clickjacking protection off:
frameOptions().disable(),frameOptions(f -> f.disable()), KotlinframeOptions { disable() }. -
HEADERS_FULLY_DISABLED =
/headers\s*(?:\(\s*\)\s*\.\s*disable\b|\([^)]*::\s*disable)/ -
Whole default header writer off. Restricted to the unambiguous forms — empty-paren fluent
headers().disable()and the method-refheaders(HeadersConfigurer::disable)— so a nested per-header disable such asheaders(h -> h.frameOptions(f -> f.disable()))is NOT mistaken for an all-headers-off (that one is caught by FRAME_OPTIONS_DISABLE). -
IGNORING_ARGS =
/(?:ignoringRequestMatchers|ignoringAntMatchers)\s*\(([^;]*?)\)/ -
ignoringRequestMatchers(...)/ignoringAntMatchers(...)— CSRF kept on for the chain but skipped for these (absolute) path patterns. Captured across line breaks: the arg group stops at the statement's;, never crossing into the next statement. The inner quote scan pulls the path literal even when wrapped (e.g.new AntPathRequestMatcher("/api")). -
MATCHER_CALL =
/\b(?:securityMatcher|antMatcher)\s*\(/ -
Chain-level request matchers that scope a SecurityFilterChain to a URL subset.
requestMatchers(...)is deliberately excluded: insideauthorizeHttpRequests {…}it scopes an authorization rule, not the chain, and treating those as CSRF scopes would mis-attribute the rule. -
SCOPE_BOUNDARY =
/SecurityFilterChain\b|configure\s*\(\s*(?:final\s+)?HttpSecurity/ -
A SecurityFilterChain bean / WebSecurityConfigurerAdapter.configure body delimits one HttpSecurity scope. A CSRF-disable and any chain-level securityMatcher are associated within the same scope/block.
-
STATE_CHANGING_METHODS =
Set {"POST", "PUT", "PATCH", "DELETE"}
Constructors
Class Method Summary
Instance Method Summary
-
#perform(endpoints : Array(Endpoint)) : Array(Endpoint)
The per-endpoint shape: look at each endpoint, tag in place, hand the array back.
Instance methods inherited from class FrameworkTagger
base_relative_path(path : String) : String
base_relative_path,
class_level_annotation(path : String, lines : Array(String), annotation_name : String) : String | Nil
class_level_annotation,
collect_files_by_extension(extension : String) : Array(String)
collect_files_by_extension,
perform(endpoints : Array(Endpoint)) : Array(Endpoint)
perform,
read_file(path : String) : String | Nil
read_file,
read_file_lines(path : String) : Array(String) | Nil
read_file_lines,
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_basename(basename : String) : Array(String)
get_files_by_basename,
get_files_by_extension(extension : String) : Array(String)
get_files_by_extension,
get_files_by_extensions(extensions : Array(String)) : Array(String)
get_files_by_extensions,
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_files_by_relative_path(relative_path : String, root : String = "") : Array(String)
get_files_by_relative_path,
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,
walked_path(expanded : String) : String
walked_path
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
Class methods inherited from class Tagger
tagger_key : String
tagger_key
Constructor Detail
Class Method Detail
Instance Method Detail
The per-endpoint shape: look at each endpoint, tag in place, hand the
array back. Fifteen framework taggers carried a byte-identical copy of
this; they now declare only check_endpoint.
Not every framework tagger fits it — eleven still override #perform
because they need a pre-scan over the project (config files, middleware
registration) before the per-endpoint pass, or they group endpoints
first. Those keep their own.