Back to skill

Security audit

Lowyat Forum Research

Security checks for vulnerabilities and agentic risk

Overview

This Lowyat forum research skill is mostly purpose-aligned, but its scraper can fetch arbitrary user-supplied URLs and writes untrusted forum text into Excel without spreadsheet-safety handling.

Review before installing. Use it only in a constrained environment, provide only forum.lowyat.net topic URLs, avoid running it against arbitrary links, and treat generated spreadsheets as untrusted content. The publisher should add URL allowlisting, redirect and timeout controls, formula neutralization for Excel cells, clearer file-write disclosure, and pinned dependency versions.

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

Error
Location
datascraping.py:11
Finding

Unrestricted User-Controlled URL Fetching Enables Server-Side Request Forgery

Content
View full analysis
1: topic_url = sys.argv[1].rstrip('/') else: topic_url = input("Enter the Lowyat forum topic URL: ").strip().rstrip('/') # Extract topic ID from URL topic_id = topic_url.split('/')[-1].split('/')[0] output_file = f'{topic_id}.xlsx' print(f"Scraping topic: {topic_id}") # Fetch first page to auto-detect total pages r = requests.get(topic_url) soup = BeautifulSoup(r.content, 'html5lib') ``` The same unvalidated destination is subsequently used for pagination: ```python for offset in tqdm(offsets, desc="Scraping", unit="page", dynamic_ncols=True): url = topic_url + '/+' + offset if offset else topic_url r = requests.get(url) ``` ### Technical Analysis The script accepts a URL directly from a command-line argument or interactive input and passes it to `requests.get()` without enforcing the documented `forum.lowyat.net` destination. There is no validation of: - The URL scheme. - The exact hostname. - Explicit URL credentials or nonstandard ports. - Loopback, private, link-local, or reserved destination addresses. - DNS resolution results. - Redirect destinations. - Response size or request timeout. Python Requests follows redirects by default. Consequently, validating only the initial URL would also be insufficient unless every redirect target were independently checked. Although the skill documentation says that the script is intended to access Lowyat Forum, this restriction is not implemented in the code. A caller can therefore cause the host executing the skill to send requests to arbitrary HTTP endpoints reachable from its network context. ### Attack Path 1. An attacker persuades the user or Agent to run the scraper with an attacker-selected URL. 2. The supplied URL ...[truncated 1657 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
datascraping.py:59
Finding

Untrusted Forum Content Is Written to Excel Without Formula Neutralization

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (10)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The code is a thread scraper/exporter for a specific Lowyat topic URL. It fetches pages of that thread, extracts post author, date, and comment text, and writes them to an .xlsx file. This partially matches the scraping-to-Excel portion of the description, but it does not implement topic research by searching the forum, selecting relevant threads, or analyzing the scraped results. The primary behavior is narrower than declared, so the description materially overstates the skill's capabilities.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill instructs use of networked capabilities (WebSearch, package installation, and running a scraper against a live site) but does not declare an explicit tool scope or permissions boundary. That creates ambiguity about what tools and network access are expected, increasing the risk of overbroad execution or unintended outbound access when the skill is invoked.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The activation criteria are overly broad, allowing the skill to trigger on generic Malaysian consumer research topics even when Lowyat-specific scraping is unnecessary. Overbroad routing can cause unintended web scraping, file creation, and data collection in contexts where a safer or simpler skill should be used.

Content

No source excerpt is available for this finding.

Tainted flow: 'topic_url' from input (line 15, user input) → requests.get (network output)

Medium
Category
Data Flow
Confidence
92% confidence
Finding

The script accepts an arbitrary URL from command-line input or stdin and fetches it with requests.get without validating that it belongs to forum.lowyat.net. This creates an SSRF-style capability: an agent or user can make the runtime send HTTP requests to unintended external or internal endpoints, which is more concerning because the skill is supposed to target only Lowyat forum research.

Content

Scanner excerpt · datascraping.py (reported line 23)May include surrounding context.

python
print(f"Scraping topic: {topic_id}")

# Fetch first page to auto-detect total pages
r = requests.get(topic_url)
soup = BeautifulSoup(r.content, 'html5lib')
last_offsets = re.findall(r'/topic/' + topic_id + r'/\+(\d+)', str(soup))
if last_offsets:

Tainted flow: 'url' from input (line 47, user input) → requests.get (network output)

Medium
Category
Data Flow
Confidence
95% confidence
Finding

Subsequent page fetches are built from the same untrusted base topic_url and then requested without restriction, so the entire pagination loop can be used to generate repeated outbound requests to attacker-controlled or sensitive destinations. Because this is a scraping skill, the behavior appears legitimate and could mask misuse for internal network probing or unwanted traffic generation.

Content

Scanner excerpt · datascraping.py (reported line 49)May include surrounding context.

python
for offset in tqdm(offsets, desc="Scraping", unit="page", dynamic_ncols=True):
    url = topic_url + '/+' + offset if offset else topic_url

    r = requests.get(url)
    soup = BeautifulSoup(r.content, 'html5lib')
    table = soup.find('div', attrs={'id': 'topic_content'})

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

The markdown describes producing .xlsx output files and appending to existing files, but it does not explicitly warn users that local files will be created and modified as part of execution. Because this behavior affects user data/storage, the skill description should disclose it more directly.

Content

No source excerpt is available for this finding.

Unverifiable Dependency: html5lib has 4 known advisory(ies) (CVE-2016-9910 (Cross-site Scripting in html5lib); CVE-2016-9909 (Improper Neutralization of Input During Web Page Generation in html5lib); CVE-2016-9909 (The serializer in html5lib before 0.99999999 might allow remote attackers to con) +1 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Content

No source excerpt is available for this finding.

Unverifiable Dependency: openpyxl has 2 known advisory(ies) (CVE-2017-5992 (Improper Restriction of XML External Entity Reference in Openpyxl); CVE-2017-5992 (Openpyxl 2.4.1 resolves external entities by default, which allows remote attack)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Content

No source excerpt is available for this finding.

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
71% confidence
Finding

Although requests is constrained to >=2.33.0, the package index does not currently provide a stable 2.33.0 release, so this spec may resolve unpredictably or fail until future versions exist. In a scraping skill that fetches attacker-controlled URLs or forum content, loose versioning around a historically security-sensitive HTTP library increases the chance of pulling an unintended release or missing security regression review.

Content

No source excerpt is available for this finding.

Unverifiable Dependency: tqdm has 4 known advisory(ies) (CVE-2024-34062 (tqdm CLI arguments injection attack); CVE-2016-10075 (TDQM Arbitrary Code Execution); CVE-2016-10075 (The tqdm._version module in tqdm versions 4.4.1 and 4.10 allows local users to e) +1 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.