T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/save_paper.py:24
- Finding
- Exposed Zotero API Credential in Source Code<![CDATA[ ## Vulnerability Details **File Location**: `scripts/save_paper.py`, line 24 **Vulnerability Type**: Hardcoded secret and incorrect environment-variable lookup **Risk Level**: High ### Vulnerable Code ```python zotero_creds = os.environ.get('19883603:YtIe0tqZtA12wBvFDTB8EIRR') # ID:KEY if zotero_creds and ':' in zotero_creds: try: parts = zotero_creds.strip().split(':') if len(parts) == 2: library_id = parts[0].strip() api_key = parts[1].strip() except: pass ``` ### Technical Analysis The argument passed to `os.environ.get()` is a credential-shaped value containing a Zotero user ID and API key rather than the documented environment-variable name, `ZOTERO_CREDENTIALS`. Consequently: 1. A likely Zotero API credential is exposed to anyone who can read the source code, package, repository history, build logs, or distributed artifact. 2. The application does not read the documented `ZOTERO_CREDENTIALS` variable. 3. Authentication normally fails unless the process environment contains a variable whose name is the entire embedded credential string. The exposed key's actual permissions cannot be established from the audited files. However, the application expects credentials capable of searching a Zotero library, creating items and notes, and uploading attachments. ### Attack Path 1. An attacker obtains a copy of the source package or accesses its repository history. 2. The attacker extracts the embedded Zotero user ID and API key from line 24. 3. The attacker submits the credential to the Zotero API. 4. If the key remains valid, the attacker reads or modifies resources allowed by its configured Zotero permissions. 5. For a write-enabled key, the attacker may create unwanted records or attachments and corrupt the associated library's integrity. ### Impact Assessment A valid exposed key could permit unauthorized access to the associated Zotero account or library within the key's configured scop ...[truncated 344 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Revoke the exposed Zotero API key immediately and issue a replacement with the minimum necessary permissions. 2. Remove the credential from the current source and repository history. 3. Correct the lookup: ```python zotero_creds = os.environ.get("ZOTERO_CREDENTIALS") ``` 4. Validate the credential using a bounded split and reject empty components: ```python zotero_creds = os.environ.get("ZOTERO_CREDENTIALS", "") try: library_id, api_key = (part.strip() for part in zotero_creds.split(":", 1)) except ValueError: library_id = api_key = "" if not library_id or not api_key: raise SystemExit("ZOTERO_CREDENTIALS must use the userID:apiKey format") ``` 5. Store production secrets in a secret manager or protected runtime environment rather than source files. 6. Enable automated secret scanning in source-control and CI pipelines. 7. Review Zotero access logs and library changes for unauthorized activity involving the exposed key. ]]>
