andrewmusselman opened a new issue, #770:
URL: https://github.com/apache/tooling-trusted-releases/issues/770

   **Source:** ASVS 2.3.1 — Finding 3.1
   **CWE:** CWE-841 (Improper Enforcement of Behavioral Workflow)
   **Location:** `atr/storage/writers/vote.py`, lines 100–127
   
   #### Description
   
   The `resolve_manually()` method allows transitioning a release from 
`RELEASE_CANDIDATE` to `RELEASE_PREVIEW` without verifying that:
   1. The release was configured for manual voting (`vote_manual` flag)
   2. An actual vote occurred
   3. Minimum vote requirements were met
   4. Minimum vote duration has elapsed
   
   A committee member could create a release draft, promote it to the candidate 
phase, and immediately call `resolve_manually(vote_result="passed")` to skip 
the entire vote process.
   
   Also related:
   ### Podling two-round vote can be bypassed via manual resolution
   **Source:** ASVS 2.3.1 — Finding 3.2
   **CWE:** CWE-841 (Improper Enforcement of Behavioral Workflow)
   **Location:** `atr/storage/writers/vote.py`, lines 100–127
   
   #### Description
   
   For podling projects, ASF policy requires two voting rounds: first by the 
PPMC, then by the Incubator PMC. The `resolve_release()` method handles this 
correctly by initiating a second vote when the first passes. However, 
`resolve_manually()` contains no podling check and can transition directly to 
`RELEASE_PREVIEW`, skipping the Incubator PMC vote entirely.
   
   #### Recommendation
   
   @dave2wave will test that PPMC voting works
   
   
   
   ### Vote thread URL validation insufficient (SSRF risk)
   
   **Labels:** `ASVS`, `security`, `L1`
   **Source:** ASVS 2.2.1 Finding HIGH-003, ASVS 2.2.2 Finding 2
   **CWE:** CWE-918 (Server-Side Request Forgery)
   **Location:** `atr/post/manual.py`, lines 37–42 and 56–66
   
   #### Description
   
   The manual vote resolution endpoint extracts thread IDs from user-provided 
URLs using `removeprefix()`. This method does not validate that the URL 
actually starts with the expected prefix — if it doesn't, the full original URL 
is returned unchanged and may be used to fetch remote content, creating an SSRF 
vector.
   
   #### Affected Code
   
   ```python
   vote_thread_id = 
vote_thread_url.removeprefix("https://lists.apache.org/thread/";)
   # If URL doesn't start with prefix, original URL is returned unchanged
   ```
   
   #### Recommendation
   
   - Validate that URLs start with `https://lists.apache.org/thread/` using 
`startswith()` before extraction
   - Validate the thread ID portion matches expected format (e.g., alphanumeric)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to