Back to skill

Security audit

Cfc Disclosure Monitor

Security checks for vulnerabilities and agentic risk

Overview

This skill performs the advertised disclosure collection work, but it needs review because it includes hardcoded API credentials, under-disclosed third-party AI uploads, weakened browser security, and unsafe download handling.

Install only if you are comfortable with a crawler that contacts many external company sites, downloads public disclosure files, may send document contents or images to third-party AI services, and mutates a persistent ontology file. The publisher should remove and rotate embedded API keys, require explicit opt-in for external AI processing, restore normal browser security settings or isolate the crawler, and harden URL and filename validation before broad use.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (6)

T09 · Insecure Skill Coding Practices

Error
Location
clean_and_eval.py:17
Finding

Hard-Coded MiniMax API Credential

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
parser.py:40
Finding

Hard-Coded GLM API Credential

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
clean_and_eval.py:35
Finding

Automatic Transmission of Collected Documents to Third-Party AI Services

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
collect.py:166
Finding

Path Traversal Through Website-Controlled Attachment Filenames

Content
View full analysis
{ const links = document.querySelectorAll('a[href], img[src]'); const results = []; for (const el of links) { const url = el.href || el.src; if (!url || url.startsWith('javascript') || url === '#') continue; const fname = (el.href ? el.getAttribute('download') : null) || url.split('/').pop().split('?')[0]; if (fname && (fname.endsWith('.pdf') || fname.match(/\\.(png|jpg|jpeg|gif|webp)$/i))) { if (fname.length < 200) { results.push({url, fname, type: fname.endsWith('.pdf') ? 'pdf' : 'image'}); } } } return results; } """) ``` ```python async def _download_attachment(att: dict, page) -> Path: """下载单个附件到 content/{id}/attachments/""" import urllib.request content_dir = Path(sys.argv[0]).parent # will be overridden by caller att_dir = content_dir / "attachments" att_dir.mkdir(parents=True, exist_ok=True) fname = att["fname"] url = att["url"] # 如果是相对路径,拼成绝对路径 if not url.startswith("http"): from urllib.parse import urljoin url = urljoin(page.url, url) filepath = att_dir / fname if filepath.exists(): return filepath try: req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"}) with urllib.request.urlopen(req, timeout=15) as r: with open(filepath, "wb") as f: f.write(r.read()) return filepath except Exception: return None ``` ### Technical Analysis The remote page controls `fname` through the HTML `download` attribute. The code only checks the extension and maximum length. It does not reject absolute paths, `..` components, backslashes, or path ...[truncated 1457 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
phase2_parse.py:38
Finding

Server-Side Request Forgery Through Unvalidated Announcement URLs

Content
View full analysis
bool: """下载 PDF 到 dest,返回是否成功。""" if dest.exists() and dest.stat().st_size > 100: return True # 已存在,跳过 import urllib.request try: req = urllib.request.Request(url, headers={ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" }) with urllib.request.urlopen(req, timeout=timeout) as resp: content = resp.read() if content[:4] != b'%PDF': return False dest.parent.mkdir(parents=True, exist_ok=True) with open(dest, 'wb') as f: f.write(content) return True except Exception: return False ``` ```python def find_pdf_links(item: dict, base_url: str = "") -> list[str]: """从 announcement 中提取 PDF URL(_attachments > 绝对URL > 相对URL > HTML抓取)。""" urls = [] text = item.get("text", "") attachments = item.get("_attachments", []) ann_url = item.get("url", "") or base_url # 1. _attachments for att in attachments: if isinstance(att, dict) and '.pdf' in att.get('url', '').lower(): urls.append(att['url']) # 2. 绝对 URL abs_urls = re.findall(r'https?://[^\s\'"<>]+\.pdf', text, re.I) urls.extend(abs_urls) # 3. 正文提.pdf但无URL → 推断base if '.pdf' in text.lower(): from urllib.parse import urljoin, urlparse if ann_url: parsed = urlparse(ann_url) base = f"{parsed.scheme}://{parsed.netloc}{parsed.path.rsplit('/', 1)[0]}/" rel = re.findall(r'["\']([^"\']*\.pdf)', text) for r in rel: urls.append(urljoin(base, r)) pass return list(dict. ...[truncated 1926 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
collect.py:34
Finding

Chromium Security Boundaries Disabled While Visiting Untrusted Websites

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (58)

Tainted flow: 'req' from os.environ.get (line 56, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · clean_and_eval.py (reported line 66)May include surrounding context.

python
},
                method="POST",
            )
            with urllib.request.urlopen(req, timeout=60) as resp:
                result = json.loads(resp.read())

            status = result.get("base_resp", {}).get("status_code", -1)

Tainted flow: 'req' from os.environ.get (line 56, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · clean_and_eval.py (reported line 97)May include surrounding context.

python
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
            "Referer": referer,
        })
        with urllib.request.urlopen(req, timeout=20, context=ctx) as r:
            data = r.read()

        # 用 URL hash 做文件名,保留扩展名

Tainted flow: 'GLM_API_KEY' from os.getenv (line 44, credential/environment) → httpx.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · parser.py (reported line 125)May include surrounding context.

python
# ── 优先:GLM-4V-flash(视觉+文本结构化提取) ─────────────────────────
    if image_base64:
        try:
            resp = httpx.post(
                GLM_API_URL,
                headers={"Authorization": f"Bearer {GLM_API_KEY}", "Content-Type": "application/json"},
                json={"model": "glm-4v-flash", "messages": messages, "max_tokens": max_tokens},

Tainted flow: 'GLM_API_KEY' from os.getenv (line 44, credential/environment) → httpx.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · parser.py (reported line 141)May include surrounding context.

python
# ── GLM-4-flash(纯文本) ──────────────────────────────────────────────
    for glm_model in ["glm-4-flash", "glm-4v-flash"]:
        try:
            resp = httpx.post(
                GLM_API_URL,
                headers={"Authorization": f"Bearer {GLM_API_KEY}", "Content-Type": "application/json"},
                json={"model": glm_model, "messages": messages, "max_tokens": max_tokens, "temperature": temperature},

Missing User Warnings

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

A live API credential appears hardcoded as the default value for MINIMAX_API_KEY. Anyone with access to this file or a redistributed copy can reuse the key for unauthorized API calls, incur billing, or access associated service activity, and the key may persist in version control history even if later removed.

Content

No source excerpt is available for this finding.

Ssd 3

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The embedded OCR API key is a direct secret exposure. Beyond unauthorized use and billing abuse, distributing this script leaks a credential into downstream environments and archives, making incident response harder because copies may persist outside the original repository.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

A hardcoded GLM API credential embeds standing access to an external service directly in the source code, enabling unauthorized reuse if the file is exposed, shared, or committed. In the context of a parser skill, this also silently grants external transmission capability beyond what users may expect from local text processing.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The code contains a hardcoded API credential, which is a direct secret-management failure. Anyone with access to the repository, packaged skill, logs, or backups may recover and abuse the credential for unauthorized API usage, billing impact, or access to associated service data.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
90% confidence
Finding

The parser sends announcement text, metadata, and optionally images to an external LLM API, which creates a clear data egress path to a third party. In a parsing skill, this may expose sensitive or regulated source content, and the code does not provide meaningful notice, consent, data classification, redaction, or provider restrictions before transmission.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill explicitly documents downloading remote content and writing announcements, extracted text, and attachments into local workspace directories, but it does not warn the user about persistent filesystem modification or storage growth. This creates a real safety issue because running the skill can unexpectedly alter the local environment, consume disk space, and retain potentially sensitive or untrusted files from external websites.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill states that Phase 3 writes extracted entities into a shared persistent ontology file under memory/ontology/graph.jsonl, yet it does not warn that execution mutates shared long-lived knowledge state. This is dangerous because imported data from scraped external sources can contaminate or poison downstream knowledge, affect unrelated workflows, and be difficult to audit or roll back once merged into shared storage.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The top-level documentation describes the phase as data cleaning, content evaluation, and image OCR, which suggests local processing of Phase 1 outputs. In implementation, the script additionally fetches image URLs over the network and uploads image contents to MiniMax via HTTP requests, a materially broader operational behavior not reflected in the docstring.

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 · clean_and_eval.py (reported line 21)May include surrounding context.

python
"MINIMAX_API_KEY",
    "sk-cp-CT_VXVxvL9Eu71Wnp5NjLO6RatHKPker4laUs67t24Cmhk56xEOSyeU5-pHkjxJkLiFCvK8_AA7QY0g3MBAPWkzXRl1AnZiQBjPdvOCSRVQq4GDWElDPEUY",
)
MINIMAX_TEXT_URL = "https://api.minimax.chat/v1/text/chatcompletion_v2"
MINIMAX_VLM_URL = "https://api.minimax.chat/v1/coding_plan/vlm"

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 · clean_and_eval.py (reported line 22)May include surrounding context.

python
"MINIMAX_API_KEY",
    "sk-cp-CT_VXVxvL9Eu71Wnp5NjLO6RatHKPker4laUs67t24Cmhk56xEOSyeU5-pHkjxJkLiFCvK8_AA7QY0g3MBAPWkzXRl1AnZiQBjPdvOCSRVQq4GDWElDPEUY",
)
MINIMAX_TEXT_URL = "https://api.minimax.chat/v1/text/chatcompletion_v2"
MINIMAX_VLM_URL = "https://api.minimax.chat/v1/coding_plan/vlm"

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 · clean_and_eval.py (reported line 28)May include surrounding context.

python
"MINIMAX_API_KEY",
    "sk-cp-CT_VXVxvL9Eu71Wnp5NjLO6RatHKPker4laUs67t24Cmhk56xEOSyeU5-pHkjxJkLiFCvK8_AA7QY0g3MBAPWkzXRl1AnZiQBjPdvOCSRVQq4GDWElDPEUY",
)
MINIMAX_TEXT_URL = "https://api.minimax.chat/v1/text/chatcompletion_v2"
MINIMAX_VLM_URL = "https://api.minimax.chat/v1/coding_plan/vlm"

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 · parser.py (reported line 42)May include surrounding context.

python
"MINIMAX_API_KEY",
    "sk-cp-CT_VXVxvL9Eu71Wnp5NjLO6RatHKPker4laUs67t24Cmhk56xEOSyeU5-pHkjxJkLiFCvK8_AA7QY0g3MBAPWkzXRl1AnZiQBjPdvOCSRVQq4GDWElDPEUY",
)
MINIMAX_TEXT_URL = "https://api.minimax.chat/v1/text/chatcompletion_v2"
MINIMAX_VLM_URL = "https://api.minimax.chat/v1/coding_plan/vlm"

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The function base64-encodes downloaded images and sends them to an external OCR service without any explicit consent, notice, or policy gate. If those images contain regulated, confidential, or personal information, normal use of the script causes unintended third-party disclosure and possible compliance violations.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

This Python file contains natural-language instructions, help text, and runtime messages exclusively in Chinese, starting from the module docstring and continuing through the CLI interface. Under the stated policy, forcing a specific language without offering a language or locale choice is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The function documentation says detail-page attachments are stored under each announcement's content/{id}/attachments/ directory. However, _download_attachment derives its destination from Path(sys.argv[0]).parent and creates a generic attachments directory there, with no caller override, so attachments fetched via _extract_attachments are not saved to the per-item path described by the docstring.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The argparse description, help strings, examples, and printed status messages are all presented only in Chinese. The file does not offer an alternate locale, opt-in mechanism, or explicit justification that the skill is restricted to Chinese-language users only.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

Multiple collectors navigate to remote websites, read full page text, intercept network responses, and directly call external APIs using page.request, but the file does not include any confirmation prompt or explicit disclosure that user/system network activity and retrieved content will be sent to external services. While some logging exists for counts and progress, it does not warn about the privacy or integrity implications of automated remote collection.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The docstring at L1078-L1082 describes a fallback strategy of waiting for Cloudflare and otherwise returning an empty list for html_dom to handle. However, the code immediately installs a response listener at L1088-L1102 and captures JSON from matching API responses, which is a materially different data-collection method than the documentation describes.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

This JSON manifest contains natural-language strings stating the configuration is for '30家消费金融公司信息披露采集配置' and that all collection entrypoints should use this file, but it provides no indication that Chinese-language behavior is optional or region-specific by design. Under the policy, forcing a specific language or locale without user opt-in can be a natural-language policy violation unless the constraint is explicitly justified.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script claims to only diagnose company disclosure pages, but the Playwright browser is launched with flags that disable important protections such as web security and certificate validation. If one of the target sites is compromised or intercepted, the browser may accept malicious content or invalid TLS sessions and interact with it under weaker isolation than expected.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This code file performs external network access by navigating an automated browser to third-party company websites, which transmits system/browser metadata and triggers page loads. Although the script prints the target URL after starting diagnosis, it does not provide a prior warning, confirmation, or inline documentation explaining that live network requests will be made to external domains.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.