Back to skill

Security audit

Expanso secrets-scan

Security checks for vulnerabilities and agentic risk

Overview

This secret-scanning skill has a legitimate purpose, but it sends sensitive scan input to OpenAI and exposes an unauthenticated network service without clear enough disclosure or controls.

Review this carefully before installing. Do not use it on production secrets, private code, logs, or regulated data unless your organization explicitly permits sending that content to OpenAI. If using MCP mode, bind it to localhost or put it behind authentication and rate limits. Treat the advertised local/no-key backend as unimplemented in the inspected pipelines.

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 (4)

other

Error
Location
pipeline-cli.yaml:29
Finding

Raw secrets and source content are transmitted to a remote LLM

Content
View full analysis
)\n- Environment variable references (${VAR})\n- Example values from documentation\n\nReturn valid JSON only.\n\nText to scan:\n```\n" + content() + "\n```" } ] - openai_chat_completion: api_key: "${OPENAI_API_KEY}" model: gpt-4o-mini ``` `pipeline-mcp.yaml:29-48`: ```yaml let secret_types = this.types.or(["api_key", "token", "password", "private_key"]).join(",") root.messages = [ { "role": "system", "content": "You are a security scanner specialized in detecting hardcoded secrets. Be thorough but avoid false positives. Do NOT flag placeholder values." }, { "role": "user", "content": "Scan for: " + $secret_types + "\n ...[truncated 2426 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
skill.yaml:13
Finding

Local-processing and optional-credential claims contradict the implemented behavior

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
pipeline-mcp.yaml:8
Finding

Unauthenticated MCP endpoint is exposed on all network interfaces

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
pipeline-cli.yaml:36
Finding

Prompt injection can suppress secret findings or force fail-open parsing

Content
View full analysis
)\n- Environment variable references (${VAR})\n- Example values from documentation\n\nReturn valid JSON only.\n\nText to scan:\n```\n" + content() + "\n```" } ] - openai_chat_completion: api_key: "${OPENAI_API_KEY}" model: gpt-4o-mini ``` `pipeline-cli.yaml:53-54`: ```yaml let raw = this.choices.0.message.content let parsed = $raw.parse_json().catch({"findings": [], "summary": "Parse error"}) ``` Equivalent vulnerable MCP construction and parsing are present at `pipeline-mcp.yaml:38-42` and `pipeline-mcp.yaml:50-51`: ```yaml "content": "Scan for: " + $secret_types + "\n\nReturn JSON:\n{\n \"findings\": [{\"type\": \"...\", \"value\": \"partial\", \"line\": 1, \"severity\": \"high|medium|low\"}],\n \"summary\": \"...\"\n}\n\nText:\n```\n" + $text + "\n```" ``` ```yaml let raw = this.choices.0.message.content let parsed = $raw.parse_json().catch({"findings": []}) ``` ### Technical Analysis Untrusted files and request text are concatenated directly into a natural ...[truncated 1730 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (7)

Natural-Language Policy Violations

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The prompt explicitly asks the model to return the full matched secret string, which causes any detected credential in stdin to be reproduced in the model response and then emitted to stdout as JSON. This increases exposure of sensitive values, creates a secondary exfiltration path to the external LLM provider, and can leak secrets into logs, terminals, downstream tooling, or saved command output.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The README encourages scanning arbitrary code, configs, and logs using a model-backed pipeline but does not clearly warn users that the scanned content may be transmitted to an external model service. Because this skill is specifically designed to process highly sensitive material such as secrets, users may unknowingly send credentials or proprietary code off-host, creating confidentiality and compliance risk.

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 · README.md (reported line 33)May include surrounding context.

bash
PORT=8080 expanso-edge run pipeline-mcp.yaml &

curl -X POST http://localhost:8080/scan \
  -H "Content-Type: application/json" \
  -d '{
    "text": "const API_KEY = \"sk-abc123def456\";",

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The pipeline exposes an HTTP service on 0.0.0.0 with a POST /scan endpoint and no visible authentication, authorization, or network restriction. Because the endpoint forwards arbitrary submitted text to an external LLM, an attacker can invoke the service remotely for unauthorized use, induce cost, and potentially exfiltrate sensitive submitted content to the model provider.

Content

No source excerpt is available for this finding.

Vague Triggers

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The manifest's commented usage shows the pipeline being run on any content piped to stdin, but it does not define narrower trigger conditions, exclusions, or negative examples. For a manifest file, this can make the activation scope ambiguous and increase the chance of unintended use on sensitive inputs.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

The prompt literal hard-codes English response fields and instructions such as "Return JSON" and fixed English keys/values, without offering any user language or locale choice. Under the policy, forcing a specific language without opt-in can be a natural-language policy violation unless clearly justified.

Content

No source excerpt is available for this finding.

Vague Triggers

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

This YAML manifest contains only a generic name and description for the skill tests, with no specific activation phrases, scope limits, or negative examples. For manifest files, that can make invocation conditions ambiguous because nothing in the file narrows when the skill should or should not activate.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.exposed_secret_literal

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
README.md:67

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
test/test.yaml:9