Back to skill

Security audit

eden-digital-web3-weekly-digest-yang

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it claims, but it has an under-scoped URL fetch path and automatically routes untrusted web content into AI completion without a clear consent or safety boundary.

Review before installing. Use it only when you intentionally want a Chinese Web3 weekly report, expect it to contact public market/news sites, and avoid passing untrusted or user-supplied URLs to --rwa-url unless the URL is verified as a PANews article. Treat fetched report text as untrusted before giving it to an AI, and avoid granting that AI file, shell, memory, or broad network tools during completion.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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 (3)

T09 · Insecure Skill Coding Practices

Error
Location
run_all.py:683
Finding

Unrestricted User-Controlled URL Fetch Enables SSRF

Content
View full analysis
str: r = subprocess.run( ['curl', '-s', '-L', f'--max-time', str(timeout), '-H', 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)', '-H', 'Accept: text/html,application/json', '-H', 'Accept-Language: zh-CN,zh;q=0.9,en;q=0.8', url], capture_output=True, text=True ) return r.stdout if r.returncode == 0 else '' ``` ```python def fetch_part7(rwa_url: str = '') -> tuple: log('Part.7 - searching PANews RWA Weekly...') if not rwa_url: rwa_url = find_rwa_article() if not rwa_url: log('[WARN] Part.7 - could not find article URL') return [], '' log(f'Part.7 - fetching: {rwa_url}') html = fetch(rwa_url) ``` ```python parser.add_argument( '--rwa-url', help='PANews RWA Weekly article URL (skip automatic search)', default='' ) ... rwa_projects, rwa_url = fetch_part7(args.rwa_url) ``` ### Technical Analysis The `--rwa-url` command-line value is passed to `curl` without validating its scheme, hostname, port, resolved address, or redirect destination. The documentation describes this value as a PANews article URL, but the implementation does not enforce that restriction. An attacker who can influence the command-line arguments can therefore cause the Skill to issue requests to arbitrary destinations, including: - Services bound to localhost - Private network addresses - Link-local or cloud metadata endpoints - Services on nonstandard ports - Local resources supported by the installed curl build - External hosts reached through redirects The use of `curl -L` expands the issue because even a URL initially hosted on an approved domain could redirect to ...[truncated 1278 chars]
Remediation
View remediation
`. 9. Where possible, accept only an article identifier and construct the complete trusted URL internally rather than accepting a complete URL. Example validation policy: ```python from urllib.parse import urlsplit import ipaddress import socket ALLOWED_HOSTS = {'www.panewslab.com'} def validate_rwa_url(url): parsed = urlsplit(url) if parsed.scheme != 'https': raise ValueError('Only HTTPS URLs are permitted') if parsed.hostname not in ALLOWED_HOSTS: raise ValueError('Only PANews URLs are permitted') if parsed.username or parsed.password or parsed.port not in (None, 443): raise ValueError('Credentials and custom ports are prohibited') if not parsed.path.startswith('/en/articles/'): raise ValueError('Unexpected PANews article path') for info in socket.getaddrinfo(parsed.hostname, 443): address = ipaddress.ip_address(info[4][0]) if not address.is_global: raise ValueError('Non-public destination prohibited') return url ``` ]]>

T01 · Skill Instruction Hijacking

Warning
Location
run_all.py:815
Finding

Untrusted Web Content Is Mandated for Downstream AI Processing

Content
View full analysis
{desc}') lines.append(f' > Original article: {link}') lines.append( f' > AI editing required: rewrite the title and summary as one report item' ) ``` RWA article content is likewise inserted into AI-facing report fields: ```python for p in rwa_projects: lines += [ f'## {p["name"]}', f'**Details:** {p["detail"][:200]}', '', ] ``` ### Technical Analysis News titles, descriptions, project names, and article paragraphs are obtained from third-party websites and inserted verbatim into a Markdown report. The Skill then explicitly requires that the entire report be submitted to an AI for completion. The implementation does not establish a strong trust boundary between operational instructions and fetched source data. It also does not sanitize instruction-like language or explicitly tell the downstream model that all fetched text is untrusted data that must never be executed as instructions. A compromised source, malicious feed entry, or attacker-selected URL exploiting the unrestricted URL-fetch issue coul ...[truncated 1444 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Note
Location
scripts/part5_fetch.py:45
Finding

Undeclared and Unpinned Playwright and Chromium Dependency

Content
View full analysis
dict: try: from playwright.sync_api import sync_playwright, TimeoutError as PWTimeout except ImportError: print( '[ERROR] Please install: pip install playwright && ' 'playwright install chromium', file=sys.stderr ) sys.exit(1) ``` The Skill metadata declares only curl and Python: ```yaml requires: bins: - curl - python3 ``` ### Technical Analysis The documented standalone Part 5 script depends on Playwright and a downloaded Chromium executable, but neither dependency is declared in the Skill's requirements. When the dependency is absent, the script instructs the user to install the latest package and browser binary without a pinned version, hash, lockfile, or documented integrity-verification process. The code does not automatically execute the installation command, so this is not direct remote payload execution. The risk arises when a user follows the installation instruction and introduces unpinned third-party code and a browser executable into the environment. This also creates a mismatch between the stated minimum requirements and actual standalone behavior. The main `run_all.py` implementation already uses CoinGecko and curl for Part 5, making the browser dependency unnecessary for the primary workflow. ### Attack Path 1. A user invokes the documented `scripts/part5_fetch.py` command. 2. Playwright is not installed because it is absent from the declared requirements. 3. The script instructs the user to run an unpinned package installation and download Chromium. 4. The package manager and Playwrig ...[truncated 707 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (17)

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The activation rule is overly broad: it explicitly says to trigger even on vague requests like '帮我写本周的' whenever surrounding context mentions Web3, crypto, financing, RWA, or DAT. That can cause the skill to run unexpectedly, leading to unsolicited network access and report generation the user may not have intended.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill is described entirely as a Chinese-language weekly-report workflow and the fixed completion prompt is written to produce output in Chinese, but there is no opt-in or alternative language option. This can violate language/locale policy when users have not explicitly chosen Chinese as the required output language.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill instructs automatic fetching from multiple third-party sources and then mandates sending the generated report skeleton to an AI for completion, but it does not require a clear user-facing notice or consent step. This creates a data-handling and transparency risk because network activity and onward transmission occur automatically, potentially exposing user-provided context or compiled content to external services.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
89% confidence
Finding

This line defines an external API call to CoinGecko, which is legitimate for the skill's purpose, but it is still a real external transmission because running the skill sends requests to a third-party service. In context, the danger is moderate rather than high: the fetched data is public market data, but the skill performs network access automatically and without prominent runtime notice.

Content

Scanner excerpt · SKILL.md (reported line 130)May include surrounding context.

md
### 数据源

**CoinGecko 公开免费 API(无需 Key)**
- BTC 持仓:`https://api.coingecko.com/api/v3/companies/public_treasury/bitcoin`
- ETH 持仓:`https://api.coingecko.com/api/v3/companies/public_treasury/ethereum`
- **局限**:仅返回当前持仓快照,变动部分由脚本自动抓取 CoinGecko 详情页补充

External Transmission

Medium
Category
Data Exfiltration
Confidence
89% confidence
Finding

This second CoinGecko endpoint is another instance of third-party network transmission. Although the content requested is public ETH treasury data and the intent appears functional, the lack of explicit consent and the automatic-fetch design make it a genuine privacy/transparency issue in the skill context.

Content

Scanner excerpt · SKILL.md (reported line 131)May include surrounding context.

md
**CoinGecko 公开免费 API(无需 Key)**
- BTC 持仓:`https://api.coingecko.com/api/v3/companies/public_treasury/bitcoin`
- ETH 持仓:`https://api.coingecko.com/api/v3/companies/public_treasury/ethereum`
- **局限**:仅返回当前持仓快照,变动部分由脚本自动抓取 CoinGecko 详情页补充

### 每个条目最终输出格式

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This Python file contains user-facing natural-language content entirely in Chinese and presents the tool as a report generator with Chinese-only CLI descriptions and output strings. Because the skill does not offer a language/locale selection or document a justified region-specific constraint, it violates the language/locale policy criteria.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · run_all.py (reported line 29)May include surrounding context.

python
# ══════════════════════════════════════════════════════

def fetch(url: str, timeout: int = 20) -> str:
    r = subprocess.run(
        ['curl', '-s', '-L', f'--max-time', str(timeout),
         '-H', 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)',
         '-H', 'Accept: text/html,application/json',

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · run_all.py (reported line 485)May include surrounding context.

python
log('Part.5 — 抓取 CoinGecko DAT 数据...')
    result = {}
    for coin_id, asset in [('bitcoin', 'BTC'), ('ethereum', 'ETH')]:
        raw = fetch(f'https://api.coingecko.com/api/v3/companies/public_treasury/{coin_id}')
        if not raw:
            log(f'[WARN] {asset} 数据获取失败')
            continue

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/part3_fetch.py (reported line 16)May include surrounding context.

python
EXCLUDE_KW = ['价格','涨幅','跌幅','清算','链上数据','空投奖励','回购销毁','行情','日报','早报','研报','教程','攻略','巨鲸']

def fetch_rss(page):
    r = subprocess.run(['curl','-s','-L','--max-time','15',
        f'https://www.techflowpost.com/api/client/common/rss.xml?page={page}'],
        capture_output=True, text=True)
    return r.stdout if r.returncode == 0 else ''

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/part4_fetch.py (reported line 7)May include surrounding context.

python
from datetime import datetime, timedelta

def fetch_html(url):
    r = subprocess.run(['curl','-s','-L','--max-time','20',
        '-H','User-Agent: Mozilla/5.0','-H','Accept: text/html', url],
        capture_output=True, text=True)
    if r.returncode != 0: print(f"[ERROR] {r.stderr}",file=sys.stderr); sys.exit(1)

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The script emits user-facing headings and templates entirely in Chinese, including required output fields such as summaries and analysis prompts. There is no option to select another language or indication that the skill is intentionally limited to a Chinese-language or region-specific workflow.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The browser context is hard-coded to use the zh-CN locale, and the script’s user-facing strings and date formatting are also fixed in Chinese. This creates a language/locale policy issue because users are not offered any choice or opt-in for the forced locale.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The module docstring and all user-facing output are written in Chinese, and the formatter explicitly converts dates to Chinese strings. This imposes a specific language/locale on all users without opt-in or indication that the skill is region-specific, matching the language/locale policy violation criteria.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/part7_fetch.py (reported line 5)May include surrounding context.

python
"""
Part.7 RWA 重要新闻抓取脚本
数据源:https://cryptorank.io/news/rwa
API:  https://api.cryptorank.io/v0/news?lang=en&coinKeys=rwa&withFullContent=true

特点:
  · 纯 curl + Python 标准库,无需 Playwright、无需 API Key

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/part7_fetch.py (reported line 21)May include surrounding context.

python
"""
Part.7 RWA 重要新闻抓取脚本
数据源:https://cryptorank.io/news/rwa
API:  https://api.cryptorank.io/v0/news?lang=en&coinKeys=rwa&withFullContent=true

特点:
  · 纯 curl + Python 标准库,无需 Playwright、无需 API Key

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/part7_fetch.py (reported line 56)May include surrounding context.

python
def fetch_page(offset: int, limit: int) -> list:
    url = (f'{API_BASE}?lang=en&coinKeys=rwa'
           f'&withFullContent=true&limit={limit}&offset={offset}')
    r = subprocess.run(
        ['curl', '-s', '-L', '--max-time', '15',
         '-H', 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)',
         '-H', 'Accept: application/json',

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The printed label says 'AI 根据标题与摘要生成背景解读' ('AI generates background interpretation from title and summary'), which implies the script produces an AI-written commentary. In reality, the code only prints a fixed placeholder string and performs no model call, inference, or generated analysis anywhere in the file.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.