Back to skill

Security audit

Oil Price Monitor

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its oil-price monitoring purpose, but unsafe adjacent Python imports and an unnecessary subprocess stub make it worth manual Review before installing.

Review before installing. Only run it in an environment where the skills directory is not writable by less-trusted code, verify the chinese-workdays dependency, pin or lock Python dependencies, and consider removing the subprocess search stub. Also confirm that stdout announcements are the intended Feishu delivery path and that you are comfortable with Chinese-only output and scheduled NDRC web requests.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (2)

T08 · Insecure Dependencies

Warning
Location
oil_price_monitor.py:18
Finding
Unsafe sibling-module resolution permits local dependency confusion<![CDATA[ ## Vulnerability Details **File Location**: `oil_price_monitor.py:18-29`; `__init__.py:8-24` **Vulnerability Type**: Local dependency confusion through unsafe `sys.path` modification **Risk Level**: Medium ### Vulnerable Code `oil_price_monitor.py:18-29`: ```python # 添加技能路径支持 workspace_skills = Path(__file__).parent.parent chinese_workdays_path = workspace_skills / 'chinese-workdays' if chinese_workdays_path.exists() and str(chinese_workdays_path) not in sys.path: sys.path.insert(0, str(chinese_workdays_path)) try: from chinese_workdays import ChineseWorkdays except ImportError as e: print("❌ 错误: 需要 chinese-workdays 技能支持") print(f" 详细错误: {e}") sys.exit(1) ``` `__init__.py:8-24`: ```python import sys from pathlib import Path # 添加 chinese-workdays 到路径 workspace_skills = Path(__file__).parent.parent if workspace_skills not in sys.path: sys.path.insert(0, str(workspace_skills)) try: from chinese_workdays import ChineseWorkdays except ImportError: # 如果在技能目录内运行,尝试相对导入 try: sys.path.insert(0, str(Path(__file__).parent.parent / 'chinese-workdays')) from chinese_workdays import ChineseWorkdays except ImportError: ChineseWorkdays = None ``` ### Technical Analysis The package prepends directories outside its own package boundary to Python's module search path and then imports `chinese_workdays` by an unverified module name. In `__init__.py`, the entire parent skills directory is trusted; in `oil_price_monitor.py`, an adjacent `chinese-workdays` directory is trusted. Python executes top-level module code during import. Consequently, a malicious `chinese_workdays.py` file or `chinese_workdays` package placed in a higher-precedence trusted directory can execute arbitrary Python code before the monitor begins its intended work. The implementation does not verify the resolved module path, package publisher, version, signature, or file digest. This does not independently grant access to an ...[truncated 1553 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Package `chinese-workdays` as a normal, reviewed Python dependency and import it without modifying `sys.path`. 2. Pin the dependency to an exact reviewed version and use hashes or signed artifacts in the deployment lock file. 3. Remove the insertion of the broad parent skills directory from `__init__.py`. 4. If cross-skill loading is unavoidable: - Resolve the expected dependency directory with `Path.resolve()`. - Reject symbolic links and paths outside a designated trusted root. - Verify the dependency files against approved cryptographic hashes. - Load the module from an exact verified file rather than performing a name-based search. - Ensure the skills directory is not writable by less-trusted users or processes. 5. After import, verify that `Path(chinese_workdays.__file__).resolve()` is located under the approved dependency directory. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
oil_price_monitor.py:197
Finding
Unvalidated remote content is forwarded into trusted Markdown notifications<![CDATA[ ## Vulnerability Details **File Location**: `oil_price_monitor.py:197-214`, `oil_price_monitor.py:223-257`, and `oil_price_monitor.py:283-285` **Vulnerability Type**: Untrusted-content and link injection in generated notifications **Risk Level**: Low ### Vulnerable Code Remote anchor extraction at `oil_price_monitor.py:197-214`: ```python if not links: links = soup.find_all('a', href=True)[:50] for link in links[:limit]: href = link.get('href', '') title = link.get_text(strip=True) if not title or len(title) < 5: continue if href.startswith('/'): href = 'https://www.ndrc.gov.cn' + href news_items.append({ 'title': title, 'url': href, 'date': self.today.strftime("%Y-%m-%d"), 'content': '' }) ``` Keyword-based acceptance at `oil_price_monitor.py:223-257`: ```python def detect_price_change(self, news: List[Dict]) -> Optional[Dict]: """检测新闻中是否包含价格调整信息""" for item in news: text = item['title'] + ' ' + item.get('content', '') keyword_hits = [kw for kw in KEYWORDS if kw in text] if not keyword_hits: continue increase = any(w in text for w in ['上调', '上涨', '提高', '增加']) decrease = any(w in text for w in ['下调', '降低', '下降', '减少']) amount_patterns = [ r'每吨[上调|下调|上涨|降低]+\s*(\d+)\s*元', r'[汽油|柴油].*?(\d{2,3})\s*元', r'调整.*?(\d{2,3})\s*元/吨' ] amount = None for pattern in amount_patterns: match = re.search(pattern, text) if match: amount = int(match.group(1)) break return { 'title': item['title'], 'date': item['date'], 'url': item['url'], 'increase': increase, 'decrease': decrease, 'amount': amount, 'raw_text': text[:300], 'keywords': keyword_hits } return None ``` Unescaped Markdown ou ...[truncated 2677 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Resolve links with `urllib.parse.urljoin(NDRC_URL, href)` rather than manually concatenating root-relative paths. 2. Parse every resolved URL with `urlsplit()` and enforce: - Scheme exactly `https`. - Hostname exactly `www.ndrc.gov.cn`, or another explicit and documented allowlist entry. - No embedded username or password. - No unexpected port. 3. Reject protocol-relative URLs, non-web schemes, malformed URLs, and external absolute URLs. 4. Escape Markdown metacharacters in remote titles and displayed URLs before creating the notification. 5. Remove the broad `find_all('a')` fallback or constrain it to a verified news-list container. 6. Fetch and validate the linked announcement page before producing a notification. Confirm its origin, publication date, document structure, and required announcement phrases. 7. Use stricter matching rules that require an oil-product term together with a clear adjustment direction and a validated amount, rather than accepting any single broad keyword. 8. Present the normalized hostname visibly in the notification and label any item that has not passed full authenticity validation as unverified. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (16)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
The documented behavior does not match the detected implementation: the skill omits the claimed Feishu push path, performs undeclared local file storage, and includes undeclared subprocess-based future-window logic. This is dangerous because hidden persistence and shell-adjacent behavior expand the attack surface and can conceal functionality that users did not authorize or expect.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
This markdown file is written entirely in Chinese, including operational instructions and warnings, with no indication that the skill is region-specific or that users may choose another language. The policy allows locale constraints when clearly documented and justified, but this file does not state such a justification within the document.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The skill description, usage examples, and output samples are entirely in Chinese, indicating the skill is intended to operate in a fixed language/locale. The file does not mention any option for users to choose another language or explicitly opt into Chinese-only behavior, which matches the policy's language/locale violation criterion.

Lp3

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding
The skill advertises networked monitoring behavior but declares no explicit tool scope or permissions despite detected capabilities for file access, network, and shell. This weakens least-privilege controls and makes it harder for reviewers or runtimes to constrain what the skill can actually do if the implementation is modified or abused.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The script's docstring, status messages, and output are consistently hard-coded in Chinese, with no option for users to select another language or locale. The policy requires flagging language or locale constraints when the skill forces a specific language without user opt-in or documented justification.

Context-Inappropriate Capability

Medium
Confidence
88% confidence
Finding
The manifest describes monitoring the NDRC website for oil price adjustment announcements, which does not inherently require launching child processes. This code invokes a separate Python interpreter via subprocess as part of a search strategy for next-year holiday notices, expanding capability beyond straightforward web monitoring.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
try:
            # 调用 multi-search-engine (通过 subprocess)
            result = subprocess.run(
                ["python3", "-c", f"""
import subprocess, json, sys
# 模拟调用 search_utils (实际需要正确导入)
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Description-Behavior Mismatch

Medium
Confidence
98% confidence
Finding
The manifest says the skill 'pushes notifications via Feishu', which is a key part of the advertised behavior. In the implementation, the main run path only fetches news, detects price changes, and prints formatted output; there is no Feishu API call, webhook invocation, or messaging integration anywhere in the file.

Missing User Warnings

Low
Confidence
88% confidence
Finding
This markdown file describes an external notification behavior ('pushes notifications via Feishu') but does not include any caution about transmitting fetched content outside the local environment. Under the markdown-specific SQP-2 criteria, behaviors that affect privacy or system/data flow should be disclosed with a user-facing warning.

Missing User Warnings

Low
Confidence
88% confidence
Finding
The code creates a local data directory and writes window cache data to windows_cache.json, but there is no user-facing notice in the main execution flow that running the script will modify local files. For code files, file writes should have some visible disclosure unless already clearly documented or inherent to the stated purpose; this script's top-level description focuses on monitoring and pushing updates, not local persistence.

Description-Behavior Mismatch

Low
Confidence
78% confidence
Finding
The manifest focuses on checking the NDRC site every 10 working days and pushing announcement notifications. The implementation also predicts and caches the next year's adjustment windows by searching for State Council holiday notices or calculating future schedules, which is broader than simple announcement monitoring.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests>=2.28.0
beautifulsoup4>=4.11.0
lxml>=4.9.0
Confidence
93% confidence
Finding
The dependency is specified with a lower bound only, which allows future installs to resolve to different versions over time. This weakens reproducibility and can unintentionally introduce vulnerable or breaking releases into the skill, especially in an automated monitoring workflow that may be redeployed without review.

Unverifiable Dependency: requests has 16 known advisory(ies) (CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
89% confidence
Finding
The manifest does not pin requests, and the package has multiple published advisories across versions. That means the deployed environment could resolve to a vulnerable release without any way to verify from this file alone, which is a genuine supply-chain risk even if the exact affected version is unknown.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests>=2.28.0
beautifulsoup4>=4.11.0
lxml>=4.9.0
Confidence
92% confidence
Finding
Using an unpinned beautifulsoup4 version means builds are not deterministic and later installs may pull in unexpected package changes. While this is not directly exploitable by itself, it increases supply-chain risk and makes it harder to ensure that only reviewed versions are deployed.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests>=2.28.0
beautifulsoup4>=4.11.0
lxml>=4.9.0
Confidence
95% confidence
Finding
The lxml dependency is not pinned, so installations may resolve to different versions with different security properties. Because lxml is a parser library with a history of security advisories, leaving it floating increases the chance of pulling an unsafe version into production.

Unverifiable Dependency: lxml has 14 known advisory(ies) (CVE-2021-43818 (lxml's HTML Cleaner allows crafted and SVG embedded scripts to pass through); CVE-2014-3146 (lxml Cross-site Scripting Via Control Characters); CVE-2021-28957 (lxml vulnerable to Cross-Site Scripting ) +11 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
91% confidence
Finding
lxml has known historical advisories, and because the requirement is not pinned, there is no assurance that installations will avoid affected versions. In a skill that fetches and parses remote web content, parser library risk is somewhat more relevant because malformed input may be attacker-controlled or externally influenced.

Static analysis

No suspicious patterns detected.