Back to skill

Security audit

Perplexity AI Search - security-hardened version (bash-based)

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent Perplexity search skill, but it needs review because it grants unrelated GitHub fetch permissions and handles the API key in a way that can affect curl behavior if the key source is compromised.

Review before installing. Only use this skill with a trusted Perplexity API key source, avoid sending secrets or private context in queries or custom system prompts, and remove the unrelated GitHub WebFetch permissions unless you have a separate documented need for them.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/perplexity_search.sh:168
Finding

Curl Configuration Injection Through Unvalidated API Key

Content
View full analysis
/dev/null || echo "") if [[ -n "$config_key" ]]; then echo "$config_key" return fi fi # 2. Try environment variable if [[ -n "${PERPLEXITY_API_KEY:-}" ]]; then echo "$PERPLEXITY_API_KEY" return fi echo "" } ``` ```bash CURL_CONFIG_FILE=$(mktemp) chmod 600 "$CURL_CONFIG_FILE" trap 'rm -f "$CURL_CONFIG_FILE"' EXIT cat > "$CURL_CONFIG_FILE" <
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
.claude/settings.local.json:3
Finding

Unnecessary GitHub WebFetch Permissions Violate Least Privilege

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (8)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
60% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

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

md
1. **No command injection** - User input is passed to Python via environment variables, never interpolated into code strings
2. **Input validation** - All parameters are validated (numeric ranges, allowed model names, allowed context values)
3. **API key protection** - The Authorization header is passed to curl via a temporary config file (`curl -K`, mode 600) and the request body via stdin (`--data @-`), so neither the API key nor the body appear in process listings (`ps aux`)
4. **Query length limit** - Queries are capped at 8000 characters to prevent denial-of-wallet attacks
5. **Strict model allowlist** - Only known valid models are accepted

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · scripts/perplexity_search.sh (reported line 255)May include surrounding context.

sh
# --- Make API request ---
# SECURITY: Both the request body and the Authorization header are passed via
# file descriptors / stdin, so neither appears in process listings (ps aux).
# We write curl config to a temp file (mode 600) containing the auth header,
# then pass the body via --data @<fd>.

CURL_CONFIG_FILE=$(mktemp)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
76% confidence
Finding

The script writes an Authorization: Bearer ... header into a temporary curl config file. Although permissions are restricted and cleanup is attempted, secrets at rest on disk can still be exposed through race conditions, crash leftovers, local filesystem monitoring, backups, or execution in less-trusted environments; in a skill context this could leak the Perplexity API key and enable unauthorized use.

Content

Scanner excerpt · scripts/perplexity_search.sh (reported line 255)May include surrounding context.

sh
# --- Make API request ---
# SECURITY: Both the request body and the Authorization header are passed via
# file descriptors / stdin, so neither appears in process listings (ps aux).
# We write curl config to a temp file (mode 600) containing the auth header,
# then pass the body via --data @<fd>.

CURL_CONFIG_FILE=$(mktemp)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill advertises shell and environment-variable based operation but does not declare any explicit tool scope such as allowed-tools or permissions. That creates an authorization gap where an agent may invoke shell/network-capable behavior without a narrowly declared execution boundary, increasing the chance of over-broad tool use and secret exposure.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
79% confidence
Finding

This skill is explicitly designed to transmit user queries and an API credential to an external third-party service via curl. Even if implemented carefully, that is still a real data egress path: sensitive user prompts, system prompts, and derived context may leave the local environment and be processed by an external provider.

Content

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

md
1. **No command injection** - User input is passed to Python via environment variables, never interpolated into code strings
2. **Input validation** - All parameters are validated (numeric ranges, allowed model names, allowed context values)
3. **API key protection** - The Authorization header is passed to curl via a temporary config file (`curl -K`, mode 600) and the request body via stdin (`--data @-`), so neither the API key nor the body appear in process listings (`ps aux`)
4. **Query length limit** - Queries are capped at 8000 characters to prevent denial-of-wallet attacks
5. **Strict model allowlist** - Only known valid models are accepted

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/perplexity_search.sh (reported line 15)May include surrounding context.

sh
set -euo pipefail

# Configuration
PERPLEXITY_API_URL="https://api.perplexity.ai/chat/completions"

# Allowed models (allowlist)
ALLOWED_MODELS=("sonar" "sonar-pro" "sonar-reasoning" "sonar-reasoning-pro")

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% 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/perplexity_search.sh (reported line 255)May include surrounding context.

sh
# --- Make API request ---
# SECURITY: Both the request body and the Authorization header are passed via
# file descriptors / stdin, so neither appears in process listings (ps aux).
# We write curl config to a temp file (mode 600) containing the auth header,
# then pass the body via --data @<fd>.

CURL_CONFIG_FILE=$(mktemp)

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/perplexity_search.sh (reported line 259)May include surrounding context.

sh
# then pass the body via --data @<fd>.

CURL_CONFIG_FILE=$(mktemp)
chmod 600 "$CURL_CONFIG_FILE"
trap 'rm -f "$CURL_CONFIG_FILE"' EXIT

cat > "$CURL_CONFIG_FILE" <<EOF

Static analysis

No suspicious patterns detected.