Back to skill

Security audit

Qryma Search

Security checks for vulnerabilities and agentic risk

Overview

This is a real web-search skill, but it handles API keys in ways that need review before installation.

Review this skill before installing. Use an environment variable or a carefully permissioned config file for the API key, do not paste real API keys into chat, do not run it from untrusted directories containing .env files, and avoid setting QRYMA_ENDPOINT unless you fully trust the destination.

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

Error
Location
scripts/qryma_search.py:45
Finding

Arbitrary API Endpoint Allows Qryma Credential and Search Query Exfiltration

Content
View full analysis
str: """Load Qryma API endpoint""" # Load from environment variable endpoint = os.environ.get("QRYMA_ENDPOINT") if endpoint: return endpoint.strip() # Load from config file env_path = os.path.expanduser("~/.qryma/.env") if not os.path.exists(env_path): env_path = ".env" if os.path.exists(env_path): try: with open(env_path, "r", encoding="utf-8", errors="ignore") as f: txt = f.read() m = re.search(r"^\s*QRYMA_ENDPOINT\s*=\s*(.+?)\s*$", txt, re.M) if m: v = m.group(1).strip().strip('"').strip("'") if v: return v except Exception: pass ``` ```python payload = { "query": query, "lang": lang, "safe": safe, "mode": mode, "max_results": max_results, } data = json.dumps(payload).encode("utf-8") req = urllib.request.Request( self.endpoint, data=data, headers={ "Content-Type": "application/json", "Accept": "application/json", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", "X-Api-Key": self.api_key, }, method="POST", ) with urllib.request.urlopen(req, timeout=30) as resp: body = resp.read().decode("utf-8", errors="replace") ``` ### Technical Analysis The script accepts `QRYMA_ENDPOINT` without validating its scheme, hostname, port, or relationship to the trusted Qryma service. The endpoint may come from either the process environment or `~/.qryma/.env`. If the user-level configuration does not exist, the script also trusts a `.env` file in the current working directory. Every search req ...[truncated 2764 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (9)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/qryma_search.py (reported line 26)May include surrounding context.

python
return key.strip()

    # Load from config file
    env_path = os.path.expanduser("~/.qryma/.env")
    if not os.path.exists(env_path):
        env_path = ".env"
    if os.path.exists(env_path):

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/qryma_search.py (reported line 28)May include surrounding context.

python
return key.strip()

    # Load from config file
    env_path = os.path.expanduser("~/.qryma/.env")
    if not os.path.exists(env_path):
        env_path = ".env"
    if os.path.exists(env_path):

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/qryma_search.py (reported line 52)May include surrounding context.

python
return key.strip()

    # Load from config file
    env_path = os.path.expanduser("~/.qryma/.env")
    if not os.path.exists(env_path):
        env_path = ".env"
    if os.path.exists(env_path):

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/qryma_search.py (reported line 54)May include surrounding context.

python
return key.strip()

    # Load from config file
    env_path = os.path.expanduser("~/.qryma/.env")
    if not os.path.exists(env_path):
        env_path = ".env"
    if os.path.exists(env_path):

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill advertises capabilities that involve environment access, file reads, and network use, but it does not declare any explicit tool scope such as permissions or allowed-tools. This weakens least-privilege controls and makes it harder for a host agent or reviewer to understand and constrain what the skill may access at runtime.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The setup text explicitly instructs users to send their API key to an AI assistant for automatic configuration, in both English and Chinese. This encourages direct credential disclosure to an LLM-mediated system, where the secret may be logged, retained in chat history, exposed to other tools, or mishandled by downstream integrations.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
81% confidence
Finding

The documentation recommends storing the API key in a persistent plaintext file under ~/.qryma/.env. While common, persistent local secret storage increases exposure if the file permissions are weak, the host is multi-user, backup/sync software captures the file, or other tools can read home-directory configuration files.

Content

Scanner excerpt · SKILL.md (reported line 53)May include surrounding context.

Option 2 - Config File

Create ~/.qryma/.env with:

text
QRYMA_API_KEY=your-key-here

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill sends user search queries, language, safe-search preference, mode, and result count to a third-party remote service, but the code contains no user-facing disclosure or consent mechanism. In an agent-skill context, queries may contain sensitive prompts, internal URLs, or proprietary data, so silent exfiltration to an external API creates a real privacy and data-handling risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

The skill reads an API key from the QRYMA_API_KEY environment variable and from ~/.qryma/.env or .env, but the code provides no user-facing notice that it accesses credential material from local environment/config sources. Access to sensitive environment variables or credentials is in scope for this rule when there is no visible disclosure.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.