T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/helper.py:151
- Finding
- Plaintext Disclosure of Zotero API Credentials Through Diagnostic Output## Vulnerability Details **File Location**: `scripts/helper.py`, lines 15–22 and 151–154 **Vulnerability Type**: Sensitive credential exposure through plaintext logging **Risk Level**: Medium ### Vulnerable Code ```python DEFAULT_CONFIG = { "zotero_api_key": os.environ.get("ZOTERO_API_KEY", ""), "zotero_user_id": os.environ.get("ZOTERO_USER_ID", ""), "zotero_collection_key": os.environ.get("ZOTERO_COLLECTION_KEY", "U4PZ3XNP"), "obsidian_vault_path": os.environ.get("OBSIDIAN_VAULT_PATH", ""), "obsidian_folder": os.environ.get("OBSIDIAN_FOLDER", "DailyArXiv"), "arxiv_base_url": "https://arxiv.drqyq.com", "category": "PTA", } ``` ```python if __name__ == "__main__": print("Arxiv-Zotero-Obsidian Helper Script") print("=" * 40) print(f"Default config: {json.dumps(DEFAULT_CONFIG, indent=2)}") ``` ### Technical Analysis `DEFAULT_CONFIG` stores the live value of the `ZOTERO_API_KEY` environment variable alongside the Zotero user ID and local Obsidian vault path. When the helper is executed directly, the entire dictionary is serialized to JSON and printed without redaction. Although reading the API key is necessary for the declared Zotero synchronization function, disclosing it through standard output is not necessary and exceeds minimum information exposure. Standard output may be retained in CI/CD logs, agent transcripts, terminal recordings, monitoring platforms, scheduled-task logs, or diagnostic reports. The audit found that normal API use sends the key in the `Zotero-API-Key` header exclusively over HTTPS to the official `api.zotero.org` endpoint. No evidence was found that the key, vault contents, notes, or environment data are transmitted to an unrelated network destination. The vulnerability is therefore the local plaintext output of the credential rather than unauthorized network exfiltration. ### Attack Path 1. A user configures `ZOTERO_A ...[truncated 1380 chars]
- Remediation
- ## Remediation Suggestions 1. Remove the complete configuration dump from the `__main__` block. 2. If diagnostic output is required, construct an explicit allowlist of non-sensitive fields rather than serializing the full configuration object. 3. Always replace the API key with a fixed marker such as `[REDACTED]`; do not reveal prefixes, suffixes, or key length. 4. Avoid printing local vault paths, user identifiers, and collection keys unless they are essential for a specific diagnostic operation. 5. Use a logging framework with centralized secret-redaction controls and ensure production logging does not run at a level that exposes configuration details. 6. Revoke and rotate any Zotero API key that may already have appeared in logs or transcripts. 7. Review and delete retained logs containing the exposed configuration where operationally possible. 8. Configure the Zotero key with only the permissions needed to create the intended items and attachments, and use a dedicated key for this Skill when possible. A safe diagnostic pattern would be: ```python if __name__ == "__main__": safe_config = { "zotero_api_key": "[REDACTED]" if DEFAULT_CONFIG["zotero_api_key"] else "", "category": DEFAULT_CONFIG["category"], "obsidian_folder": DEFAULT_CONFIG["obsidian_folder"], "arxiv_base_url": DEFAULT_CONFIG["arxiv_base_url"], } print("Arxiv-Zotero-Obsidian Helper Script") print("=" * 40) print(f"Configuration: {json.dumps(safe_config, indent=2)}") ```
