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/04/22 15:16:08 UTC

(tooling-agents) branch main updated: ASVS L3 audit: 7.1.2 (ch07_general)

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 7123b24  ASVS L3 audit: 7.1.2 (ch07_general)
7123b24 is described below

commit 7123b2499d06c865fec2a0a98d063daa6373a61a
Author: ASF Tooling Team <ro...@apache.org>
AuthorDate: Wed Apr 22 17:16:02 2026 +0200

    ASVS L3 audit: 7.1.2 (ch07_general)
---
 .../reports/steve/v3/d0aa7e9/ch07_general/7.1.2.md | 324 +++++++++++++++++++++
 1 file changed, 324 insertions(+)

diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.1.2.md b/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.1.2.md
new file mode 100644
index 0000000..dcda708
--- /dev/null
+++ b/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.1.2.md
@@ -0,0 +1,324 @@
+# ASVS 7.1.2 Security Audit Report
+
+## Executive Summary
+
+- **Repository:** apache/steve
+- **Audit Date:** Apr 22, 2026
+- **Auditor:** Tooling Agents
+- **ASVS Requirement:** 7.1.2 — Verify that the documentation defines how many concurrent (parallel) sessions are allowed for one account as well as the intended behaviors and actions to be taken when the maximum number of active sessions is reached.
+- **ASVS Level:** 2
+- **Section:** Session Management Documentation
+- **Files Analyzed:** 3 relevant out of 49 total, 12 skipped
+
+### Finding Counts
+
+| Severity | Count |
+|----------|-------|
+| Critical | 0 |
+| High | 0 |
+| Medium | 1 |
+| Low | 0 |
+| **Total** | **1** |
+
+### Summary
+
+This audit evaluated the Apache Steve voting/election management system against ASVS requirement 7.1.2, which mandates documented policies and enforcement for concurrent session limits. The application completely lacks any concurrent session management controls, policy documentation, or enforcement mechanisms. While the application implements strong authentication decorators and role-based access controls, it has no visibility into how many parallel sessions exist per user account and no [...]
+
+---
+
+## Security Controls Inventory
+
+### Session Management Controls Found
+
+| Control | Location | Status | Notes |
+|---------|----------|--------|-------|
+| Session reading | `pages.py:75` — `asfquart.session.read()` | Present | Reads session uid, fullname, email |
+| Authentication decorators | `pages.py` — `@asfquart.auth.require` | Present | Applied to 17+ endpoints |
+| OAuth integration | `main.py:35-38` | Present | Apache OAuth for authentication |
+| Concurrent session tracking | Not found | **ABSENT** | No code tracks active sessions per user |
+| Concurrent session limits | Not found | **ABSENT** | No maximum session count defined or enforced |
+| Session enumeration per user | Not found | **ABSENT** | No ability to list a user's active sessions |
+| Session revocation on limit | Not found | **ABSENT** | No behavior defined when limit is exceeded |
+| Session management UI | `pages.py:547-560` — profile/settings pages | **Skeleton only** | No session management functionality |
+| Session policy documentation | Not found | **ABSENT** | No documented concurrent session policy |
+
+---
+
+## Critical File Review
+
+### `v3/server/pages.py` — Session Handling Entry Points
+
+| Entry Point | Auth | Session Read | Concurrent Session Check | Gap |
+|-------------|------|-------------|------------------------|-----|
+| `basic_info()` (called by all handlers) | N/A | ✅ `asfquart.session.read()` | ❌ None | Type A |
+| `voter_page()` | ✅ committer | Via `basic_info()` | ❌ None | Type A |
+| `do_vote_endpoint()` | ✅ committer | Via `basic_info()` | ❌ None | Type A |
+| `do_create_endpoint()` | ✅ pmc_member | Via `basic_info()` | ❌ None | Type A |
+| `do_open_endpoint()` | ✅ committer | Via `basic_info()` | ❌ None | Type A |
+| `do_close_endpoint()` | ✅ committer | Via `basic_info()` | ❌ None | Type A |
+| `admin_page()` | ✅ committer | Via `basic_info()` | ❌ None | Type A |
+| `profile_page()` | ✅ session | Via `basic_info()` | ❌ None | Type A |
+| `settings_page()` | ✅ session | Via `basic_info()` | ❌ None | Type A |
+
+### `v3/server/main.py` — Application Configuration
+
+| Configuration Aspect | Present | Notes |
+|---------------------|---------|-------|
+| OAuth URLs | ✅ | Hardcoded Apache OAuth endpoints |
+| TLS configuration | ✅ | Optional cert/key from config |
+| Session max count | ❌ | Not configured |
+| Session timeout | ❌ | Not visible in available code |
+| Session cookie config | ❌ | Not visible in available code |
+
+---
+
+## Findings
+
+### Medium Severity
+
+#### ASVS-712-MED-001: Complete Absence of Concurrent Session Limit Policy and Enforcement
+
+| Attribute | Value |
+|-----------|-------|
+| **Severity** | MEDIUM |
+| **Gap Type** | Type A — Entry point with NO control |
+| **ASVS Requirement** | 7.1.2 |
+| **Affected Files** | `v3/server/pages.py`, `v3/server/main.py` |
+| **Related Functions** | `basic_info()`, `profile_page()`, `settings_page()`, application initialization |
+
+**Description:**
+
+The application has no documented policy, configuration, or code to define or enforce how many concurrent (parallel) sessions are permitted for a single user account. For a voting/election management system where session integrity directly impacts the trustworthiness of votes and administrative actions, this is a significant gap.
+
+**Evidence — Session read with no concurrent session awareness (`pages.py:70-87`):**
+
+```python
+async def basic_info():
+    """Return base-level EZT template data."""
+    # ...
+    s = await asfquart.session.read()
+    if s:
+        basic.update(
+            uid=s['uid'],
+            name=s['fullname'],
+            email=s['email'],
+        )
+    else:
+        # No session.
+        basic.update(
+            uid=None,
+            name=None,
+            email=None,
+        )
+
+    ### generate a real token and store in the session
+    basic.csrf_token = 'placeholder'
+
+    return basic
+```
+
+The session is read and consumed with no check against any session registry or count. There is no session ID tracking, no session store enumeration, and no enforcement logic.
+
+**Evidence — Application initialization with no session configuration (`main.py:39-41`):**
+
+```python
+    app = asfquart.construct('steve', app_dir=THIS_DIR, static_folder=None)
+
+    # Now that we have an APP, import modules that will add page
+    # and API endpoints into the APP.
+    import pages  # noqa: F401
+    import api  # noqa: F401
+```
+
+No session management parameters (max sessions, timeout policy, concurrent session behavior) are configured during application setup.
+
+**Evidence — Profile/Settings pages with no session management (`pages.py:547-560`):**
+
+```python
+@APP.get('/profile')
+@asfquart.auth.require
+@APP.use_template(TEMPLATES / 'profile.ezt')
+async def profile_page():
+    result = await basic_info()
+    result.title = 'Profile'
+    return result
+
+@APP.get('/settings')
+@asfquart.auth.require
+@APP.use_template(TEMPLATES / 'settings.ezt')
+async def settings_page():
+    result = await basic_info()
+    result.title = 'Settings'
+    return result
+```
+
+These pages exist but contain no session enumeration, session listing, or session termination capabilities for the user.
+
+**Missing Controls (comprehensive search):**
+
+1. **No session count tracking**: No database table, in-memory store, or external service tracks how many sessions exist per `uid`.
+2. **No session limit constant/configuration**: No `MAX_SESSIONS`, `SESSION_LIMIT`, or equivalent is defined anywhere in the codebase.
+3. **No enforcement action**: No code path exists to revoke oldest sessions, deny new login, or notify the user when multiple sessions exist.
+4. **No session listing endpoint**: Users cannot view their active sessions.
+5. **No session revocation endpoint**: Users cannot terminate other active sessions.
+6. **No documentation**: No policy document, configuration comment, or code comment defines the intended concurrent session behavior.
+
+**Data Flow:**
+
+```
+User Authentication (OAuth) → asfquart.session.read() → Session consumed
+                                      ↓
+                              No registry check
+                              No count verification
+                              No limit enforcement
+                                      ↓
+                              Unlimited parallel sessions possible
+```
+
+**Proof of Concept:**
+
+An attacker who compromises user credentials can:
+
+1. Authenticate and establish Session A
+2. Authenticate again and establish Session B
+3. Authenticate again and establish Session C
+4. Continue indefinitely with no system intervention
+5. All sessions remain valid simultaneously
+6. Legitimate user has no visibility into parallel sessions
+7. No alerts or logging of unusual concurrent session patterns
+
+**Impact:**
+
+In this election/voting system:
+
+- A compromised account can have unlimited parallel sessions, making detection of account takeover difficult.
+- An attacker who obtains session credentials can maintain access indefinitely alongside the legitimate user without any alert or forced session management.
+- During critical voting windows (the `S_OPEN` election state), there is no mechanism to ensure a single authenticated presence per voter, which could complicate forensic analysis if vote integrity is questioned.
+- Administrative endpoints (`/do-open/<eid>`, `/do-close/<eid>`, `/do-create-election`) are accessible from unlimited concurrent sessions, increasing the attack surface for privileged operations.
+
+**Remediation:**
+
+1. **Document the policy** — Create a session management policy defining:
+   - Maximum concurrent sessions per account (e.g., 3 for regular users, 1 during active voting)
+   - Behavior when the limit is reached (e.g., terminate oldest session, or deny new login)
+   - Any role-specific limits (e.g., election administrators vs. voters)
+
+2. **Implement session tracking:**
+
+```python
+# Example: Server-side session registry
+import time
+
+class SessionRegistry:
+    """Tracks active sessions per user for concurrent session management."""
+    
+    MAX_CONCURRENT_SESSIONS = 3  # Documented policy decision
+    
+    def __init__(self, db):
+        self.db = db
+    
+    def register_session(self, uid: str, session_id: str) -> bool:
+        """Register a new session. Returns True if allowed, False if limit exceeded."""
+        active = self.get_active_sessions(uid)
+        
+        if len(active) >= self.MAX_CONCURRENT_SESSIONS:
+            # Policy: revoke oldest session
+            oldest = min(active, key=lambda s: s['created_at'])
+            self.revoke_session(oldest['session_id'])
+            _LOGGER.warning(
+                f'User[U:{uid}] exceeded max sessions ({self.MAX_CONCURRENT_SESSIONS}). '
+                f'Revoked oldest session.'
+            )
+        
+        self.db.c_register_session.perform(session_id, uid, int(time.time()))
+        return True
+    
+    def get_active_sessions(self, uid: str) -> list:
+        """Return all active sessions for a user."""
+        self.db.q_active_sessions.perform(uid)
+        return list(self.db.q_active_sessions.fetchall())
+    
+    def revoke_session(self, session_id: str):
+        """Revoke a specific session."""
+        self.db.c_revoke_session.perform(session_id)
+```
+
+3. **Integrate into authentication flow** — Check session count at login and at `basic_info()`.
+
+4. **Add session management UI** — Populate the existing `/settings` page with session listing and revocation controls.
+
+---
+
+## Positive Security Patterns
+
+| Pattern | Location | Assessment |
+|---------|----------|------------|
+| Consistent authentication decorators | `pages.py` — all sensitive routes | ✅ All state-changing and data-access endpoints require authentication |
+| Role-based access control | `pages.py` — `R.committer`, `R.pmc_member` | ✅ Different privilege levels for different operations |
+| Session-based identity | `basic_info()` | ✅ User identity consistently derived from session |
+| Security logging | Multiple endpoints | ✅ User actions logged with UIDs and resource IDs |
+| Parameterized queries | `election.py` via `asfpy.db` | ✅ SQL injection prevention |
+| Election state machine | `election.py` — `is_editable()`, `is_open()`, `is_closed()` | ✅ State assertions before sensitive operations |
+| Cryptographic vote integrity | `election.py` — `is_tampered()` | ✅ Anti-tamper detection via opened_key verification |
+
+---
+
+## Architecture Observations
+
+1. **Session management is delegated entirely to `asfquart`**: The application relies on the `asfquart.session` module for all session handling. No application-level session management logic exists. The framework may provide some session controls, but the application makes no effort to configure or leverage concurrent session management.
+
+2. **Voting system threat model gap**: For a voting system, concurrent session management is particularly important. If an attacker compromises a voter's credentials, they could establish a parallel session and cast votes without the legitimate user being aware. The lack of session visibility or limits means there is no detection mechanism.
+
+3. **Administrative operations at risk**: Election lifecycle operations (`open`, `close`, `create`) are protected by authentication but not by session uniqueness. An attacker maintaining a persistent session could perform administrative actions even after the legitimate admin changes their password, if session invalidation on credential change is also absent.
+
+4. **Existing infrastructure can support enhancement**: The presence of profile and settings pages provides natural locations for session management UI. The consistent use of `basic_info()` across all endpoints provides a centralized location for session validation logic.
+
+---
+
+## Recommendations Summary
+
+### Immediate Actions (0-30 days)
+
+| Priority | Recommendation | Effort | Impact | Rationale |
+|----------|---------------|--------|--------|-----------|
+| 1 | **Document concurrent session policy** — Define max sessions, behavior on limit, and role-specific rules as required by ASVS 7.1.2 | Low | High | Satisfies ASVS requirement, enables informed implementation, provides security baseline |
+
+### Short-term Actions (1-3 months)
+
+| Priority | Recommendation | Effort | Impact | Rationale |
+|----------|---------------|--------|--------|-----------|
+| 2 | **Implement server-side session registry** — Track active sessions per user with timestamps | Medium | High | Enables all session management features, provides visibility into concurrent sessions |
+| 3 | **Enforce concurrent session limits** — Apply the documented policy at login time and optionally at sensitive operations | Medium | High | Reduces risk of undetected account compromise, implements documented policy |
+| 4 | **Add session management to Settings page** — Let users view and revoke their active sessions | Medium | Medium | User self-service security, improves incident response, increases user awareness |
+
+### Long-term Actions (3-6 months)
+
+| Priority | Recommendation | Effort | Impact | Rationale |
+|----------|---------------|--------|--------|-----------|
+| 5 | **Invalidate sessions on credential change** — When a user's OAuth token or password changes, revoke existing sessions | Medium | Medium | Limits persistence after credential compromise, defense-in-depth measure |
+
+---
+
+## Appendix: Files Analyzed
+
+<details>
+<summary>Click to expand file list (3 files)</summary>
+
+### High Relevance Files
+
+- **`v3/server/pages.py`** (relevance: 8/10)
+  - Primary session handling via `basic_info()`
+  - All authenticated endpoints
+  - Profile and settings pages (skeleton session management UI)
+  
+- **`v3/steve/election.py`** (relevance: 5/10)
+  - Election state management
+  - Vote handling logic
+  - Security-sensitive operations requiring session integrity
+
+- **`v3/server/main.py`** (relevance: 4/10)
+  - Application initialization
+  - Configuration entry point
+  - OAuth integration setup
+
+</details>
\ 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