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:04:57 UTC
(tooling-agents) branch main updated: ASVS audit: 15.4.4.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 f68bf39 ASVS audit: 15.4.4.md (redacted)
f68bf39 is described below
commit f68bf39d434f7c6bd59b27763faf73b923fb6733
Author: ASF Tooling Team <ro...@apache.org>
AuthorDate: Tue May 5 14:04:51 2026 +0200
ASVS audit: 15.4.4.md (redacted)
---
ASVS/reports/steve/v3/d0aa7e9/all/15.4.4.md | 183 ++++++++++++++++++++++++++++
1 file changed, 183 insertions(+)
diff --git a/ASVS/reports/steve/v3/d0aa7e9/all/15.4.4.md b/ASVS/reports/steve/v3/d0aa7e9/all/15.4.4.md
new file mode 100644
index 0000000..7b8a58c
--- /dev/null
+++ b/ASVS/reports/steve/v3/d0aa7e9/all/15.4.4.md
@@ -0,0 +1,183 @@
+# Security Audit Report: ASVS 15.4.4
+
+## Executive Summary
+
+| Field | Value |
+|-------|-------|
+| **Repository** | apache/steve/v3 |
+| **Audit Date** | May 05, 2026 |
+| **Auditor** | Tooling Agents (bundled-pass mode) |
+| **ASVS Requirement** | ASVS 15.4.4 |
+| **Files Analyzed** | 5 relevant / 49 total |
+| **Files Skipped** | 12 |
+
+**Requirement description:** Verify that resource allocation policies prevent thread starvation by ensuring fair access to resources, such as by leveraging thread pools, allowing lower-priority threads to proceed within a reasonable timeframe.
+
+### Findings Overview
+
+| Severity | Count |
+|----------|-------|
+| 🔴 Critical | 0 |
+| 🟠High | 0 |
+| 🟡 Medium | 1 |
+| 🟢 Low | 1 |
+
+---
+
+## ASVS-15.4.4: Safe Concurrency - Thread Starvation Prevention
+
+### Findings for 15.4.4
+
+### [MEDIUM]
+
+**Finding ID:** ASVS-1544-MED-001
+
+**Title:** Synchronous SQLite Operations Blocking Async Event Loop Without Thread Pool
+
+**File:** `v3/steve/election.py` (multiple methods) and `v3/server/pages.py` (multiple handlers)
+
+**Vulnerable Code:**
+
+In `v3/steve/election.py`, the `add_salts()` method (line 116):
+```python
+def add_salts(self):
+ "Set the SALT column in the MAYVOTE table."
+ assert self.is_editable()
+ self.db.conn.execute('BEGIN TRANSACTION')
+ self.q_all_issues.perform(self.eid)
+ for mayvote in self.q_all_issues.fetchall():
+ salt = crypto.gen_salt()
+ self.c_salt_mayvote.perform(salt, mayvote.rowid)
+ self.db.conn.execute('COMMIT')
+```
+
+In `v3/server/pages.py`, the `voter_page()` handler (line 133):
+```python
+async def voter_page():
+ result = await basic_info()
+ with asfpy.stopwatch.Stopwatch():
+ election = steve.election.Election.open_to_pid(DB_FNAME, result.uid)
+ owned = steve.election.Election.owned_elections(DB_FNAME, result.uid)
+```
+
+**Data Flow:** HTTP request → async handler → synchronous SQLite call → event loop blocked → other requests starved
+
+**Impact:** The Quart async web framework runs on an asyncio event loop. All database operations in `steve.election.Election` use synchronous SQLite calls (`sqlite3` module via `asfpy.db`). When these operations execute (especially bulk operations like `add_salts()`, `tally_issue()`, or `gather_election_data()`), they block the entire event loop. During an election open operation with many voters, all other requests—including those from lower-priority or concurrent users—are starved unti [...]
+
+**Proof of Concept:** An election with thousands of voters triggers `add_salts()` on the `/do-open/<eid>` endpoint. While this iterates and generates salts for each mayvote row, all other async handlers are blocked, causing request timeouts for concurrent users.
+
+**Remediation:**
+
+```python
+import asyncio
+from concurrent.futures import ThreadPoolExecutor
+
+# At module level in pages.py
+_DB_EXECUTOR = ThreadPoolExecutor(max_workers=4, thread_name_prefix='db-worker')
+
+# Example for voter_page:
+async def voter_page():
+ result = await basic_info()
+ loop = asyncio.get_event_loop()
+ election = await loop.run_in_executor(
+ _DB_EXECUTOR,
+ steve.election.Election.open_to_pid, DB_FNAME, result.uid
+ )
+ owned = await loop.run_in_executor(
+ _DB_EXECUTOR,
+ steve.election.Election.owned_elections, DB_FNAME, result.uid
+ )
+```
+
+---
+
+### [LOW]
+
+**Finding ID:** ASVS-1544-LOW-001
+
+**Title:** No Request Timeout or Connection Limits Configured
+
+**File:** `v3/server/main.py` (lines 52-85)
+
+**Vulnerable Code:**
+```python
+def run_standalone():
+ logging.basicConfig(...)
+ app = create_app()
+ extra_files = { steve.election.QUERIES }
+ kwargs = {}
+ if app.cfg.server.certfile:
+ kwargs['certfile'] = CERTS_DIR / app.cfg.server.certfile
+ kwargs['keyfile'] = CERTS_DIR / app.cfg.server.keyfile
+ app.runx(port=app.cfg.server.port, extra_files=extra_files, **kwargs)
+```
+
+**Impact:** No visible configuration for request timeouts, maximum concurrent connections, or worker limits. Under load, all resources may be consumed by long-running requests (e.g., tallying large elections), with no mechanism to ensure fair scheduling for other users.
+
+**Remediation:** Configure Hypercorn/Quart with appropriate limits:
+```python
+# In hypercorn.toml or programmatically:
+# keep_alive_timeout = 5
+# graceful_timeout = 3
+# workers = 4 # multiple workers for fairness
+```
+
+### Security Controls Inventory for 15.4.4
+
+| Control | Location | Status |
+|---------|----------|--------|
+| Thread pool for DB operations | Not present | **MISSING** |
+| Async database driver | Not present (uses synchronous sqlite3) | **MISSING** |
+| Request timeout configuration | Not visible in `main.py` | **MISSING** |
+| Worker/connection limits | Not configured in visible code | **MISSING** |
+| Transaction scope management | `election.py` lines 55, 122 | Present but blocks event loop |
+| Stopwatch monitoring | `pages.py` line 147 | Present (detection only, no prevention) |
+
+### Positive Patterns for 15.4.4
+
+- Use of `asfpy.stopwatch.Stopwatch()` in `pages.py` indicates awareness of performance concerns
+- Transactions in `add_salts()` and `delete()` are scoped to minimize lock duration
+- SQLite WAL mode (if configured) would allow concurrent reads during writes
+
+---
+
+
+
+## Cross-cutting Architecture Observations
+
+1. **Logging Architecture Maturity**: The application has basic logging in place with consistent patterns (module loggers, action logging), but lacks the maturity markers expected for ASVS Level 2/3: no documentation, no structured format, no correlation IDs, and insufficient timestamp precision.
+
+2. **Async/Sync Impedance Mismatch**: The application uses Quart (async) but all database operations via `asfpy.db`/`sqlite3` are synchronous. This creates a fundamental architectural issue affecting both concurrency fairness (15.4.4) and potentially logging reliability (if the event loop is blocked, log writes may also be delayed).
+
+3. **Centralized Logging Configuration with Gaps**: While `main.py` centralizes logging configuration, the `print()` statements in `pages.py` and the separate `basicConfig()` in `mail-voters.py` create inconsistencies that undermine all logging requirements simultaneously.
+
+4. **Security Event Coverage**: The application logs the right categories of events (CRUD operations, state changes, access decisions) but the metadata quality (missing source IP, missing correlation ID, imprecise timestamps) significantly reduces the investigative value of these logs.
+
+5. **No Separation of Security vs. Operational Logs**: All logs go to the same destination with the same format. There's no differentiation between security-relevant events (votes, election state changes, access denials) and operational events (loading elections, rendering templates).
+
+## Cross-cutting Recommendations
+
+### Immediate (Sprint 1)
+
+1. **Fix timestamp format** — Change `DATE_FORMAT` to `'%Y-%m-%dT%H:%M:%S%z'` and set `logging.Formatter.converter = time.gmtime` for UTC. Single-line fix with highest impact on 16.2.2.
+
+2. **Remove `print()` statements** — Replace the two `print('FORM:', form)` calls in `pages.py` with `_LOGGER.debug()` or remove entirely. Fixes 16.2.3 compliance.
+
+3. **Add source IP to log messages** — Include `quart.request.remote_addr` in security-relevant log entries. Improves 16.2.1 metadata.
+
+### Short-term (1-2 Sprints)
+
+4. **Implement request correlation IDs** — Add a `before_request` hook that generates and propagates a request ID through all log entries. Addresses 16.2.4 correlation.
+
+5. **Create logging inventory document** — Document all event types, destinations, formats, access controls, and retention. Addresses 16.1.1 entirely.
+
+6. **Adopt structured logging format** — Migrate to JSON logging format (e.g., `python-json-logger`) for machine parseability. Addresses 16.2.4.
+
+### Long-term (Next Quarter)
+
+7. **Implement async database layer** — Use `aiosqlite` or wrap synchronous calls in `asyncio.to_thread()` with a bounded thread pool to prevent event loop starvation. Addresses 15.4.4.
+
+8. **Add request timeout middleware** — Configure Hypercorn's `keep_alive_timeout` and add application-level timeouts for database operations. Further addresses 15.4.4.
+
+9. **Implement log access controls** — Define and enforce who can access logs, implement log rotation with retention policies, and consider separating security logs from operational logs. Addresses 16.1.1 comprehensively.
+
\ 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