Back to skill

Security audit

scholar-search-aisa

Security checks for vulnerabilities and agentic risk

Overview

The skill is advertised as scholarly search, but it ships a broader networked search client that can send general queries, arbitrary URLs, and aggregated results to AISA services.

Install only if you are comfortable giving this skill an AISA API key and having it use a broader multi-search client than the scholar-search description suggests. Avoid using it with private URLs, presigned links, internal research systems, or sensitive queries unless the publisher narrows the runtime or documents these broader data flows clearly.

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)

other

Warning
Location
scripts/search_client.py:133
Finding

Bundled Client Exposes Undeclared Network and Data-Processing Capabilities

Content
View full analysis

Vulnerability Details

File Location: scripts/search_client.py:133-174, 258-269, 303-342; declared scope in SKILL.md:3, 27-31
Vulnerability Type: Excessive capability scope and undisclosed data transmission
Risk Level: Medium

The Skill declares scholarly paper and academic-source search as its purpose. However, its canonical client also exposes general web search, Tavily search, arbitrary URL extraction, Perplexity/Sonar queries, multi-source retrieval, and AI synthesis.

python
def cmd_tavily(args: argparse.Namespace) -> None:
    api_key = get_api_key()
    body: dict[str, Any] = {
        "query": args.query,
        "max_results": args.count,
        "search_depth": args.depth,
    }
    if args.topic:
        body["topic"] = args.topic
    if args.time_range:
        body["time_range"] = args.time_range
    if args.include_answer:
        body["include_answer"] = True
    data = aisa_post(api_key, "/tavily/search", body)
    print_results(data, "Tavily Search")


def cmd_extract(args: argparse.Namespace) -> None:
    api_key = get_api_key()
    urls = [u.strip() for u in args.urls.split(",")]
    data = aisa_post(api_key, "/tavily/extract", {"urls": urls})
    if "results" in data and isinstance(data["results"], list):
        for r in data["results"]:
            print(f"\n{'='*60}")
            print(f"  URL: {r.get('url', 'Unknown')}")
            print(f"{'='*60}")
            content = r.get("raw_content", "")
            print(content[:3000] if content else "(no content)")
    else:
        print(json.dumps(data, indent=2))


def cmd_sonar(args: argparse.Namespace) -> None:
    api_key = get_api_key()
    endpoint_map = {
        "sonar": "/sonar",
        "sonar-pro": "/sonar-pro",
        "sonar-reasoning-pro": "/sonar-reasoning-pro",
        "sonar-deep-research": "/sonar-deep-research",
    }
    endpoint = endpoint_map.get(args.model, "/sonar
...[truncated 2807 chars]
Remediation
View remediation

Remediation Suggestions

  1. Restrict this Skill’s parser and runtime to the scholar command and /scholar/search/scholar endpoint.
  2. Move web search, URL extraction, Sonar, Tavily, and multi-source synthesis into separately declared Skills that users must select explicitly.
  3. Update SKILL.md if broader capabilities are intentionally retained, listing every data type transmitted and all relevant remote-processing operations.
  4. Require explicit confirmation before processing user-supplied URLs or resubmitting provider responses for synthesis.
  5. Minimize synthesis payloads by sending only the fields needed to generate the summary rather than complete provider responses.
  6. Apply command-level authorization or allowlists so an agent loading a scholarly-search Skill cannot silently access unrelated paid endpoints.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/search_client.py:26
Finding

Bearer API Credential Is Not Protected Against Cross-Origin Redirects

Content
View full analysis

Vulnerability Details

File Location: scripts/search_client.py:26-49
Vulnerability Type: Authenticated request redirect weakness
Risk Level: Medium

python
def get_api_key() -> str:
    key = os.environ.get("AISA_API_KEY", "")
    if not key:
        print("Error: AISA_API_KEY environment variable is not set.", file=sys.stderr)
        print("Get your key at https://aisa.one", file=sys.stderr)
        sys.exit(1)
    return key


def aisa_post(api_key: str, path: str, body: dict[str, Any]) -> dict[str, Any]:
    url = f"{AISA_BASE}{path}"
    data = json.dumps(body).encode()
    req = urllib.request.Request(
        url,
        data=data,
        headers={
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json",
            "Accept": "application/json",
        },
        method="POST",
    )
    try:
        with urllib.request.urlopen(req, timeout=60) as resp:
            return json.loads(resp.read().decode())
    except urllib.error.HTTPError as e:
        body_text = e.read().decode() if e.fp else ""
        print(f"API error {e.code} on {path}: {body_text}", file=sys.stderr)
        return {"error": str(e), "status": e.code}

Technical Analysis

Sending AISA_API_KEY to https://api.aisa.one as bearer authentication is necessary for the declared service and is not, by itself, unauthorized exfiltration. The weakness is that urllib.request.urlopen uses automatic redirect handling, while the client does not validate the destination of redirects or enforce that every authenticated request remains on the original HTTPS origin.

Under redirect behavior that preserves request headers, a cross-origin redirect can cause the bearer credential to be included in a request to another host. Exploitation depends on the legitimate API endpoint, DNS or routing path, or an upstream component being compromised or misconfigured to retu ...[truncated 1292 chars]

Remediation
View remediation

Remediation Suggestions

  1. Disable automatic redirects for authenticated requests and handle redirect responses explicitly.
  2. If redirects are required, permit only HTTPS destinations whose normalized hostname is exactly api.aisa.one.
  3. Never forward the Authorization header when the scheme, hostname, or effective port changes.
  4. Reject HTTPS-to-HTTP downgrade redirects.
  5. Impose a small redirect limit and reject malformed, credential-bearing, or unexpected destination URLs.
  6. Add tests confirming that cross-origin redirects do not receive the bearer token.
  7. Support prompt key revocation and rotation so a potentially exposed credential can be invalidated quickly.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • 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
Findings (12)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared behavior is limited to academic paper search, but the referenced implementation reportedly supports broader web search, URL extraction, third-party search providers, model querying, and synthesis. This mismatch is dangerous because users and policy engines may trust the narrower description while the skill can access and process arbitrary external content through multiple services.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

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

md
## When NOT to Use

- Do not use this skill for browser-cookie extraction, passwords, Keychain access, or other local sensitive credential access.
- Prefer a different skill when the user request is outside this skill's domain.

## Capabilities

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The file is packaged as a scholar-search skill, but its documented and implemented behavior is a general multi-search client with web search, URL extraction, and deep-research/chat endpoints. This violates least privilege and creates a capability/expectation mismatch: callers or reviewers may authorize the skill for narrow academic lookup while it can exfiltrate arbitrary queries and fetch broader external content.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The implemented command set materially exceeds the declared scope by enabling non-academic web search, hybrid search, URL extraction, and Perplexity-style research calls. In an agent environment, this can bypass governance based on the skill metadata and allow unintended outbound data sharing or content retrieval under the guise of a scholar-only tool.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding

The skill declares access to an API key and uses a networked Python client, but it does not define any explicit tool scope such as allowed-tools or permissions. That creates an authorization gap where the runtime may permit broader actions than users would expect from the metadata, increasing the risk of unintended network use or environment access.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The module documentation explicitly brands the tool as a multi-search engine client, contradicting the narrower scholar-search metadata. This inconsistency is dangerous because operators, reviewers, or automated policy systems may rely on the manifest while the code advertises and provides broader capabilities.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

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

python
from concurrent.futures import ThreadPoolExecutor, as_completed
from typing import Any

AISA_BASE = "https://api.aisa.one/apis/v1"


def get_api_key() -> str:

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

Arbitrary URL extraction lets a user submit any URL to a remote extraction service, which is unrelated to a narrow scholarly search role. This broadens the skill into a generic content retrieval/exfiltration primitive and may cause sensitive internal, signed, or user-private URLs to be transmitted to a third party without appropriate review.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The extract path forwards user-supplied URLs to a remote API, which means potentially sensitive targets and retrieved content are transmitted outside the local environment. Without explicit disclosure or consent, users may not realize that private research links, presigned URLs, or internal resources are being shared with a third party.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The verity workflow performs aggregation across multiple external sources and sends retrieved results to an explain/synthesis endpoint, extending the skill from search into analysis and summarization. That increases outbound data flow and functional scope beyond the declared scholar-search purpose, making misuse and over-collection more likely in constrained environments.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

The manifest sets "language": "en", which is a natural-language locale constraint. There is no indication in this file that users can opt into other languages or that the English-only restriction is required for a documented region-specific purpose.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
96% confidence
Finding

The explain request explicitly sets "language": "en", which forces a specific language for generated output. The file does not offer a language option or explain why English is mandatory, so this is a natural-language locale policy concern.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.