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 21:00:07 UTC
(tooling-agents) branch main updated: ASVS audit: 16.3.3.md (redacted) [source: apache/steve/v3 @ d0aa7e9]
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 09fe174 ASVS audit: 16.3.3.md (redacted) [source: apache/steve/v3 @ d0aa7e9]
09fe174 is described below
commit 09fe174ae97984ba60b86fcdd42da0c3e116992b
Author: ASF Tooling Team <ro...@apache.org>
AuthorDate: Tue May 5 22:54:24 2026 +0200
ASVS audit: 16.3.3.md (redacted) [source: apache/steve/v3 @ d0aa7e9]
---
ASVS/reports/steve/v3/d0aa7e9/all/16.3.3.md | 203 ++++++++++++++++++++++++++++
1 file changed, 203 insertions(+)
diff --git a/ASVS/reports/steve/v3/d0aa7e9/all/16.3.3.md b/ASVS/reports/steve/v3/d0aa7e9/all/16.3.3.md
new file mode 100644
index 0000000..fc4a32d
--- /dev/null
+++ b/ASVS/reports/steve/v3/d0aa7e9/all/16.3.3.md
@@ -0,0 +1,203 @@
+# Security Audit Report: ASVS 16.3.3
+
+## Executive Summary
+
+| Field | Value |
+|-------|-------|
+| **Repository** | apache/steve/v3 |
+| **Audit Date** | May 05, 2026 |
+| **Auditor** | Tooling Agents (bundled-pass mode) |
+| **ASVS Requirement** | ASVS 16.3.3 |
+| **Files Analyzed** | 9 relevant / 49 total |
+| **Files Skipped** | 12 |
+
+**Requirement description:** Verify that the application logs the security events that are defined in the documentation and also logs attempts to bypass the security controls, such as input validation, business logic, and anti-automation.
+
+### Findings Overview
+
+| Severity | Count |
+|----------|-------|
+| 🔴 Critical | 0 |
+| 🟠 High | 2 |
+| 🟡 Medium | 2 |
+| 🟢 Low | 0 |
+
+---
+
+## ASVS-16.3.3: Security Events and Bypass Attempt Logging
+
+### Findings for 16.3.3
+
+### [HIGH]
+**Finding ID:** ASVS-1633-HIGH-001
+**Location:** `v3/server/pages.py`, `do_vote_endpoint()` (line 399)
+**Vulnerable Code:**
+```python
+for iid, votestring in votes.items():
+ if iid not in issue_dict:
+ await flash_danger(f'Invalid issue ID: {iid}')
+ return quart.redirect(f'/vote-on/{election.eid}', code=303)
+```
+**Data Flow:** User submits vote with invalid/manipulated IID → validation catches it → redirect with flash → NO LOG
+**Proof of Concept:**
+```
+POST /do-vote/abc1234567 HTTP/1.1
+Content-Type: application/x-www-form-urlencoded
+
+vote-FORGED_IID=y&csrf_token=placeholder
+```
+**Impact:** Input validation failures (potential bypass attempts) are caught but not logged. An attacker attempting to vote on issues outside their election, or injecting fabricated issue IDs, leaves no audit trail.
+**Remediation:**
+```python
+if iid not in issue_dict:
+ _LOGGER.warning(
+ f'INPUT_VALIDATION_BYPASS: user={result.uid} submitted invalid '
+ f'issue_id={iid} for election={election.eid}'
+ )
+ await flash_danger(f'Invalid issue ID: {iid}')
+ return quart.redirect(f'/vote-on/{election.eid}', code=303)
+```
+
+### [HIGH]
+**Finding ID:** ASVS-1633-HIGH-002
+**Location:** `v3/server/pages.py`, `_set_election_date()` (lines 95-99)
+**Vulnerable Code:**
+```python
+if not date_str:
+ quart.abort(400, 'Missing date')
+
+try:
+ dt = datetime.datetime.fromisoformat(date_str).date()
+except ValueError:
+ quart.abort(400, 'Invalid date format')
+```
+**Data Flow:** User submits malformed date → validation rejects → 400 response → NO LOG
+**Proof of Concept:**
+```
+POST /do-set-open_at/abc1234567 HTTP/1.1
+Content-Type: application/json
+
+{"date": "'; DROP TABLE election; --"}
+```
+**Impact:** Invalid input that fails validation is not logged. Repeated invalid requests (potential injection attempts) generate no security events.
+**Remediation:**
+```python
+if not date_str:
+ _LOGGER.warning(f'INPUT_VALIDATION: user={result.uid} missing date for {field} on election={election.eid}')
+ quart.abort(400, 'Missing date')
+
+try:
+ dt = datetime.datetime.fromisoformat(date_str).date()
+except ValueError:
+ _LOGGER.warning(f'INPUT_VALIDATION: user={result.uid} invalid date_format for {field} on election={election.eid}')
+ quart.abort(400, 'Invalid date format')
+```
+
+### [MEDIUM]
+**Finding ID:** ASVS-1633-MED-001
+**Location:** `v3/server/pages.py` — no anti-automation detection
+**Vulnerable Code:**
+```python
+# No rate limiting, no anti-automation controls, no suspicious pattern detection
+@APP.post('/do-vote/<eid>')
+@asfquart.auth.require({R.committer})
+@load_election
+async def do_vote_endpoint(election):
+ # ... processes vote immediately without any anti-automation check ...
+```
+**Data Flow:** Repeated automated requests → endpoint → processing → no detection/logging
+**Impact:** There are no anti-automation controls and therefore no logging of bypass attempts. Automated vote submission, rapid election manipulation, or brute-force ID enumeration cannot be detected.
+**Remediation:** Implement rate limiting middleware with logging:
+```python
+from quart_rate_limiter import RateLimiter, rate_limit
+
+rate_limiter = RateLimiter(APP)
+
+@APP.post('/do-vote/<eid>')
+@rate_limit(10, timedelta(minutes=1)) # 10 votes per minute
+async def do_vote_endpoint(election):
+ ...
+```
+
+### [MEDIUM]
+**Finding ID:** ASVS-1633-MED-002
+**Location:** `v3/steve/election.py`, state assertion failures (multiple lines)
+**Vulnerable Code:**
+```python
+def close(self):
+ "Close an election."
+ # The Election should be open.
+ assert self.is_open()
+ # ...
+
+def add_issue(self, title, description, vtype, kv):
+ assert self.is_editable()
+ assert vtype in vtypes.TYPES
+```
+**Data Flow:** Business logic violation → `assert` → `AssertionError` → unhandled crash → no security log
+**Proof of Concept:** Attempting to close an already-closed election or add an issue to an open election triggers an unlogged AssertionError.
+**Impact:** Business logic bypass attempts (operating on elections in wrong state) crash with AssertionError but generate no security event log. Additionally, assertions are disabled with `python -O`, removing these checks entirely in optimized mode.
+**Remediation:** Replace assertions with proper exceptions and log security events:
+```python
+def close(self):
+ if not self.is_open():
+ _LOGGER.warning(f'BUSINESS_LOGIC_VIOLATION: attempted to close election[E:{self.eid}] in state={self.get_state()}')
+ raise ElectionBadState(self.eid, self.get_state(), self.S_OPEN)
+ self.c_close.perform(self.eid)
+```
+
+### Security Controls Inventory for 16.3.3
+
+| Control | Location | Coverage Status |
+|---------|----------|-----------------|
+| Input validation bypass logging | Not found | ❌ NOT IMPLEMENTED |
+| Anti-automation detection | Not found | ❌ NOT IMPLEMENTED |
+| Business logic violation logging | Not found | ❌ NOT IMPLEMENTED (assertions only) |
+| State transition logging | `pages.py:445,461` | ✅ Partial — open/close logged but violations not |
+| CSRF bypass logging | N/A (CSRF not implemented) | ❌ NOT APPLICABLE |
+| Election tamper detection logging | `tally.py:146-148` | ✅ Detected but only prints, no structured log |
+
+### Positive Patterns for 16.3.3
+
+1. **Administrative actions are logged** — Election creation, opening, closing, issue add/edit/delete all produce `_LOGGER.info()` entries with user and resource identifiers.
+2. **Anti-tamper detection exists** — `is_tampered()` in `election.py` computes and verifies an `opened_key` to detect election data modification after opening.
+3. **Vote actions logged without content** — Successful votes are logged with user/issue/election identifiers but never the vote content, balancing auditability with vote secrecy.
+
+---
+
+
+
+## Cross-cutting Architecture Observations
+
+1. **Logging maturity is low** — The application has action logging for administrative operations but lacks authentication event logging, authorization failure logging, input validation failure logging, and error logging across most endpoints. Only `do_vote_endpoint()` demonstrates the full pattern of try/except with error logging.
+
+2. **Type B gaps are pervasive** — The codebase contains numerous `### check authz` comments indicating the developer intended to add authorization checks. These are never implemented, creating a false sense of security and making authorization failure logging impossible.
+
+3. **No centralized logging infrastructure** — There is no logging middleware, no structured log format (e.g., JSON), no log sanitization layer, and no consistent error handling pattern. Each endpoint handles (or doesn't handle) logging independently.
+
+4. **Debug code in production paths** — `print('FORM:', form)` statements exist in two production endpoints, bypassing all logging controls and dumping raw user data.
+
+5. **Security assertions vs. proper error handling** — The `election.py` module uses Python `assert` statements for security-critical state checks. These are: (a) disabled with `-O` flag, (b) generate no log entries when they fire, and (c) provide no graceful error handling.
+
+6. **Single responsibility gap** — The authentication framework (`asfquart.auth`) handles enforcement but there's no evidence it handles logging. The application layer logs actions but not auth events. This creates a gap where neither layer owns auth logging.
+
+## Cross-cutting Recommendations
+
+### Immediate (Critical/High priority)
+1. **Remove debug `print()` statements** — Lines 481 and 497 in `pages.py` dump raw form data to stdout. Remove immediately.
+2. **Implement log sanitization** — Create a wrapper or formatter that strips control characters (`\r`, `\n`, `\x00`-`\x1f`) from all logged values before output.
+3. **Add error handling with logging to all state-changing endpoints** — Wrap `election.open()`, `election.close()`, `Election.create()` in try/except with `_LOGGER.error()`.
+4. **Log authorization denials** — Add `_LOGGER.warning()` calls in `vote_on_page()` and `serve_doc()` where access is denied.
+
+### Short-term (1-2 sprints)
+5. **Implement authentication event logging** — Add a middleware or decorator that logs all authentication successes and failures with metadata (user, endpoint, method, IP, auth type).
+6. **Replace `assert` with proper exceptions** — Convert all security-relevant `assert` statements in `election.py` to explicit checks with `ElectionBadState` exceptions and logging.
+7. **Implement authorization checks** — Address all `### check authz` placeholders with ownership verification and log failures.
+8. **Add input validation failure logging** — Log when date parsing fails, when invalid IIDs are submitted, and when other validation rejects input.
+
+### Long-term (Architecture)
+9. **Adopt structured logging (JSON)** — Migrate to structured log format with consistent fields (`timestamp`, `level`, `event_type`, `user_id`, `resource_id`, `action`, `outcome`) for machine-readable analysis.
+10. **Implement centralized security event framework** — Create a `SecurityEvent` class or module that provides typed events (`AUTH_SUCCESS`, `AUTH_FAILURE`, `AUTHZ_DENIED`, `INPUT_VALIDATION_FAILED`, `BUSINESS_LOGIC_VIOLATION`) with automatic metadata collection.
+11. **Add anti-automation detection** — Implement rate limiting with logging of threshold violations to detect brute-force or automated abuse.
+12. **PII handling policy in logs** — Establish a logging policy that defines which fields may be logged in full, which must be masked, and which must never be logged, then enforce via the structured logging framework.
+
\ 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