You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tooling.apache.org by as...@apache.org on 2026/05/05 12:15:41 UTC

(tooling-agents) branch main updated: ASVS audit: 4.1.5.md (redacted)

This is an automated email from the ASF dual-hosted git repository.

asf-tooling pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tooling-agents.git


The following commit(s) were added to refs/heads/main by this push:
     new e73c71a  ASVS audit: 4.1.5.md (redacted)
e73c71a is described below

commit e73c71a9676c4800390e5f1bdb2084f06b1754ec
Author: ASF Tooling Team <ro...@apache.org>
AuthorDate: Tue May 5 14:07:28 2026 +0200

    ASVS audit: 4.1.5.md (redacted)
---
 ASVS/reports/steve/v3/d0aa7e9/all/4.1.5.md | 172 +++++++++++++++++++++++++++++
 1 file changed, 172 insertions(+)

diff --git a/ASVS/reports/steve/v3/d0aa7e9/all/4.1.5.md b/ASVS/reports/steve/v3/d0aa7e9/all/4.1.5.md
new file mode 100644
index 0000000..63cf50c
--- /dev/null
+++ b/ASVS/reports/steve/v3/d0aa7e9/all/4.1.5.md
@@ -0,0 +1,172 @@
+# Security Audit Report: ASVS 4.1.5
+
+## Executive Summary
+
+| Field | Value |
+|-------|-------|
+| **Repository** | apache/steve/v3 |
+| **Audit Date** | May 05, 2026 |
+| **Auditor** | Tooling Agents (bundled-pass mode) |
+| **ASVS Requirement** | ASVS 4.1.5 |
+| **Files Analyzed** | 4 relevant / 49 total |
+| **Files Skipped** | 12 |
+
+**Requirement description:** Verify that per-message digital signatures are used to provide additional assurance on top of transport protections for requests or transactions which are highly sensitive or which traverse a number of systems.
+
+### Findings Overview
+
+| Severity | Count |
+|----------|-------|
+| 🔴 Critical | 0 |
+| 🟠 High | 0 |
+| 🟡 Medium | 1 |
+| 🟢 Low | 0 |
+
+---
+
+## ASVS-4.1.5: Per-Message Digital Signatures
+
+### Findings for 4.1.5
+
+### [MEDIUM]
+
+**Finding ID:** ASVS-415-MED-001
+
+**Title:** Absence of per-message digital signatures for highly sensitive election operations
+
+**File:** `v3/server/pages.py` (multiple endpoints)
+
+**Vulnerable Code:**
+
+```python
+# do_vote_endpoint (line 372) - Highly sensitive vote submission
+@APP.post('/do-vote/<eid>')
+@asfquart.auth.require({R.committer})
+@load_election
+async def do_vote_endpoint(election):
+    result = await basic_info()
+    form = edict(await quart.request.form)
+    # ... processes vote with no per-message signature verification
+    for iid, votestring in votes.items():
+        election.add_vote(result.uid, iid, votestring)
+
+# do_open_endpoint (line 431) - Irreversible election state change
+@APP.get('/do-open/<eid>')
+@asfquart.auth.require({R.committer})
+@load_election
+async def do_open_endpoint(election):
+    # Opens election permanently with no request-level signature
+    election.open(pdb)
+
+# do_close_endpoint (line 451) - Irreversible election state change
+@APP.get('/do-close/<eid>')
+@asfquart.auth.require({R.committer})
+@load_election
+async def do_close_endpoint(election):
+    # Closes election permanently with no request-level signature
+    election.close()
+```
+
+**Data Flow:** Client HTTP request → Quart framework (TLS only) → endpoint handler → state-changing operation → no message-level integrity verification beyond transport
+
+**Proof of Concept:** An attacker who compromises a TLS-terminating proxy or load balancer in front of the application could forge or replay election management requests (open, close, vote) since there is no per-message cryptographic binding to the requester's identity beyond the session cookie.
+
+**Impact:** In a deployment where TLS is terminated at a load balancer or reverse proxy (common in ASF infrastructure), the requests between the proxy and application server have no additional integrity protection. A vote submission, election open, or election close could be tampered with or replayed by a compromised intermediary. The voting system handles irreversible, high-integrity operations (elections cannot be re-opened once closed).
+
+**Remediation:**
+
+Implement request signing for critical operations using a scheme like HTTP Message Signatures (RFC 9421):
+
+```python
+import hmac
+import hashlib
+import time
+
+async def verify_request_signature(request, session):
+    """Verify per-message digital signature on sensitive requests."""
+    signature = request.headers.get('X-Request-Signature')
+    timestamp = request.headers.get('X-Request-Timestamp')
+    
+    if not signature or not timestamp:
+        quart.abort(401, 'Missing request signature')
+    
+    # Verify freshness (prevent replay)
+    if abs(time.time() - float(timestamp)) > 30:
+        quart.abort(401, 'Request signature expired')
+    
+    # Reconstruct signed payload
+    body = await request.get_data()
+    message = f"{request.method}{request.path}{timestamp}{body.decode()}"
+    
+    # Verify HMAC using session-bound signing key
+    expected = hmac.new(
+        session['signing_key'].encode(),
+        message.encode(),
+        hashlib.sha256
+    ).hexdigest()
+    
+    if not hmac.compare_digest(signature, expected):
+        quart.abort(401, 'Invalid request signature')
+```
+
+### Security Controls Inventory for 4.1.5
+
+| Control | Location | Coverage Status |
+|---------|----------|-----------------|
+| Vote encryption (at-rest integrity) | `v3/steve/election.py:231-243` | Applied to vote storage |
+| Anti-tamper key (`opened_key`) | `v3/steve/election.py:78, 320-332` | Applied to election data integrity at rest |
+| TLS (transport-level) | Framework/deployment | Assumed but not verified in code |
+| Per-message digital signatures | Not present | **NOT IMPLEMENTED** |
+| CSRF token | `v3/server/pages.py:83` | **PLACEHOLDER ONLY** (`'placeholder'`) |
+
+### Positive Patterns for 4.1.5
+
+1. **Anti-tamper mechanism**: The application implements `is_tampered()` which recomputes the `opened_key` from election data (metadata, issues, voters) to detect unauthorized modifications to election data at rest (`v3/steve/election.py:320-332`).
+2. **Cryptographic vote tokens**: Vote tokens are derived from `opened_key`, PID, IID, and per-voter salt, providing cryptographic binding between voter identity and vote records (`v3/steve/election.py:239`).
+3. **Vote encryption**: Votes are encrypted using `crypto.create_vote()` before storage, preventing plaintext exposure (`v3/steve/election.py:243`).
+
+---
+
+
+
+## Cross-cutting Architecture Observations
+
+1. **Framework Delegation for HTTP-level Security**: The application relies entirely on Quart/Hypercorn for HTTP protocol handling (message framing, header parsing, Content-Length calculation). While this is appropriate for application code, there is no evidence of explicit server configuration enforcing the HTTP-level security requirements (4.2.1-4.2.4). The security posture depends heavily on the deployment architecture (reverse proxy, ASGI server settings) which is not visible in the  [...]
+
+2. **State-Changing GET Requests**: The `/do-open/<eid>` and `/do-close/<eid>` endpoints use GET methods for irreversible state changes. This is particularly concerning in combination with the lack of request smuggling protections (4.2.1), as smuggled GET requests require no body parsing and are easier to exploit.
+
+3. **Placeholder Security Controls**: The CSRF token (`basic.csrf_token = 'placeholder'`) and multiple `### check authz` comments indicate that important security controls are planned but not yet implemented. This creates a false sense of security where templates reference tokens that provide no actual protection.
+
+4. **Sensitive Operations Without Defense-in-Depth**: The voting system handles high-integrity operations (irreversible election state changes, anonymous vote collection) but relies on a single layer of protection (TLS + session cookie authentication). There are no per-message signatures (4.1.5), no request integrity verification beyond transport, and limited input validation for the most critical operations.
+
+5. **Client-Server Trust Boundary**: The frontend JavaScript builds and sends requests to the backend, but there is no server-side validation that these requests are well-formed beyond basic format checks. The absence of size limits, combined with session-stored flash messages, creates a DoS vector (4.2.5).
+
+## Cross-cutting Recommendations
+
+### Immediate (Critical/High Priority)
+
+1. **Implement input length validation** on all user-supplied fields (`title`, `description`, `votestring`) before they are stored or included in flash messages. This prevents the cookie overflow DoS (ASVS-425-MED-001).
+
+2. **Change state-changing operations to POST methods** — convert `/do-open/<eid>` and `/do-close/<eid>` from GET to POST to reduce the attack surface for request smuggling and CSRF.
+
+3. **Implement real CSRF protection** — replace the placeholder token with actual token generation and validation, as this is a prerequisite for meaningful request integrity.
+
+### Short-term (Within Next Sprint)
+
+4. **Add request size limits** at the application level via Quart's `MAX_CONTENT_LENGTH` configuration or middleware, setting appropriate bounds for each endpoint.
+
+5. **Configure ASGI server explicitly** — document and configure Hypercorn (or the deployment ASGI server) settings for:
+   - Maximum header size
+   - HTTP/2 settings frame limits
+   - Connection-specific header rejection in HTTP/2
+
+6. **Add before_request middleware** for HTTP protocol validation (TE/CL conflict detection, CRLF rejection, connection-specific header filtering) as defense-in-depth.
+
+### Long-term (Architecture)
+
+7. **Implement per-message signatures** for critical operations (election open/close, vote submission) using a scheme like HTTP Message Signatures (RFC 9421) or application-level HMAC verification, particularly important if the deployment involves load balancers or TLS-terminating proxies.
+
+8. **Implement server-side session storage** (e.g., Redis-backed) rather than cookie-based sessions to eliminate the cookie size DoS vector entirely and reduce the security impact of session data growth.
+
+9. **Add comprehensive authorization checks** to replace all `### check authz` placeholders, ensuring that election ownership is verified before state-changing operations (currently any committer can open/close any election).
+        
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@tooling.apache.org
For additional commands, e-mail: commits-help@tooling.apache.org