T09 · Insecure Skill Coding Practices
- Location
scripts/extract_web.py:36- Finding
Server-Side Request Forgery Through Unrestricted URL Fetching
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill does what it says, but its unrestricted web fetching and unsanitized Excel export create risks users should review before installing.
Install only if you are comfortable letting the skill read the PDFs/folders you provide, contact Crossref for DOI verification, and fetch supplied web URLs from the agent runtime. Avoid using it on sensitive networks until URL validation and Excel formula escaping are added, and prefer pinned dependency versions for repeatable installs.
scripts/extract_web.py:36Server-Side Request Forgery Through Unrestricted URL Fetching
scripts/excel_writer.py:59Spreadsheet Formula Injection in Generated Excel Reconciliation Files
The documented behavior promises web collection, PDF and folder processing, Crossref verification, RIS/XML generation, and Excel reconciliation, but the analyzed implementation reportedly only supports much narrower citation formatting behavior. This mismatch is dangerous because users and orchestrators may trust the skill to have performed validation, extraction, and import preparation that never actually occurred, leading to silent integrity failures, incorrect bibliographic records, and unsafe workflow decisions based on false assurances.
The skill advertises operations that require reading local files and accessing web resources, but it does not declare any explicit tool scope or permissions boundary. This creates an authorization ambiguity where an agent may invoke broader file_read or network capabilities than a reviewer or user expects, increasing the risk of unintended local file access or outbound data exposure when handling PDF paths, folders, and URLs.
The display name, short description, and default prompt are all written in Chinese, indicating a language-specific skill experience. There is no visible indication that users can choose another language or that the Chinese-only presentation is required for a documented region-specific purpose.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
## Endpoint
`GET https://api.crossref.org/works/{DOI}`
Returns JSON with a `message` object. No API key is required for basic queries (polite pool).
The failure-handling instructions require marking results as 待人工确认, which imposes a specific language choice in the skill documentation. This is a natural-language locale policy issue because the file does not offer a user language choice or explain a justified region-specific requirement.
The function transmits the provided DOI to the external Crossref service, which creates a data-flow from local processing to a third party. In this skill context, DOI values are usually public identifiers, so risk is limited, but if users supply sensitive or proprietary reference metadata, this can leak usage patterns or confidential identifiers to an external service without explicit consent or configuration control.
"""Query Crossref for a DOI. Returns a normalized dict or None."""
if not doi:
return None
url = f"https://api.crossref.org/works/{requests.utils.quote(doi, safe='')}"
try:
r = requests.get(url, headers=UA, timeout=20)
except requests.RequestException:
The docstring defines the returned check_result values exclusively as Chinese strings: '已修正 / 原样正确 / 待人工确认'. This enforces a specific language in user-visible output without any opt-in or indication that the skill is intentionally limited to a Chinese-language context.
Strings appended to the notes list, such as correction messages and manual-review notices, are all written in Chinese. Because these messages are part of the returned record, they are user-facing behavior that imposes a locale choice without offering alternatives or documenting a justified locale restriction.
The workbook headers and worksheet title are hard-coded in Chinese, which imposes a specific language/locale on output. There is no indication in this file that users can opt into that locale or that the skill is explicitly limited to a Chinese-language context.
The worksheet title '文献对账表' enforces a Chinese locale in generated output. The file does not provide any language selection mechanism or justification that the skill is region- or language-specific.
The instructions tell users to verify imported records against a spreadsheet using Chinese column/file names (文献对账表.xlsx, 核对结果) without indicating that this is locale-specific or offering an alternative. This creates a natural-language locale assumption that may not fit users outside that language context.
The dependency is specified with a minimum version only, which allows builds to resolve to different future releases over time. This weakens supply-chain reproducibility and makes it difficult to ensure that a known-safe version of requests is consistently installed, especially for a skill that fetches remote web content.
requests>=2.28
beautifulsoup4>=4.11
pypdf>=3.9
openpyxl>=3.1
Requests has multiple known advisories, and because the manifest does not pin a version, there is no way to verify that deployed environments avoid affected releases. In a skill that retrieves data from remote web pages, this uncertainty increases the chance of credential leakage, TLS/verification issues, or other network-security weaknesses depending on the resolved version.
Using an unpinned beautifulsoup4 version means the installed package may vary between environments or over time, reducing reproducibility and increasing supply-chain risk. While not an immediate exploit by itself, it can silently introduce breaking or vulnerable transitive behavior in future installs.
requests>=2.28
beautifulsoup4>=4.11
pypdf>=3.9
openpyxl>=3.1
The unpinned pypdf dependency is more concerning in this skill because the tool processes untrusted PDF files, a common attack surface for parser bugs and denial-of-service issues. Allowing arbitrary future versions makes it impossible to verify whether the installed release contains known parsing vulnerabilities or regressions.
requests>=2.28
beautifulsoup4>=4.11
pypdf>=3.9
openpyxl>=3.1
Pypdf has several advisories related to malformed PDF handling and potential excessive runtime or memory consumption, and the unpinned requirement prevents verification that a safe version is installed. Given this skill explicitly ingests PDFs from users or folders, the context makes parser vulnerabilities materially more dangerous than in a non-PDF-processing tool.
An unpinned openpyxl dependency creates non-reproducible installs and makes it hard to guarantee protection from historical XML-related issues. Since this skill generates Excel reconciliation files, dependency drift could introduce insecure parsing or output-handling behavior in future releases.
requests>=2.28
beautifulsoup4>=4.11
pypdf>=3.9
openpyxl>=3.1
Openpyxl has historical advisories involving XML external entity handling, and the lack of version pinning means the actual installed version may be vulnerable without visibility. In this skill the exposure is somewhat limited because openpyxl appears intended for generating reconciliation sheets, but risk remains if any workbook parsing or XML handling occurs.
The module docstring explicitly states the skill is for "Chinese + English" citation formatting. Under the policy rule for natural-language constraints, this is a language/locale limitation presented without any indication of user choice, opt-in, or documented justification for restricting the skill to those languages.
The function performs a file write via wb.save(path), which can modify user data on disk. In this file there is no confirmation prompt, logging/print statement, or inline warning/comment disclosing that behavior to the user.
No suspicious patterns detected.