Back to skill

Security audit

Mfapi

Security checks for vulnerabilities and agentic risk

Overview

This skill is a straightforward MFapi.in lookup helper, with disclosed external API use and local caching, but its temporary cache handling should be treated cautiously on shared systems.

Install only if you are comfortable sending fund search terms, scheme codes, and ISINs to MFapi.in. On shared or multi-user machines, prefer changing the script to store its cache in a private per-user cache directory instead of /tmp before relying on ISIN lookup results.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/get_nav.py:19
Finding
Predictable Shared Cache File Allows Symlink-Based File Overwrite and Cache Poisoning<![CDATA[ ## Vulnerability Details **File Location**: `scripts/get_nav.py`, lines 19–36 **Vulnerability Type**: Unsafe temporary file handling **Risk Level**: Medium ### Vulnerable Code ```python CACHE_PATH = Path("/tmp/mfapi-schemes.json") CACHE_MAX_AGE = 86400 # 24 hours in seconds def load_cache() -> List[Dict[str, Any]]: """Load scheme list from cache, refreshing if stale or missing.""" if CACHE_PATH.exists() and (time.time() - CACHE_PATH.stat().st_mtime) < CACHE_MAX_AGE: with open(CACHE_PATH) as f: return json.load(f) return refresh_cache() def refresh_cache() -> List[Dict[str, Any]]: """Download full scheme list and write to cache.""" data = api_get("/mf") CACHE_PATH.write_text(json.dumps(data)) return data ``` ### Technical Analysis The script stores cached API data at the fixed path `/tmp/mfapi-schemes.json`. On multi-user systems, `/tmp` is normally writable by every local user. Although the directory commonly has the sticky bit enabled, that does not prevent an attacker from creating a previously nonexistent file or symbolic link at this predictable path. The script does not: - Verify that the cache is a regular file rather than a symbolic link. - Verify that the cache is owned by the current user. - Apply restrictive file permissions explicitly. - Create the cache through an exclusive, race-resistant operation. - Write to a securely created temporary file and atomically replace the cache. - Protect the check-and-use sequence from time-of-check/time-of-use races. `Path.write_text()` follows an existing symbolic link. Therefore, during a cache refresh, a malicious link can redirect the write to another file writable by the victim account. The cache-reading path also accepts any sufficiently recent JSON file at the shared location, allowing another local user to supply forged scheme records. ### Attack Path #### Symlink-based file overwrite 1. A local attacker predicts the fixed cache path ` ...[truncated 1923 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Store the cache in a private, per-user cache directory, such as `$XDG_CACHE_HOME/mfapi` or `~/.cache/mfapi`, rather than directly under shared `/tmp`. 2. Create the cache directory with mode `0700` and verify that it is owned by the current user. 3. Before reading an existing cache, use `lstat()` to reject symbolic links and verify that the object is a regular file owned by the current user. 4. Write updates to a securely created temporary file in the same private directory, set its mode to `0600`, flush and synchronize it as appropriate, and atomically install it with `os.replace()`. 5. Avoid separate existence, metadata, and open operations where possible, because those operations introduce time-of-check/time-of-use race conditions. 6. Validate the decoded cache structure before trusting it. Confirm that the top-level value is a list and that each accepted record contains fields of the expected types. 7. Handle invalid, unreadable, or unexpectedly owned cache files by rejecting and securely recreating them rather than trusting their contents. A hardened design should resemble the following: ```python import os import stat import tempfile from pathlib import Path CACHE_DIR = Path(os.environ.get("XDG_CACHE_HOME", Path.home() / ".cache")) / "mfapi" CACHE_PATH = CACHE_DIR / "schemes.json" def prepare_cache_dir(): CACHE_DIR.mkdir(mode=0o700, parents=True, exist_ok=True) info = CACHE_DIR.stat() if info.st_uid != os.getuid() or not stat.S_ISDIR(info.st_mode): raise RuntimeError("Unsafe cache directory") def write_cache_atomically(data): prepare_cache_dir() fd, temporary_name = tempfile.mkstemp(dir=CACHE_DIR, prefix=".schemes-", text=True) try: os.fchmod(fd, 0o600) with os.fdopen(fd, "w") as output: json.dump(data, output) output.flush() os.fsync(output.fileno()) os.replace(temporary_name, CACHE_PATH) except Exception: try: ...[truncated 244 chars]
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • 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 (16)

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding
The documented purpose is general MF API querying, but the skill also describes undeclared local caching and ISIN-based resolution behavior, which materially changes its data handling footprint. Description-behavior mismatches are dangerous because reviewers and users may authorize a seemingly read-only query skill without realizing it writes local files or performs broader retrieval logic.

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill documents network access to an external API and local file writes to /tmp via the ISIN cache, but it does not declare any tool scope or permissions for those capabilities. This creates a transparency and policy-enforcement gap: consumers cannot easily understand or constrain what the skill is allowed to do, and a runner may permit broader behavior than intended.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
```bash
# Debian/Ubuntu
sudo apt install -y curl jq

# macOS
brew install curl jq
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

External Transmission

Medium
Category
Data Exfiltration
Content
### Search schemes by name

```bash
curl -s "https://api.mfapi.in/mf/search?q=HDFC" | jq '.[] | {schemeCode, schemeName}'
```

### List all schemes (paginated)
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
### Search schemes by name

```bash
curl -s "https://api.mfapi.in/mf/search?q=HDFC" | jq '.[] | {schemeCode, schemeName}'
```

### List all schemes (paginated)
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
### Search schemes by name

```bash
curl -s "https://api.mfapi.in/mf/search?q=HDFC" | jq '.[] | {schemeCode, schemeName}'
```

### List all schemes (paginated)
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
### Search schemes by name

```bash
curl -s "https://api.mfapi.in/mf/search?q=HDFC" | jq '.[] | {schemeCode, schemeName}'
```

### List all schemes (paginated)
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
### Search schemes by name

```bash
curl -s "https://api.mfapi.in/mf/search?q=HDFC" | jq '.[] | {schemeCode, schemeName}'
```

### List all schemes (paginated)
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
### Search schemes by name

```bash
curl -s "https://api.mfapi.in/mf/search?q=HDFC" | jq '.[] | {schemeCode, schemeName}'
```

### List all schemes (paginated)
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
### Search schemes by name

```bash
curl -s "https://api.mfapi.in/mf/search?q=HDFC" | jq '.[] | {schemeCode, schemeName}'
```

### List all schemes (paginated)
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
### Search schemes by name

```bash
curl -s "https://api.mfapi.in/mf/search?q=HDFC" | jq '.[] | {schemeCode, schemeName}'
```

### List all schemes (paginated)
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
### Search schemes by name

```bash
curl -s "https://api.mfapi.in/mf/search?q=HDFC" | jq '.[] | {schemeCode, schemeName}'
```

### List all schemes (paginated)
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
### Search schemes by name

```bash
curl -s "https://api.mfapi.in/mf/search?q=HDFC" | jq '.[] | {schemeCode, schemeName}'
```

### List all schemes (paginated)
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
### Search schemes by name

```bash
curl -s "https://api.mfapi.in/mf/search?q=HDFC" | jq '.[] | {schemeCode, schemeName}'
```

### List all schemes (paginated)
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Description-Behavior Mismatch

Low
Confidence
95% confidence
Finding
The manifest describes broader functionality including scheme information and historical data access. This file's documented usage and implementation are limited to looking up the latest NAV by ISIN via /mf and /mf/{scheme_code}/latest, without any support for history queries or general scheme-info retrieval beyond fields incidental to the latest-NAV response.

Missing User Warnings

Low
Confidence
86% confidence
Finding
This code sends data derived from user input to https://api.mfapi.in via an HTTP request, but there is no print/log message or other runtime disclosure informing the user that their queried ISIN will be sent to a third-party service. While the module docstring names MFapi.in, the execution path itself provides no explicit warning about outbound data transmission.

Static analysis

No suspicious patterns detected.