T09 · Insecure Skill Coding Practices
- Location
scripts/save_paper.py:24- Finding
Exposed Zotero API Credential in Source Code
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This Zotero helper has a coherent goal, but the shipped script contains a credential-shaped secret, does not match its credential documentation, and can automatically download and upload poorly validated URLs.
Review this carefully before installing. Use a narrowly scoped Zotero API key, rotate any key matching the exposed credential-shaped string if it is real, and avoid running the script on untrusted URLs until the credential lookup, arXiv host validation, download limits, and attachment opt-in behavior are fixed.
scripts/save_paper.py:24Exposed Zotero API Credential in Source Code
scripts/save_paper.py:91Server-Side Request Forgery Through Insufficient arXiv URL Validation
scripts/save_paper.py:2Unpinned Runtime Dependency Allows Unreviewed Package Updates
The documented behavior materially understates what the code actually does: it searches Zotero, creates notes, downloads remote PDFs from arXiv, and uploads attachments. Hidden or underdocumented network/file operations are dangerous because they can cause unintended data transfer, consume resources, and exceed the trust boundary the user believed they were granting.
The script claims to use the ZOTERO_CREDENTIALS environment variable but actually calls os.environ.get() with a hardcoded string that looks like a real Zotero userID:API-key pair. This can embed a secret identifier in source code, break expected credential handling, and may cause accidental credential disclosure or unauthorized use if the hardcoded value corresponds to a real account.
The skill uses sensitive capabilities—environment variable access for Zotero credentials and outbound network access to Zotero/arXiv—but the manifest does not declare a tool/permission scope. This weakens user consent and review because operators cannot easily see that the skill will access secrets and perform external network actions.
The skill presents itself as a Zotero save helper, but the code also fetches content from arXiv and uploads it as an attachment. This is a scope expansion beyond the stated purpose and can surprise users with extra external requests and content ingestion they did not explicitly authorize.
The manifest description is written as an instruction in Chinese and does not provide any language choice or note that the skill is region- or locale-specific. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation.
The documentation suggests only storing PDF links, but the implementation downloads the full PDF and re-uploads it to Zotero for arXiv URLs. That distinction matters because downloading and storing third-party files changes the privacy, bandwidth, storage, and content-handling risk profile.
This code reads a credential-like value from the environment and uses it to authenticate to Zotero, then sends bibliographic data to a remote service. While some progress messages exist later, there is no clear warning at the point of credential access or before transmitting user-supplied paper metadata over the network.
The script automatically downloads a PDF from a URL derived from user input and uploads it to Zotero without explicit confirmation. In an agent-skill context, this creates unreviewed outbound and inbound network activity, which can be abused to fetch unexpected content, consume resources, or attach unwanted files to a user's library.
The script's CLI description, argument help, and runtime messages are all presented in Chinese, which imposes a specific language on users without opt-in or documented locale scope. This matches the policy category for language or locale constraints lacking user choice.
No suspicious patterns detected.