Back to skill

Security audit

Felo Slides

Security checks for vulnerabilities and agentic risk

Overview

This slide-generation skill mostly matches its purpose, but it can send the user's prompt and Felo API key to an environment-selected API host that is not documented or constrained.

Review before installing. Use this skill only when you intend to send slide content to Felo, avoid prompts containing secrets or sensitive personal/business data, and ensure FELO_API_BASE is unset or locked to the official Felo API host before using a real FELO_API_KEY.

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/run_ppt_task.mjs:132
Finding

Arbitrary API Base Override Enables API Key and Prompt Exfiltration

Content
View full analysis

Vulnerability Details

File Location: scripts/run_ppt_task.mjs, lines 132–180
Vulnerability Type: Unvalidated network destination for sensitive data
Risk Level: High

Vulnerable Code

js
async function createTask(apiKey, apiBase, query, timeoutMs) {
  const payload = await fetchJson(
    `${apiBase}/v2/ppts`,
    {
      method: 'POST',
      headers: {
        Accept: 'application/json',
        Authorization: `Bearer ${apiKey}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ query }),
    },
    timeoutMs
  );
  const data = payload?.data ?? {};
  if (!data.task_id) {
    throw new Error('Unexpected response: missing task_id');
  }
  return data;
}

async function queryHistorical(apiKey, apiBase, taskId, timeoutMs) {
  const payload = await fetchJson(
    `${apiBase}/v2/tasks/${encodeURIComponent(taskId)}/historical`,
    {
      method: 'GET',
      headers: {
        Accept: 'application/json',
        Authorization: `Bearer ${apiKey}`,
      },
    },
    timeoutMs
  );
  return payload?.data ?? {};
}

async function main() {
  const args = parseArgs(process.argv.slice(2));
  if (args.help) {
    usage();
    process.exit(0);
  }
  if (!args.query) {
    usage();
    process.exit(1);
  }

  const apiKey = process.env.FELO_API_KEY?.trim();
  if (!apiKey) {
    console.error('ERROR: FELO_API_KEY not set');
    process.exit(1);
  }

  const apiBase = (process.env.FELO_API_BASE?.trim() || DEFAULT_API_BASE).replace(/\/$/, '');

Technical Analysis

The documented destination for this Skill is the fixed Felo API origin, https://openapi.felo.ai. However, the implementation permits the FELO_API_BASE environment variable to replace that origin without validating its scheme, hostname, port, or trust level.

Both createTask() and queryHistorical() attach the production `FELO_API_K ...[truncated 2324 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove the FELO_API_BASE override and always use the fixed official origin:

    js
    const apiBase = 'https://openapi.felo.ai';
    
  2. If endpoint configurability is operationally required, parse and validate the URL before making any request:

    js
    const OFFICIAL_API_ORIGIN = 'https://openapi.felo.ai';
    const candidate = new URL(
      process.env.FELO_API_BASE?.trim() || OFFICIAL_API_ORIGIN
    );
    
    if (candidate.origin !== OFFICIAL_API_ORIGIN) {
      throw new Error('FELO_API_BASE must use the official Felo API origin');
    }
    
    const apiBase = candidate.origin;
    
  3. Require HTTPS explicitly and reject alternate protocols, embedded credentials, unexpected ports, and hostname suffix tricks. Exact origin comparison is preferable to suffix matching.

  4. Bind credential attachment to the approved origin inside the request helper. Before adding the Authorization header, verify that the final request URL uses the exact trusted origin. This provides defense in depth if URL construction changes later.

  5. Do not follow cross-origin redirects while carrying authorization credentials. Configure redirect handling explicitly and reject redirects to any origin other than the approved Felo API.

  6. If a non-production endpoint is genuinely needed for testing, require an explicit development mode and separate test credentials. Production FELO_API_KEY values must never be sent to custom endpoints.

  7. Document that presentation prompts are transmitted to Felo and advise users not to include secrets or regulated data unless approved under their organization’s data-handling policy.

  8. Rotate any API key that may have been used while FELO_API_BASE pointed to an untrusted destination, and review associated API activity for unauthorized use.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (5)

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill does not clearly warn that the user's prompt will be transmitted to a third-party API for processing. This creates a meaningful privacy and data-handling risk because users may include confidential notes, internal plans, or regulated data in slide-generation requests without informed consent.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill instructs the agent to read an environment variable and make external network calls, but it declares no explicit tool scope or permissions boundary. This increases the chance the skill is invoked with broader-than-necessary capabilities, making secret access and data egress less transparent and harder to govern.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The trigger conditions are broad enough to auto-activate on many ordinary presentation-related requests, which can cause user content to be sent to the external Felo service without a clear, narrow invocation boundary. In this skill, over-triggering is more dangerous because execution includes network transmission of arbitrary user prompts to a third party.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

The trigger keywords explicitly call out Chinese prompts alongside English phrases, but the skill does not explain language-selection behavior or offer opt-in/choice for locale handling. This can create a language-policy issue because it bakes in language-specific activation rules without clarifying user preference or necessity.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The script sends the user-supplied slide prompt directly to a third-party API without any user-facing disclosure, confirmation, or sanitization boundary. In a coding-agent skill, prompts may contain sensitive business data, credentials, or proprietary content, so silent transmission to an external service creates a real privacy and data-handling risk even if the network call is functionally required.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.env_credential_access

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/run_ppt_task.mjs:178