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:03:31 UTC

(tooling-agents) branch main updated: ASVS audit: 13.2.6.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 fead212  ASVS audit: 13.2.6.md (redacted)
fead212 is described below

commit fead212380cdd834ee84799875f43275233edaf0
Author: ASF Tooling Team <ro...@apache.org>
AuthorDate: Tue May 5 14:03:25 2026 +0200

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

diff --git a/ASVS/reports/steve/v3/d0aa7e9/all/13.2.6.md b/ASVS/reports/steve/v3/d0aa7e9/all/13.2.6.md
new file mode 100644
index 0000000..e109744
--- /dev/null
+++ b/ASVS/reports/steve/v3/d0aa7e9/all/13.2.6.md
@@ -0,0 +1,174 @@
+# Security Audit Report: ASVS 13.2.6
+
+## Executive Summary
+
+| Field | Value |
+|-------|-------|
+| **Repository** | apache/steve/v3 |
+| **Audit Date** | May 05, 2026 |
+| **Auditor** | Tooling Agents (bundled-pass mode) |
+| **ASVS Requirement** | ASVS 13.2.6 |
+| **Files Analyzed** | 7 relevant / 49 total |
+| **Files Skipped** | 12 |
+
+**Requirement description:** Verify that where the application connects to separate services, it follows the documented configuration for each connection, such as maximum parallel connections, behavior when maximum allowed connections is reached, connection timeouts, and retry strategies.
+
+### Findings Overview
+
+| Severity | Count |
+|----------|-------|
+| 🔴 Critical | 0 |
+| 🟠 High | 0 |
+| 🟡 Medium | 1 |
+| 🟢 Low | 1 |
+
+---
+
+## ASVS-13.2.6: Connection Configuration
+
+### Findings for 13.2.6
+
+### [MEDIUM]
+
+**Finding ID**: ASVS-1326-MED-001
+
+**Title**: Database connections opened without documented configuration for timeouts, connection limits, or retry strategies
+
+**File**: `v3/steve/election.py`, function `open_database()`, line 36
+
+**Vulnerable Code**:
+```python
+@staticmethod
+def open_database(db_fname):
+    return asfpy.db.DB(db_fname, yaml_fname=QUERIES, yaml_section='election')
+```
+
+**Additional instances**:
+- `v3/steve/persondb.py`, line 27:
+```python
+@classmethod
+def open(cls, db_fname):
+    return cls(asfpy.db.DB(db_fname, yaml_fname=QUERIES, yaml_section='person'))
+```
+
+- `v3/server/pages.py`, line 567 (ad-hoc database opening):
+```python
+db = steve.election.Election.open_database(DB_FNAME)
+```
+
+**Data flow**: Multiple call sites → `asfpy.db.DB()` → SQLite connection with no timeout, pool limit, or retry configuration.
+
+**Impact**: 
+- No connection timeout means requests could hang indefinitely if the database file becomes locked
+- No maximum connection limit means concurrent requests could exhaust file handles
+- No retry strategy means transient failures (e.g., WAL checkpoint) cause immediate errors
+- Database connections are opened per-request without pooling (e.g., `pdb = steve.persondb.PersonDB.open(DB_FNAME)` in multiple handlers)
+
+**Proof of concept**: Under concurrent load, multiple requests simultaneously opening SQLite connections could cause `database is locked` errors with no retry mechanism.
+
+**Remediation**:
+```python
+import sqlite3
+
+# Configuration constants
+DB_TIMEOUT = 30  # seconds to wait for database lock
+DB_MAX_CONNECTIONS = 10  # maximum parallel connections
+DB_RETRY_ATTEMPTS = 3
+DB_RETRY_DELAY = 0.5  # seconds
+
+@staticmethod
+def open_database(db_fname):
+    db = asfpy.db.DB(db_fname, yaml_fname=QUERIES, yaml_section='election')
+    # Set connection timeout
+    db.conn.execute(f'PRAGMA busy_timeout = {DB_TIMEOUT * 1000}')
+    # Enable WAL mode for better concurrency
+    db.conn.execute('PRAGMA journal_mode = WAL')
+    return db
+```
+
+### [LOW]
+
+**Finding ID**: ASVS-1326-LOW-001
+
+**Title**: Ad-hoc database connections opened in request handlers without connection lifecycle management
+
+**File**: `v3/server/pages.py`, multiple locations
+
+**Vulnerable Code**:
+```python
+# Line 233 - in vote_on_page:
+pdb = steve.persondb.PersonDB.open(DB_FNAME)
+
+# Line 295 - in admin_page:
+pdb = steve.persondb.PersonDB.open(DB_FNAME)
+
+# Line 435 - in do_open_endpoint:
+pdb = steve.persondb.PersonDB.open(DB_FNAME)
+
+# Line 567 - in serve_doc:
+db = steve.election.Election.open_database(DB_FNAME)
+```
+
+**Impact**: Multiple database connections are opened per request without explicit closing or connection pooling. Comments acknowledge this issue: `### should open/keep a PersonDB instance in the APP`.
+
+**Remediation**: Implement a connection pool or application-level singleton for database access with proper lifecycle management.
+
+### Security Controls Inventory for 13.2.6
+
+| Control | Location | Coverage Status |
+|---------|----------|-----------------|
+| Connection timeout | Not configured | **MISSING** |
+| Max parallel connections | Not configured | **MISSING** |
+| Connection pooling | Not implemented | **MISSING** (acknowledged in comments) |
+| Retry strategy | Not implemented | **MISSING** |
+| Connection lifecycle | No explicit close in handlers | **MISSING** |
+| Transaction management | `election.py` lines 55-66, 122-133 | Applied for multi-step operations |
+
+### Positive Patterns for 13.2.6
+
+1. **Explicit transactions**: Multi-step operations (delete, add_salts) use `BEGIN TRANSACTION`/`COMMIT` for atomicity.
+2. **Connection cleanup on delete**: `self.db.conn.close()` is called when an election is deleted (line 67).
+3. **Integrity error retry**: ID generation retries on `sqlite3.IntegrityError` (lines 170-177, 378-384).
+
+---
+
+
+
+## Cross-cutting Architecture Observations
+
+1. **Authentication without Authorization**: The application has robust authentication (via `asfquart.auth.require`) but authorization is largely unimplemented. Multiple `### check authz` placeholders throughout `pages.py` mean any authenticated committer can manage any election. This impacts the backend communication security posture because it means the application's internal access control doesn't properly protect backend resources.
+
+2. **Local-First Architecture**: The application uses SQLite (local file database) rather than remote services. This significantly reduces the attack surface for ASVS 13.2.x requirements about backend communication, as there are no remote database credentials, API keys, or network connections to external services to protect.
+
+3. **Cryptographic Material Lifecycle**: The application has a well-designed cryptographic lifecycle (salt generation → key derivation → vote encryption) but all material resides in the same SQLite file. There's no separation of privilege between the application accessing election metadata and accessing cryptographic secrets.
+
+4. **Single Process Model**: The application appears to run as a single Quart process, connecting to local SQLite. This means connection configuration (13.2.6) is less critical than in distributed architectures, but still relevant for concurrency handling.
+
+5. **Defense in Depth Gap**: While queries are properly parameterized (SQL injection protection) and sensitive data is filtered at the API layer, the single-layer design means a compromise at the application level exposes all secrets simultaneously.
+
+---
+
+## Cross-cutting Recommendations
+
+### Immediate (Critical/High Priority)
+
+1. **Implement secrets management**: Integrate a key vault (e.g., HashiCorp Vault) to store `opened_key` values separately from the election database. At minimum, enable SQLite encryption (SQLCipher) for the database file.
+
+2. **Restrict `__getattr__` proxy**: Limit the Election class's attribute proxy to only expose a defined set of public operations, preventing unintended access to raw database cursors that return sensitive columns.
+
+### Short-term (Medium Priority)
+
+3. **Document and configure connection behavior**: Add SQLite `PRAGMA busy_timeout`, WAL mode, and explicit connection lifecycle management. Document expected concurrency limits.
+
+4. **Implement file serving allowlist**: Add file extension and name validation to `serve_doc()` to define permitted document types.
+
+5. **Add database encryption at rest**: Use SQLCipher or similar to encrypt the SQLite database, ensuring that file system access alone cannot expose secrets.
+
+### Long-term (Architecture)
+
+6. **Separate secrets storage**: Move cryptographic material (election salts, opened_keys) to a dedicated secrets store with access control, audit logging, and key rotation capabilities.
+
+7. **Implement connection pooling**: Replace ad-hoc `open_database()` calls with an application-level connection pool with documented configuration for timeouts, max connections, and retry behavior.
+
+8. **Add outbound request allowlist**: If the application evolves to include email notifications or external integrations (suggested by `get_voters_for_email()`), implement an allowlist of permitted outbound destinations at the application and network layers.
+        
\ 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