Back to skill

Security audit

Wolfram Alpha (LLM API)

Security checks for vulnerabilities and agentic risk

Overview

This is a straightforward Wolfram|Alpha API wrapper, with disclosed network use, credential requirements, and local caching, but users should be careful with sensitive queries and non-default query-string authentication.

Install only if you are comfortable sending selected queries to Wolfram|Alpha. Keep the default bearer authentication, avoid --auth query, use --cache off for sensitive or time-sensitive requests, and avoid sending IP, latitude/longitude, or precise location unless it is necessary for the answer.

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/wa_llm.py:139
Finding

Wolfram AppID Exposure Through Query-Authentication Error Logging

Content
View full analysis

Vulnerability Details

File Location: scripts/wa_llm.py, lines 139–143 and 167–170
Vulnerability Type: Credential disclosure through sensitive URL logging
Risk Level: Medium

Vulnerable Code

python
# Auth
authorization: Optional[str] = None
if args.auth == "query":
    params.insert(0, ("appid", appid))
else:
    authorization = f"Bearer {appid}"

url = build_url(params)
python
# Non-2xx => signal failure for scripting.
exit_code = 0
if status >= 400:
    print(f"\n\n[wa_llm] HTTP {status} for URL: {url}", file=sys.stderr)
    exit_code = 1

Technical Analysis

When the user selects --auth query, the Wolfram AppID is inserted into the URL as the appid query parameter. If the API returns an HTTP error, the complete URL is printed to standard error without redaction.

Although bearer authentication is the default, query authentication is an explicitly supported mode. Standard error is commonly captured by CI systems, agent execution transcripts, shell redirection, centralized logging systems, and monitoring tools. Consequently, an API error can cause the credential to be retained in systems with a broader readership and a longer retention period than the original process environment.

TLS protects the request in transit, but it does not prevent disclosure through local or centralized logs generated by this code.

Attack Path

  1. A user or automation process invokes the wrapper with --auth query.
  2. The script reads WOLFRAM_APP_ID and embeds it in the request URL.
  3. An HTTP failure is triggered, such as by supplying invalid parameters, using an invalid or quota-exhausted AppID, or receiving a service-side error.
  4. The script writes the full URL, including the appid value, to standard error.
  5. Standard error is captured in an agent transcript, CI log, terminal history capture, or centralized logging service.
  6. An individual with access to those log ...[truncated 533 chars]
Remediation
View remediation

Remediation Suggestions

  1. Never log a URL that may contain credentials. Log only the HTTP status, hostname, and path.
  2. Redact sensitive query parameters before logging. At minimum, replace the value of appid with [REDACTED].
  3. Preferably remove --auth query and exclusively use the Authorization header.
  4. If query authentication must remain for compatibility, construct a separately sanitized diagnostic URL rather than printing the request URL.
  5. Add automated tests that verify the AppID never appears in stdout, stderr, exceptions, or cached data.

A safer error message would be:

python
if status >= 400:
    print(
        f"\n\n[wa_llm] HTTP {status} from Wolfram|Alpha LLM API",
        file=sys.stderr,
    )
    exit_code = 1

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/wa_llm.py:96
Finding

Sensitive API Responses Are Cached in Plaintext by Default

Content
View full analysis

Vulnerability Details

File Location: scripts/wa_llm.py, lines 96–107, 145–158, and 173–178
Vulnerability Type: Insecure local storage of potentially sensitive information
Risk Level: Medium

Vulnerable Code

python
# Cache
p.add_argument(
    "--cache",
    choices=["off", "on"],
    default="on",
    help="Enable a small local cache to save WA quota for repeated requests",
)
p.add_argument(
    "--cache-ttl",
    type=int,
    default=604800,
    help="Cache TTL seconds (default 604800 = 7d)",
)
python
# Cache key should include full URL + auth mode (but not the secret itself).
cache_enabled = args.cache == "on"
# Prefer a stable, explicit cache path (avoid surprising XDG overrides).
cache_dir = Path.home() / ".cache" / "openclaw-wolfram-alpha"
cache_key_material = json.dumps({"url": url, "auth": args.auth}, sort_keys=True).encode("utf-8")
cache_key = hashlib.sha256(cache_key_material).hexdigest()
cache_path = cache_dir / f"{cache_key}.json"

if cache_enabled:
    try:
        if cache_path.exists():
            data = json.loads(cache_path.read_text(encoding="utf-8"))
            age = time.time() - float(data.get("ts", 0))
            if age <= int(args.cache_ttl):
                sys.stdout.write(str(data.get("body", "")))
                return int(data.get("exit_code", 0))
    except Exception:
        # Cache is best-effort; ignore failures.
        pass
python
if cache_enabled:
    try:
        cache_dir.mkdir(parents=True, exist_ok=True)
        payload = {"ts": time.time(), "status": status, "body": body, "exit_code": exit_code}
        cache_path.write_text(json.dumps(payload, ensure_ascii=False), encoding="utf-8")
    except Exception:
        pass

Technical Analysis

Caching is enabled by default with a seven-day time-to-live. The complete API response body is serialized to a plaintext JSON file unde ...[truncated 2029 chars]

Remediation
View remediation

Remediation Suggestions

  1. Disable caching by default, especially because the wrapper accepts arbitrary user queries:
    python
    default="off"
    
  2. Require explicit user consent before caching location-aware, financial, or otherwise sensitive requests.
  3. Create the cache directory with mode 0700 and cache files with mode 0600, without relying on the process umask.
  4. Write cache entries atomically through a securely created temporary file, then replace the destination.
  5. Delete expired entries rather than merely declining to return them.
  6. Provide a documented cache-clearing command or option.
  7. Consider encrypting cached responses where the execution environment provides an appropriate protected key store.
  8. Do not cache error responses by default, because they may contain echoed request data or service diagnostics.
  9. Document that API responses are persisted locally, the retention period, the storage location, and the associated privacy implications.

Example permission hardening:

python
cache_dir.mkdir(parents=True, exist_ok=True, mode=0o700)
os.chmod(cache_dir, 0o700)

flags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC
fd = os.open(cache_path, flags, 0o600)
with os.fdopen(fd, "w", encoding="utf-8") as cache_file:
    json.dump(payload, cache_file, ensure_ascii=False)
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 (8)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill advertises and relies on capabilities that include environment access, filesystem reads/writes, and outbound network access, but it does not declare an explicit tool scope such as permissions or allowed-tools. That creates an avoidable least-privilege gap: an agent may invoke the skill without clear sandboxing expectations, increasing the blast radius if the wrapper script is modified, misused, or combined with sensitive user inputs.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill instructs the agent to send user queries and optionally precise contextual data such as IP, latitude/longitude, location, timezone, country, language, and currency to a third-party HTTP API, but it does not require an explicit user-facing privacy notice or consent step. This is dangerous because users may unknowingly disclose sensitive personal, financial, or location information to an external service, especially when the skill encourages context enrichment for better results.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The script persistently caches full query URLs and returned bodies on disk, even though user queries may contain sensitive data such as locations, finance questions, medical topics, or proprietary calculations. Because caching is enabled by default and there is no disclosure or access control around the cache, this creates unnecessary local data retention and exposure beyond the stated purpose of making API requests.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The default-on cache can return previously stored results for up to 7 days without contacting Wolfram|Alpha, which conflicts with the skill's promise of fresh, verified lookups. For time-sensitive facts, financial values, or changing data, this can silently produce stale answers that users may incorrectly trust as current.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The tool sends user-supplied query content and optional contextual parameters like IP, lat/long, semantic location, timezone, currency, and country code to a remote service, but provides no runtime warning or explicit consent mechanism. In this skill context, those parameters can reveal sensitive personal or business information, and the transmission is central to the feature but insufficiently disclosed.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script writes remote query/response-derived data to a persistent local cache without clearly informing the user that their inputs and returned content will remain on disk. In a tool meant for factual lookups and computations, this increases the risk of inadvertent retention of sensitive prompts, derived business data, or personal context on shared systems.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill enables caching by default and states that results are stored under the user's home cache directory, but it does not clearly warn that query results persist on disk. This can expose sensitive prompts, derived facts, or regulated data to other local users, backups, forensics, or later unintended reuse, particularly on shared systems.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
64% confidence
Finding

The inline comment presents the fixed cache location as a deliberate behavioral choice, but that intent is not reflected in the module docstring or manifest and materially changes how local data is stored. While not a direct contradiction of code behavior, it documents an opinionated persistence decision that is inconsistent with the otherwise simple API-wrapper description.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.