T05 · Unauthorized Access and Privilege Escalation
Warning
- Location
- scripts/transcribe.py:15
- Finding
- Undocumented Ancestor Credential File Access Violates Least Privilege## 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**: Medium ### Vulnerable 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.py` is 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_KEY` environment 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 1. An attacker, administrator, image builder, or unrelated application creates a readable `/.assemblyai_config.json` containin ...[truncated 1636 chars]
- Remediation
- ## Remediation Suggestions 1. Remove the ancestor-derived configuration path: ```python CONFIG_PATHS = [ Path.home() / ".assemblyai_config.json", Path.cwd() / ".assemblyai_config.json", ] ``` 2. 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") ``` 3. 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. 4. 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. 5. Emit a safe diagnostic identifying which configuration source was selected without printing the credential. 6. Document credential precedence and the fact that selected audio is transmitted to AssemblyAI before processing.
