Back to skill

Security audit

爬论文与人才触达工作流

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed recruiting and scraping toolkit, but it collects personal contact data, infers Chinese identity for recruiting, and can write to Feishu with overly broad permissions.

Install only if you are prepared to supervise it closely: use a sandboxed environment, pin dependencies, provide least-privilege Feishu and API credentials, block local/internal network targets, require dry runs before scraping or Feishu writes, and avoid using the Chinese-identity field for recruiting selection or outreach targeting.

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 (4)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/openreview_scraper.py:92
Finding
OpenReview credentials can be redirected to an attacker-controlled endpoint<![CDATA[ ## Vulnerability Details **File Location**: `scripts/openreview_scraper.py:92-106` **Vulnerability Type**: Unrestricted authentication endpoint **Risk Level**: High ### Vulnerable Code ```python def __init__(self, username: str, password: str, baseurl: str = 'https://api2.openreview.net'): """ 初始化爬虫 Args: username: OpenReview 注册邮箱 password: OpenReview 密码 baseurl: API 地址 (必须用 api2.openreview.net) """ print("正在登录 OpenReview...") try: self.client = openreview.api.OpenReviewClient( baseurl=baseurl, username=username, password=password ) ``` ### Technical Analysis The constructor accepts a caller-controlled `baseurl` and passes it to `OpenReviewClient` together with the user's OpenReview username and password. Although the default value and documentation identify `https://api2.openreview.net` as the required endpoint, the implementation does not enforce that restriction. There is no validation of the URL scheme, hostname, port, user-information component, or redirect behavior. Consequently, a malicious caller can substitute an endpoint under their control and cause authentication information to be submitted to it. Reading credentials from environment variables does not mitigate this issue because those credentials are subsequently supplied to the unrestricted endpoint. The network transmission is legitimate only when directed to the official OpenReview API. Permitting arbitrary destinations exceeds the minimum network privileges required by the declared conference-scraping functionality. ### Attack Path 1. A user or agent places valid OpenReview credentials in `OPENREVIEW_USER` and `OPENREVIEW_PASSWORD`. 2. An attacker influences a task, wrapper, copied example, or direct constructor invocation. 3. The attacker supplies a value such as `https://attacker.example/api` as `baseurl`. 4. `OpenReviewScraper` passes the credentials and attacker-controlled ...[truncated 688 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Remove the public `baseurl` parameter if alternate OpenReview endpoints are not required. - Otherwise, parse the URL and enforce: - HTTPS only. - Exact hostname `api2.openreview.net`. - No embedded username or password. - No unexpected port. - No redirects to a different hostname. - Reject malformed, IP-literal, loopback, private, link-local, and reserved destinations. - Prefer revocable API tokens over reusable account passwords if supported. - Avoid keeping the plaintext password longer than required to initialize the client. - Add tests proving that attacker-controlled hosts, HTTP endpoints, deceptive subdomains, and cross-host redirects are rejected. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/httpx_scraper.py:69
Finding
Arbitrary URL fetching permits server-side request forgery and internal network access<![CDATA[ ## Vulnerability Details **File Location**: `scripts/httpx_scraper.py:69-79, 149-154, 271-276` **Additional Locations**: `scripts/lab_member_scraper.py:121-143, 200-210, 402-411, 568`; `scripts/cvf_paper_scraper.py:191-198, 221-228, 254-264, 294-301` **Vulnerability Type**: Server-side request forgery through unrestricted URLs and redirects **Risk Level**: High ### Vulnerable Code ```python async def async_scrape( url: str, client: httpx.AsyncClient, headers: Optional[Dict[str, str]] = None, max_content_length: int = 50000 ) -> ScrapeResult: # 检查是否需要 BrightData if any(domain in url.lower() for domain in BRIGHTDATA_DOMAINS): return ScrapeResult( url=url, status="skipped", error="This domain requires BrightData MCP service" ) request_headers = {**DEFAULT_HEADERS, **(headers or {})} try: response = await client.get(url, headers=request_headers) ``` ```python async with httpx.AsyncClient( timeout=timeout, follow_redirects=True, limits=limits ) as client: ``` ```python async with httpx.AsyncClient( timeout=self.timeout, follow_redirects=True, limits=limits ) as client: ``` The specialized CVF scraper has a related trust-boundary issue: ```python def __init__(self, base_url: str = "https://openaccess.thecvf.com"): self.base_url = base_url.rstrip('/') self.results: List[PaperInfo] = [] self._session = requests.Session() ``` ```python pdf_rel_link = pdf_a_tag['href'] pdf_link = urljoin(self.base_url + '/', pdf_rel_link) ``` ```python response = self._session.get(pdf_url, timeout=20) ``` ### Technical Analysis The generic asynchronous scraper accepts arbitrary caller-provided URLs and fetches them without validating their scheme, resolved address, hostname, or port. Automatic redirects are enabled, but redirect destinations are not revalidated. The string-based `BRIGHTDATA_DOMAINS` check only skips selected social-medi ...[truncated 2519 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Accept only explicit `http` and `https` schemes. - Resolve the destination before every request and reject: - Loopback addresses. - Private network ranges. - Link-local addresses. - Multicast, reserved, unspecified, and documentation ranges. - IPv4-mapped IPv6 representations of prohibited addresses. - Known cloud metadata destinations. - Restrict destination ports to an approved set, normally 80 and 443. - Disable automatic redirects or manually process redirects and apply the same validation to every hop. - Protect against DNS rebinding by validating resolved addresses and connecting consistently to the validated destination. - Add strict host allowlists to specialized scrapers: - CVF requests should remain on `openaccess.thecvf.com`. - OpenReview requests should remain on official OpenReview hosts. - Reject absolute PDF links that leave the approved CVF origin. - Do not expose complete response bodies from untrusted destinations until the target has passed policy validation. - Add regression tests for IPv4, IPv6, encoded IP addresses, deceptive hostnames, redirects, and DNS rebinding scenarios. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/lab_member_scraper.py:402
Finding
TLS certificate verification is disabled and insecure HTTP downgrade is recommended<![CDATA[ ## Vulnerability Details **File Location**: `scripts/lab_member_scraper.py:402-411` **Additional Locations**: `scripts/lab_member_scraper.py:568`; `references/anti-scraping-solutions.md:337-350`; `references/python-scraping-guide.md:989` **Vulnerability Type**: Improper certificate validation and transport downgrade **Risk Level**: Medium ### Vulnerable Code ```python try: response = self.session.get(page_url, timeout=15, verify=False) response.encoding = response.apparent_encoding or 'utf-8' soup = BeautifulSoup(response.text, 'html.parser') except Exception as e: print(f"页面请求失败: {e}") return [] ``` The reference instructions also recommend insecure fallback behavior: ```python # 方案 1: 跳过 SSL 验证 (简单粗暴) response = requests.get(url, verify=False, timeout=10) # 方案 2: 捕获异常并跳过 (推荐) try: response = requests.get(url, timeout=10) except requests.exceptions.SSLError: print(f"SSL 错误,跳过: {url}") # 可选:尝试 http 而非 https if url.startswith('https://'): response = requests.get(url.replace('https://', 'http://'), timeout=10) ``` ### Technical Analysis Passing `verify=False` disables X.509 certificate-chain and hostname validation. HTTPS encryption may still be negotiated, but the client no longer verifies that it is communicating with the intended server. The documented fallback from HTTPS to HTTP is more severe because it removes both server authentication and transport encryption. A network-positioned attacker can observe or modify the entire response. The scraped content is used to extract identities, biographies, links, and email addresses. Modified content can therefore poison recruitment data or introduce attacker-controlled links into later output. These bypasses are not necessary for the Skill's core functionality; hosts with invalid TLS can be skipped or handled through narrowly scoped, explicit exceptions. ### Attack Path 1. The agent connects through an untrusted or compromised network. 2. An attacke ...[truncated 999 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Remove every use of `verify=False`. - Never automatically replace `https://` with `http://`. - Keep certificate and hostname verification enabled by default. - Update the host's certificate configuration or use a current trusted CA bundle when compatibility problems occur. - Skip sites with invalid TLS rather than silently weakening transport security. - If an exceptional site must be supported: - Require explicit user approval. - Scope the exception to the exact hostname. - Pin the expected certificate or public key. - Display a clear warning in the output. - Do not transmit credentials or sensitive information. - Convert `urllib3` insecure-request warnings into actionable failures rather than suppressing them. - Add tests confirming that expired, self-signed, mismatched, and untrusted certificates are rejected. ]]>

T08 · Insecure Dependencies

Warning
Location
README.md:80
Finding
Unpinned dependency installation creates supply-chain and environment integrity risk<![CDATA[ ## Vulnerability Details **File Location**: `README.md:80` **Additional Locations**: `references/conference-paper-scraping.md:51,454,466`; `scripts/openreview_scraper.py:8`; `scripts/cvf_paper_scraper.py:12-18`; `scripts/README.md:36` **Vulnerability Type**: Unpinned third-party dependencies and destructive environment modification **Risk Level**: Medium ### Vulnerable Code ```bash pip install requests beautifulsoup4 httpx python-dotenv openreview-py pandas openpyxl PyMuPDF ``` Other project instructions include: ```bash pip install openreview-py pandas tqdm ``` ```bash pip install requests beautifulsoup4 PyMuPDF pandas tqdm ``` ```bash pip uninstall -y fitz PyMuPDF && pip install PyMuPDF ``` ### Technical Analysis The project instructs users to install dependencies without version constraints, lockfiles, integrity hashes, or an isolated environment. Package resolution therefore depends on the current state of the package index at installation time rather than a reviewed dependency set. Python packages may execute code during installation and are imported into the Skill's process afterward. If a future package version or transitive dependency is compromised, installation may execute attacker-controlled code with the privileges of the user running `pip`. The uninstall-and-reinstall command also modifies the active Python environment and can remove packages needed by unrelated applications. This exceeds the minimum change required when an isolated virtual environment would provide the same functionality safely. No evidence was found that the named packages are intentionally malicious or misspelled. The issue is the unsafe, non-reproducible installation process. ### Attack Path 1. A user follows the setup instructions in a global or shared Python environment. 2. `pip` resolves the latest available versions and transitive dependencies from the configured index. 3. A dependency account, release, index, or transitive package is compromised. ...[truncated 1086 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Provide a reviewed dependency manifest with exact versions. - Generate and commit a lockfile using an appropriate tool such as `pip-tools`, Poetry, or uv. - Record package hashes and install with hash verification, for example `pip install --require-hashes`. - Pin transitive dependencies as well as direct dependencies. - Require installation in a dedicated virtual environment or container. - Avoid uninstalling packages from the user's existing environment. - Add dependency vulnerability and provenance scanning to continuous integration. - Review and update pinned versions through controlled pull requests. - Consider publishing a minimal supported dependency set rather than one broad installation command. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (100)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
声明描述的是一个面向招聘/研究者挖掘的复合搜索与数据处理 skill,涵盖多源抓取、身份识别、去重、外部系统导入和邮件生成等高层功能。实际代码却只是一个底层工具模块,用于解码 Cloudflare 保护的邮箱地址,属于非常狭窄的辅助功能。虽然“提取邮箱”可能是大工作流中的一个支持步骤,但单独这段代码并不能体现声明中的主要用途,且其核心行为与声明的主能力严重不匹配。因此应判定为描述与代码行为不一致。

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The declared description presents a comprehensive recruiting/talent-discovery skill spanning multiple sources and downstream actions. The supplied code only implements one specific subcomponent: scraping CVF Open Access conference papers and extracting author emails/institution domains from PDFs. While this partially overlaps with the declared mention of CVF/OpenReview author discovery and email extraction, the actual code lacks most of the advertised workflow capabilities and has a much narrower primary purpose. Therefore the description does not accurately represent what this code chunk actually does.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
声明描述的是一个范围很广的端到端人才搜寻与招聘自动化 skill,而给出的代码块仅覆盖其中较窄的一部分:GitHub 网络研究者信息抓取。它确实与“GitHub 研究者挖掘、提取 Scholar/GitHub/邮箱”等子能力部分吻合,但没有任何 OpenReview/CVF、实验室网页、人才搜索筛选、华人识别、去重、飞书导入或邮件生成的实现。因此该代码块的实际主功能明显比声明狭窄,不能准确代表所宣称的完整 skill 能力范围,属于描述与行为不匹配。未发现明显额外的高风险越权能力;主要问题是声明严重过度涵盖。

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description promises a high-level end-to-end recruiting/researcher-discovery skill with multiple domain-specific data sources and downstream processing steps. The actual code is a low-level utility for concurrent URL fetching. While such scraping could support a larger pipeline, this chunk by itself only retrieves HTML text from supplied URLs and reports success/error/skipped states. Its primary purpose is materially narrower and different from the declared skill behavior, so the description does not accurately represent the code.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
声明描述的是一个覆盖多来源人才搜索与后处理的综合型招聘/研究者发现 skill;而代码仅实现了其中“实验室成员爬取”这一子功能,且范围聚焦于学术实验室网页抓取与结构化提取。代码确实支持提取主页、Scholar、GitHub、邮箱、研究方向等字段,因此与声明中的部分内容一致;但它没有实现 OpenReview/CVF 作者发现、GitHub 研究者网络挖掘、华人识别/分类去重、飞书多维表格导入或邮件生成等关键能力。也就是说,声明显著高估了该代码块的能力边界。虽然未发现明显恶意或越权行为,但“描述覆盖面远大于实际实现”构成了实质性不匹配。

Tp4

High
Category
MCP Tool Poisoning
Confidence
87% confidence
Finding
The description presents a comprehensive talent search and outreach skill with multiple discovery sources and downstream recruiting actions. The actual code only implements one subset: scraping OpenReview conference papers/authors and extracting profile metadata, with simple Chinese-author identification and CSV export. While this partially aligns with the OpenReview/author-discovery portion of the description, the declared purpose substantially overstates the implemented behavior by including lab scraping, CVF support, GitHub researcher mining, dedup/classification pipelines, Feishu export, and email generation, none of which appear in this code chunk. Therefore the description does not accurately represent what this supplied code actually does.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
声明描述的是一个复杂的端到端人才发现与招聘自动化 skill,而给出的代码块只是其中很小的一部分:调用 Serper API 进行 Google/Scholar 搜索,并从结果中收集 URL。它确实与“发现 researcher 主页/实验室页面”这一子任务相关,因此不是完全无关;但相较声明,实际代码缺少大部分核心能力,尤其是作者抓取、GitHub 挖掘、信息抽取、身份识别、飞书导入和邮件生成。因此描述不能准确代表该代码块实际行为,属于明显不匹配。

Vague Triggers

High
Confidence
97% confidence
Finding
The skill explicitly says it should be triggered even when the user did not ask for it, across broad recruiting and scraping scenarios. That encourages implicit activation of a data-collection workflow with network access and external exports, increasing the risk of unauthorized scraping or side effects without informed user consent.

Missing User Warnings

High
Confidence
97% confidence
Finding
The skill is designed to collect emails, profiles, and research information and export them into Feishu, but it gives no warning that it handles personal data or sends that data to an external system. Users may unknowingly trigger large-scale collection and transfer of personal information, creating privacy, compliance, and trust risks.

Natural-Language Policy Violations

High
Confidence
99% confidence
Finding
The skill description explicitly includes identifying whether candidates are Chinese, which is a sensitive ethnicity or nationality inference. Performing protected-attribute classification for recruiting workflows creates substantial discrimination, privacy, and compliance risk, especially when used to filter or prioritize candidates.

Ssd 3

High
Confidence
98% confidence
Finding
The skill encourages large-scale collection of personal contact details and profile data, including harvesting missing emails and exporting them for outreach. In this context, the issue is especially dangerous because the stated use case is recruiting, which incentivizes bulk profiling and unsolicited contact of identifiable individuals.

Natural-Language Policy Violations

High
Confidence
99% confidence
Finding
Treating Chinese-candidate identification as a standard extraction step operationalizes sensitive-attribute inference as part of normal processing. In recruiting and outreach contexts, this makes discriminatory use much easier and increases legal and ethical exposure.

Ssd 3

High
Confidence
99% confidence
Finding
The standard extraction schema mandates collection of direct identifiers, contact data, and sensitive inferred attributes. Requiring these fields as routine output increases the likelihood of overcollection, persistent storage, and discriminatory downstream processing.

Missing User Warnings

High
Confidence
96% confidence
Finding
The Feishu workflow includes reading, creating fields, and batch-updating records in an external system, yet it lacks any warning or consent checkpoint for modifying stored data. This creates a clear risk of unintended writes, data leakage, or corruption in user-connected third-party workspaces.

Missing User Warnings

High
Confidence
97% confidence
Finding
The prompt template directs extraction of personal profiles and email addresses from websites and papers, including following secondary pages to find missing contact data, without any consent or privacy warning. In a recruiting context this materially increases the risk of mass contact harvesting and unauthorized aggregation of personal information.

Ssd 3

High
Confidence
98% confidence
Finding
The skill instructs the agent to visit personal homepages and paper pages specifically to obtain missing email addresses and consolidate them into CSV and Feishu tables. That is targeted contact harvesting and aggregation, which materially increases privacy risk and enables large-scale unsolicited outreach.

Natural-Language Policy Violations

High
Confidence
99% confidence
Finding
Including a dedicated 'Chinese?' field in the output schema normalizes storage and downstream use of a sensitive protected-attribute label. Once embedded in exported tables and candidate summaries, the data can be used for discriminatory filtering or outreach targeting at scale.

Ae1

High
Category
analysis-evasion
Content
2. 在本 `SKILL.md` 的“最佳实践提示词”部分补充该功能已支持的明确说明
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Hidden Instructions

High
Category
Prompt Injection
Content
网站使用 Cloudflare CDN 的邮箱保护功能,邮箱地址被替换为加密字符串:

```html
<!-- 原始邮箱: example@domain.com -->
<a href="/cdn-cgi/l/email-protection#0762637474346762637474342964686a">
    [email protected]
</a>
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Hidden Instructions

High
Category
Prompt Injection
Content
网站使用 Cloudflare CDN 的邮箱保护功能,邮箱地址被替换为加密字符串:

```html
<!-- 原始邮箱: example@domain.com -->
<a href="/cdn-cgi/l/email-protection#0762637474346762637474342964686a">
    [email protected]
</a>
Confidence
70% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Context-Inappropriate Capability

High
Confidence
99% confidence
Finding
The guidance explicitly recommends disabling TLS certificate verification and downgrading from HTTPS to HTTP when scraping continues to fail. This weakens transport security, enables man-in-the-middle interception or content tampering, and normalizes insecure handling of remote data sources.

Natural-Language Policy Violations

High
Confidence
98% confidence
Finding
The file explicitly defines a workflow to identify whether people are Chinese based on surnames, affiliations, and name structure, which is a sensitive ethnicity/national-origin inference about individuals. In the context of a recruiting and researcher-harvesting skill, this materially increases the risk of discriminatory profiling, privacy harms, and downstream biased outreach or selection decisions at scale.

Missing User Warnings

High
Confidence
95% confidence
Finding
The document explicitly frames conference scraping as a way to collect authors' contact details and academic profile links for talent discovery, but provides no privacy, consent, retention, or lawful-use guidance. In the context of a recruiting/mapping skill, this materially increases the risk of bulk personal-data harvesting and downstream outreach misuse.

Ssd 3

High
Confidence
97% confidence
Finding
The instructions direct users to collect and export authors' emails and profile/contact data into a dataset for researcher discovery and recruiting workflows. In this skill's context, that is sensitive-data harvesting at scale and can facilitate spam, profiling, or unauthorized contact enrichment.

Ssd 3

High
Confidence
98% confidence
Finding
The guide instructs treating any author ID containing an email address as a direct email and preserving it in output records. This converts identifiers into actionable contact data without validation of consent or intended use, making bulk outreach and deanonymization easier.

Static analysis

No suspicious patterns detected.