T05 · Unauthorized Access and Privilege Escalation
- Location
scripts/transcribe.py:15- Finding
Undocumented Ancestor Credential File Access Violates Least Privilege
- Content
View full analysis
Vulnerability Details
File Location:
scripts/transcribe.py, lines 15–19 and 26–30
Vulnerability Type: Undocumented credential discovery outside the intended configuration scope
Risk Level: MediumVulnerable Code
python CONFIG_PATHS = [ Path.home() / ".assemblyai_config.json", Path.cwd() / ".assemblyai_config.json", Path(__file__).parent.parent.parent.parent / ".assemblyai_config.json", ]python def load_api_key(): """Load API key from config file.""" for config_path in CONFIG_PATHS: if config_path.exists(): with open(config_path) as f: config = json.load(f) return config.get("api_key")Technical Analysis
The script searches for an AssemblyAI API key in three locations. The home-directory and current-working-directory paths correspond to documented configuration behavior. However, the third path is derived by traversing four parent directories from the script.
In the audited project layout,
scripts/transcribe.pyis located under the project artifact directory, and this traversal resolves to/.assemblyai_config.json. Reading a configuration file from the filesystem root is undocumented and unnecessary for the declared transcription functionality.The candidate paths are evaluated before the
ASSEMBLYAI_API_KEYenvironment variable. Consequently, any readable configuration file found at one of these locations silently overrides the caller's environment credential. The code also performs no file ownership, permission, regular-file, or symlink validation.This behavior crosses the expected configuration boundary and can cause transcription requests and audio uploads to use a credential belonging to another user, deployment, or administrative context.
Attack Path
- An attacker, administrator, image builder, or unrelated application creates a readable
/.assemblyai_config.jsoncontainin ...[truncated 1636 chars]
- An attacker, administrator, image builder, or unrelated application creates a readable
- Remediation
View remediation
Remediation Suggestions
-
Remove the ancestor-derived configuration path:
python CONFIG_PATHS = [ Path.home() / ".assemblyai_config.json", Path.cwd() / ".assemblyai_config.json", ] -
Prefer the explicitly supplied environment variable over configuration-file discovery:
python def load_api_key(): api_key = os.environ.get("ASSEMBLYAI_API_KEY") if api_key: return api_key for config_path in CONFIG_PATHS: if config_path.is_file(): with config_path.open(encoding="utf-8") as f: config = json.load(f) api_key = config.get("api_key") if api_key: return api_key raise ValueError("No AssemblyAI API key found") -
Permit configuration files only at clearly documented, intentional locations. If workspace configuration is supported, resolve it against a trusted workspace root rather than the process's arbitrary current directory.
-
On platforms that expose suitable metadata, verify that credential files:
- Are regular files rather than device nodes or directories.
- Are owned by the expected user.
- Are not writable by group or other users.
- Do not unexpectedly resolve through symbolic links.
-
Emit a safe diagnostic identifying which configuration source was selected without printing the credential.
-
Document credential precedence and the fact that selected audio is transmitted to AssemblyAI before processing.
-
