[ 
https://issues.apache.org/jira/browse/WW-5844?focusedWorklogId=1053403&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-1053403
 ]

ASF GitHub Bot logged work on WW-5844:
--------------------------------------

                Author: ASF GitHub Bot
            Created on: 08/Nov/26 15:00
            Start Date: 08/Nov/26 15:00
    Worklog Time Spent: 10m 
      Work Description: lukaszlenart merged PR #2120:
URL: https://github.com/apache/struts/pull/2120




Issue Time Tracking
-------------------

    Worklog Id:     (was: 1053403)
    Time Spent: 50m  (was: 40m)

> HttpMethodInterceptor fails open for the implicit execute() method; 
> restDefaultStack / beanValidationDefaultStack omit httpMethod entirely
> ------------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: WW-5844
>                 URL: https://issues.apache.org/jira/browse/WW-5844
>             Project: Struts 2
>          Issue Type: Bug
>          Components: Core Interceptors
>    Affects Versions: 6.12.0, 7.0.0, 7.3.0, 7.4.0
>            Reporter: Gouri Sankar A
>            Priority: Major
>             Fix For: 7.5.0
>
>          Time Spent: 50m
>  Remaining Estimate: 0h
>
> Two compounding gaps in the @HttpGet/@HttpPost verb-restriction control:
> (a) HttpMethodInterceptor misses an @Http* annotation in four distinct, 
> independent ways:
>   - A method-level annotation on the implicit "execute" method: the 
> method-level check only runs when proxy.isMethodSpecified() is true, which is 
> false for an action invoked without an explicit method= -- so @HttpPost 
> placed directly on execute() is never read for that case. (The separate, 
> unconditional class-level check still runs regardless of isMethodSpecified(), 
> so a class-level annotation on the same action is still enforced; this is 
> narrower than it may first appear.)
>   - A class-level annotation on a base class is not enforced on a subclass 
> that doesn't repeat it, and a method-level annotation is lost the same way 
> when a subclass overrides the annotated method without repeating the 
> annotation -- plain Java annotation semantics, since none of the Http* 
> annotations is @Inherited. This happens independently of isMethodSpecified(), 
> including with an explicit method= configured.
>   - The same loss happens one level further out: an annotation declared on an 
> interface (a default method, or a class-level annotation on the interface 
> itself) is not found by an action class that only implements that interface 
> through an intermediate superclass, rather than directly.
>   Any of the four reaching an unguarded action means any HTTP verb reaches it.
> (b) restDefaultStack (plugins/rest) and beanValidationDefaultStack 
> (plugins/bean-validation) are the only two bundled interceptor stacks 
> anywhere in core or any plugin that carry params but omit httpMethod entirely 
> -- every application extending rest-default or struts-bean-validation gets no 
> verb rejection at all, regardless of annotations (RestActionMapper does read 
> the verb to choose which method to route to, but nothing is ever rejected for 
> using the "wrong" one). Every bundled stack in core and every plugin was 
> enumerated to confirm this is exactly two gaps, not a wider pattern.
> Prevalence: apps/showcase has 156 <action> tags and only 54 use an explicit 
> method=, so roughly two-thirds rely on the implicit default -- gap (a) is 
> realistic wherever a developer adds @HttpPost to an execute()-mapped action 
> as defence-in-depth rather than naming the method.
> Live-verified on a throwaway Struts Boot app, loopback only: two action 
> shapes (implicit execute(), named method) crossed with two package types 
> (rest-default-, bean-validation-derived) = 4 combinations. Before the patch, 
> GET reached the action and ran it in all 4 cases (should have been rejected 
> by @HttpPost in each). After, all 4 GETs returned 405 and the action never 
> ran; POST was unaffected as a control.
> Proposal:
> - HttpMethodInterceptor always resolves the invoked method, including the 
> implicit execute() case, and walks the full class/superclass/interface 
> hierarchy for the nearest annotation at both the method and class level, 
> checking every level's own implemented interfaces (not only the leaf class's) 
> -- Class#getInterfaces() only returns interfaces a class declares itself, not 
> ones a superclass further up implements. Mirrors the existing 
> AnnotationUtils.findAnnotation walk shape used elsewhere in the convention 
> plugin.
> - httpMethod added to restDefaultStack and beanValidationDefaultStack.
> - A new, generic AccStackInvariantsTest (core) walks every stack definition 
> in struts-default.xml and asserts any stack carrying params also carries 
> httpMethod -- a durable regression guard against a third stack developing the 
> same gap.
> Tests: full suites pass with the patch applied -- core 3749/0 failures (2 
> skipped), rest 245/0, bean-validation 25/0, convention 94/0, json 177/0 -- 
> including the existing HttpMethodInterceptorTest and the WW-5718 
> stack-ordering pins (RestDefaultStackTest/BeanValidationDefaultStackTest), 
> both unaffected.
> Affected versions: both gaps present, same code pattern, by source 
> inspection, in the 6.12.0, 7.0.0, 7.3.0 and 7.4.0 tags.



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

Reply via email to