Back to skill

Security audit

Wikipedia Publisher

Security checks for vulnerabilities and agentic risk

Overview

The skill’s Wikipedia drafting purpose is coherent, but its publishing helper can send wiki credentials to a user-supplied API endpoint and its URL enricher fetches arbitrary URLs without network safety bounds.

Review before installing. Use dry-run first, avoid passing passwords on the command line, do not set WIKI_USERNAME/WIKI_PASSWORD when using a custom --api endpoint, and only run URL enrichment on trusted public URLs or in a network-restricted environment.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/citation_fetch_enricher.py:55
Finding

Arbitrary URL Fetching Enables Server-Side Request Forgery

Content
View full analysis
dict: result = {'url': url} try: r = requests.get(url, headers={'User-Agent': UA}, timeout=timeout, allow_redirects=True) result['status_code'] = r.status_code result['final_url'] = r.url result['classification'], result['host'] = classify_url(r.url) html = r.text[:400000] meta = parse_meta(html) title = first(meta, TITLE_KEYS) or fallback_title(html) work = first(meta, WORK_KEYS) or urlparse(r.url).netloc.replace('www.', '') author = first(meta, AUTHOR_KEYS) date = first(meta, DATE_KEYS) desc = first(meta, DESC_KEYS) result.update({ 'title': title, 'work': work, 'author': author, 'date': date, 'description': desc, }) result['suggested_cite'] = '{{cite web |title=%s |url=%s |work=%s%s%s}}' % ( title or 'MISSING TITLE', r.url, work or 'MISSING WORK', f' |author={author}' if author else ' |author=', f' |date={date}' if date else ' |date=', ) except Exception as e: result['error'] = f'{type(e).__name__}: {e}' result['classification'], result['host'] = classify_url(url) return result ``` The affected URL collection and invocation path is: ```python def urls_from_args(args) -> list[str]: urls: list[str] = [] if args.urls: urls.extend(args.urls) if args.draft: refs = extract_refs(load_text(args.draft)) for ref in refs[: args.limit]: if ref['urls']: urls.append(ref['urls'][0]) return list( ...[truncated 2911 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/sandbox_publish.py:16
Finding

Custom MediaWiki Endpoint Can Receive Automatically Loaded Credentials

Content
View full analysis
str: r = session.get(api, params={'action':'query','meta':'tokens','type':'login','format':'json'}, timeout=30) r.raise_for_status() return r.json()['query']['tokens']['logintoken'] def login(session: requests.Session, api: str, username: str, password: str) -> dict: token = get_login_token(session, api) r = session.post(api, data={'action':'login','lgname':username,'lgpassword':password,'lgtoken':token,'format':'json'}, timeout=30) r.raise_for_status() return r.json() ``` The endpoint and credential configuration is: ```python def main(): ap = argparse.ArgumentParser(description='Publish a local wiki draft to a user sandbox or Draft: page') ap.add_argument('--file', required=True, help='Path to local .wiki draft') ap.add_argument('--title', required=True, help='Target wiki page title') ap.add_argument('--summary', default='Save sourced draft for review', help='Edit summary') ap.add_argument('--api', default=API_DEFAULT, help='MediaWiki API endpoint') ap.add_argument('--username', default=os.getenv('WIKI_USERNAME')) ap.add_argument('--password', default=os.getenv('WIKI_PASSWORD')) ap.add_argument('--dry-run', action='store_true', help='Print target info without editing') args = ap.parse_args() text = read_text(args.file) if args.dry_run: print(f'title: {args.title}') print(f'summary: {args.summary}') print(f'chars: {len(text)}') print('mode: dry-run') return if not args.username or not args.password: raise SystemExit('Missing credentials. Use --username/--password or WIKI_USERNAME/WIKI_PASSWORD') s = requests.Session() s ...[truncated 2237 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (5)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared purpose emphasizes safe drafting, review, sourcing, and de-risking, but the detected behavior includes direct authenticated publishing, credential handling, and arbitrary local content upload without evidence that the promised safety checks are actually enforced. That mismatch is dangerous because users and orchestrators may trust the skill as review-oriented while it can perform high-impact write actions, potentially publishing unreviewed, biased, or attacker-controlled content to external services.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding

The skill advertises and references capabilities that imply file access, environment access, and networked publishing workflows, but it does not declare any explicit tool scope or permission boundaries. This creates a governance gap: an agent may be allowed to invoke sensitive capabilities without a clear least-privilege contract, increasing the chance of unintended data access or external actions.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

This code accepts wiki credentials from environment variables or CLI parameters and then uses them for authentication, but there is no docstring, comment, or explicit warning to users about handling sensitive credentials. For a code file, accessing credentials is safety-relevant and should include some visible disclosure unless already documented elsewhere in the skill description, which is not present here.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
81% confidence
Finding

The script performs a live MediaWiki edit that publishes local content to a remote page, which is a write operation affecting external data. Although the argument parser description mentions publishing and there is a dry-run mode, there is no explicit confirmation prompt or clear warning immediately before the irreversible network write.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script performs outbound HTTP requests to arbitrary user-supplied or draft-extracted URLs with no warning, approval step, or host restrictions. In an agent/skill context, this can disclose network access capability, trigger unintended requests to attacker-controlled infrastructure, and enable SSRF-style access to internal or sensitive network endpoints if the runtime has privileged connectivity.

Content

No source excerpt is available for this finding.