-
Notifications
You must be signed in to change notification settings - Fork 22
Closed
Labels
ASVSAnything related to ASVS requirementsAnything related to ASVS requirementsL1ASVS L1 requirementASVS L1 requirementcriticalCritical issueCritical issuesecurityIssues related to security postureIssues related to security posture
Description
Summary
Web sessions can remain valid indefinitely with continued activity. The application uses sliding session expiration only, with no absolute maximum lifetime enforced. This allows compromised sessions unlimited exploitation windows.
ASVS Requirements
- 7.3.2 - Verify that there is an absolute maximum session lifetime such that re-authentication is enforced
Related Audit Reports
- 7.3.2.md - ASVS-732-CRIT-001
Affected Files
atr/config.py(lines 70-74) - Missing lifetime configurationatr/server.py- Session initializationatr/web.py-Committerclass lacks age validationtypestubs/asfquart/session.pyi- External library interface
Current Behavior
# atr/config.py lines 70-74
class AppConfig:
SESSION_COOKIE_SECURE = True
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_SAMESITE = "Strict"
SESSION_COOKIE_NAME = "__Host-session"
# MISSING: No SESSION_PERMANENT_LIFETIME or absolute timeout
# typestubs/asfquart/session.pyi - confirms sliding expiration only
async def read(expiry_time=..., app=...) -> typing.Optional[ClientSession]:
"""Fetches a cookie-based session if found (and valid), and updates the last access timestamp
for the session."""
...Risk
- Sessions with continued activity remain valid indefinitely
- Compromised sessions cannot be limited by time-based controls
- Session fixation or hijacking attacks have unlimited exploitation windows
- Violates compliance requirements (PCI-DSS, SOC2, ASVS)
Recommended Fix
# Option 1: Application-layer enforcement in atr/web.py
from datetime import timedelta, datetime, UTC
from typing import Final
MAX_SESSION_LIFETIME_HOURS: Final[int] = 72
class Committer:
def __init__(self, web_session: session.ClientSession) -> None:
self.session = web_session
self._validate_session_lifetime()
def _validate_session_lifetime(self) -> None:
session_created = getattr(self.session, 'created_at', None)
if session_created is None:
raise base.ASFQuartException("Session expired", errorcode=401)
if (datetime.now(UTC) - session_created) > timedelta(hours=MAX_SESSION_LIFETIME_HOURS):
raise base.ASFQuartException("Session expired", errorcode=401)
# Option 2: Add to atr/config.py
ABSOLUTE_SESSION_MAX_SECONDS: Final[int] = 28800 # 8 hoursAcceptance Criteria
- Session creation timestamp stored in session metadata
- Maximum session lifetime configured (recommend 8 hours)
- Age validation performed on every authenticated request
- Expired sessions redirected to login with
?reason=session_expired - Re-authentication enforced after maximum lifetime exceeded
- Configuration documented in security documentation
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
ASVSAnything related to ASVS requirementsAnything related to ASVS requirementsL1ASVS L1 requirementASVS L1 requirementcriticalCritical issueCritical issuesecurityIssues related to security postureIssues related to security posture