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/21 23:41:48 UTC
(tooling-agents) branch main updated: ASVS L3 audit: 10.7.1 (authentication_and_session)
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 801e28c ASVS L3 audit: 10.7.1 (authentication_and_session)
801e28c is described below
commit 801e28c10c900b34c7f4766973820855e6bbf0ee
Author: ASF Tooling Team <ro...@apache.org>
AuthorDate: Wed Apr 22 01:41:43 2026 +0200
ASVS L3 audit: 10.7.1 (authentication_and_session)
---
.../d0aa7e9/authentication_and_session/10.7.1.md | 228 +++++++++++++++++++++
1 file changed, 228 insertions(+)
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.7.1.md b/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.7.1.md
new file mode 100644
index 0000000..e983b6b
--- /dev/null
+++ b/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.7.1.md
@@ -0,0 +1,228 @@
+# ASVS 10.7.1 Security Audit Report
+
+## Executive Summary
+
+- **Repository:** apache/steve
+- **Audit Date:** Apr 21, 2026
+- **Auditor:** Tooling Agents
+- **ASVS Requirement:** 10.7.1 — Verify that the authorization server ensures that the user consents to each authorization request. If the identity of the client cannot be assured, the authorization server must always explicitly prompt the user for consent.
+- **Level:** 2
+- **Section:** Consent Management
+- **Files Analyzed:** 3 relevant out of 3 total, 0 skipped
+
+### Finding Summary
+
+| Severity | Count | Status |
+|----------|-------|--------|
+| Critical | 0 | ✓ |
+| High | 0 | ✓ |
+| Medium | 1 | ⚠️ |
+| Low | 0 | ✓ |
+
+### Context
+
+This application is an **OAuth client** delegating authentication to an external authorization server (`oauth.apache.org`). The audit focuses on how the client configures and participates in the OAuth flow with respect to consent enforcement. One significant finding was identified where the OAuth configuration deliberately bypasses OIDC (which provides standardized consent mechanisms) and omits all consent-enforcing parameters, making it impossible to verify or guarantee that the externa [...]
+
+---
+
+## Security Controls Inventory
+
+| Control | Defined | Location | Applied | Coverage |
+|---------|---------|----------|---------|----------|
+| OAuth URL Configuration | Yes | `main.py:38-42` | Globally | Missing consent/scope params |
+| Authentication Decorator | Yes | `asfquart.auth.require` | All protected routes | Applied consistently |
+| Session Read | Yes | `asfquart.session.read()` | `basic_info()` | Used by all handlers |
+| OIDC Support | **Deliberately Disabled** | `main.py:36` | N/A | OIDC consent flow unavailable |
+| Consent Prompt Parameter | **Not present** | N/A | N/A | No coverage |
+| Scope Parameter | **Not present** | N/A | N/A | No coverage |
+
+---
+
+## Critical File Review
+
+### `v3/server/main.py` — OAuth Configuration
+
+| Line | Code | Consent Relevance | Status |
+|------|------|-------------------|--------|
+| 36 | `# Avoid OIDC` | Disables OIDC consent mechanisms | ⚠️ Finding |
+| 38–39 | `OAUTH_URL_INIT = '...?state=%s&redirect_uri=%s'` | No `prompt`, `scope`, or `client_id` params | ⚠️ Finding |
+| 41 | `OAUTH_URL_CALLBACK = '...?code=%s'` | Token exchange — no consent verification | ⚠️ Observation |
+
+### `v3/server/pages.py` — Session Consumption
+
+| Line | Code | Consent Relevance | Status |
+|------|------|-------------------|--------|
+| 90–93 | `s = await asfquart.session.read()` | Consumes session without checking how consent was obtained | ℹ️ Observation |
+| 103 | `basic.csrf_token = 'placeholder'` | Acknowledged tech debt, not consent-related | N/A (excluded) |
+
+### `v3/server/bin/asf-load-ldap.py` — Not Relevant
+
+This script populates voter eligibility from LDAP. It does not participate in the OAuth flow and has no consent management responsibilities.
+
+---
+
+## Findings
+
+### Medium Severity
+
+#### ASVS-1071-MED-001: Missing Consent Enforcement Parameters in OAuth Authorization Flow
+
+| Attribute | Detail |
+|-----------|--------|
+| **Severity** | **MEDIUM** |
+| **Gap Type** | Type A — No consent-enforcing control exists in the OAuth flow |
+| **File** | `v3/server/main.py` |
+| **Function** | `create_app()` |
+| **Lines** | 36–42 |
+| **Related Functions** | OAuth initialization in `asfquart.generics` |
+
+**Description:**
+
+The OAuth authorization URL configuration omits all consent-enforcing parameters and explicitly disables OIDC support. This makes it impossible to verify or guarantee that the external authorization server prompts users for consent on each authorization request.
+
+**Vulnerable Code:**
+
+```python
+# Avoid OIDC
+import asfquart.generics
+
+asfquart.generics.OAUTH_URL_INIT = (
+ 'https://oauth.apache.org/auth?state=%s&redirect_uri=%s'
+)
+asfquart.generics.OAUTH_URL_CALLBACK = 'https://oauth.apache.org/token?code=%s'
+```
+
+**Data Flow:**
+
+1. `create_app()` configures OAuth authorization URL → no `prompt`, `consent_prompt`, or `scope` parameters included
+2. Comment explicitly states `# Avoid OIDC` — removes access to the standardized `prompt=consent` mechanism defined in OpenID Connect Core §3.1.2.1
+3. When `asfquart` redirects a user to the AS for authorization, the AS receives no instruction to prompt for consent
+4. The AS (`oauth.apache.org`) may silently issue tokens for returning users without displaying a consent screen
+5. No application-side verification that consent was actually obtained during the callback
+
+**Why This Matters:**
+
+ASVS 10.7.1 requires consent for each authorization request. The second clause states: *"If the identity of the client cannot be assured, the authorization server must always explicitly prompt the user for consent."* Since the OAuth URL template contains no `client_id` and no `prompt` parameter, the client relies entirely on the AS's default behavior. Without OIDC's `prompt=consent`, there is no standardized mechanism to:
+
+- Request the AS to display a consent screen
+- Verify via the ID token or token response that consent was freshly granted
+- Distinguish between a first-time authorization and a silently re-issued token
+
+For a voting system, silent re-authorization without explicit consent could enable scenarios where a user's browser is redirected through the OAuth flow (e.g., via CSRF on the login initiation endpoint) and obtains a valid session without the user's awareness.
+
+**Proof of Concept:**
+
+If an attacker can trigger a navigation to the OAuth init URL for a user who previously authorized the application:
+
+```
+https://oauth.apache.org/auth?state=ATTACKER_STATE&redirect_uri=https://steve.apache.org/callback
+```
+
+The AS may complete the flow silently (no consent prompt), issuing a code that gets exchanged for a session. The user may not realize a new session was established.
+
+**Impact:**
+
+- Users may be authorized without being aware of individual authorization events
+- No audit trail distinguishing user-initiated vs. silently-completed OAuth flows
+- Reduced user agency over their delegated authorization
+- Potential for unauthorized session establishment in a voting system
+
+**Remediation:**
+
+Switch to OIDC (or add consent parameters if the AS supports them in plain OAuth):
+
+```python
+def create_app():
+ import asfquart.generics
+
+ # Use OIDC with explicit consent prompting
+ asfquart.generics.OAUTH_URL_INIT = (
+ 'https://oauth.apache.org/auth?'
+ 'response_type=code&'
+ 'scope=openid%20profile%20email&'
+ 'prompt=consent&'
+ 'state=%s&'
+ 'redirect_uri=%s'
+ )
+ asfquart.generics.OAUTH_URL_CALLBACK = 'https://oauth.apache.org/token?code=%s'
+
+ app = asfquart.construct('steve', app_dir=THIS_DIR, static_folder=None)
+ import pages
+ import api
+ return app
+```
+
+If OIDC adoption is not feasible, coordinate with the `oauth.apache.org` operators to confirm that consent is **always** prompted for the STeVe client registration, and document this as a compensating control.
+
+---
+
+## Positive Security Patterns
+
+1. **State parameter is included**: The OAuth init URL includes `state=%s`, which (assuming the framework validates it) protects against CSRF on the authorization callback. This is a prerequisite for meaningful consent.
+
+2. **TLS enforced on LDAP**: `ldaps://ldap-us.apache.org/` uses LDAP over TLS, protecting credential transmission.
+
+3. **Authentication decorators consistently applied**: All state-changing endpoints use `@asfquart.auth.require`, ensuring a valid session (and thus a completed OAuth flow) exists before operations proceed.
+
+4. **External AS delegation**: Using Apache's centralized OAuth service (`oauth.apache.org`) rather than a custom AS is a strong architectural choice — the consent behavior can be configured centrally for all ASF applications.
+
+---
+
+## Architecture Observations
+
+1. **Client vs. AS boundary**: This application is an OAuth **client**, not an authorization server. ASVS 10.7.1 primarily governs AS behavior. The finding reported above addresses the client's responsibility to **request** consent and to **verify** that it was obtained, which is the extent of what a client can do.
+
+2. **OIDC avoidance is a conscious decision**: The `# Avoid OIDC` comment suggests an intentional architectural choice. However, this removes access to standardized consent mechanisms (`prompt` parameter, `auth_time` claim for verifying freshness, `acr` for authentication context). The rationale for this decision should be documented.
+
+3. **First-party application context**: As an ASF application authenticating ASF members against ASF infrastructure, the consent model is arguably simpler than third-party OAuth. The AS operator and the application operator are the same organization. This reduces (but does not eliminate) the risk of unauthorized authorization.
+
+4. **Session longevity**: Session expiration configuration is not visible in the provided code. Long-lived sessions effectively bypass re-consent since users won't be redirected through the OAuth flow again. The session management configuration in `asfquart` should be reviewed to ensure session lifetimes are appropriate for a voting system.
+
+---
+
+## Recommendations Summary
+
+### Immediate Actions (Priority 1)
+
+| Recommendation | Effort | Impact |
+|----------------|--------|--------|
+| Coordinate with `oauth.apache.org` operators to confirm consent is always prompted for the STeVe client, and document this as a compensating control | Low | High |
+
+### Short-term Actions (Priority 2-3)
+
+| Recommendation | Effort | Impact |
+|----------------|--------|--------|
+| Add `prompt=login` or `prompt=consent` to the OAuth authorization URL (if supported by the AS) to ensure active user participation in each authorization | Low | High |
+| Evaluate migrating from plain OAuth to OIDC to gain access to standardized consent mechanisms, `auth_time` verification, and `prompt` parameter support | Medium | High |
+| Add `scope` parameter to the authorization URL so the consent screen (if displayed) can show the user what permissions are being requested | Low | Medium |
+
+### Long-term Actions (Priority 4-5)
+
+| Recommendation | Effort | Impact |
+|----------------|--------|--------|
+| In the OAuth callback handler (within `asfquart`), log whether the authorization was freshly consented vs. silently completed, for audit trail purposes | Medium | Medium |
+
+---
+
+## Appendix: Files Analyzed
+
+<details>
+<summary>Click to expand file list (3 files)</summary>
+
+1. **`v3/server/bin/asf-load-ldap.py`** (relevance: 10)
+ - LDAP voter eligibility population script
+ - Not relevant to OAuth consent flow
+
+2. **`v3/server/main.py`** (relevance: 10)
+ - OAuth configuration and application initialization
+ - **Contains Finding ASVS-1071-MED-001**
+
+3. **`v3/server/pages.py`** (relevance: 10)
+ - Session consumption and route handlers
+ - Uses authentication decorators consistently
+
+</details>
+
+---
+
+**End of Report**
\ 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