Back to skill

Security audit

Agent Crypto Lens

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a normal crypto analysis skill, but it sends analysis data to external services and has some output-integrity and disclosure gaps.

Install only if you are comfortable with token queries, market/news context, and generated prompts being sent to third-party APIs. Configure restricted API keys, avoid submitting secrets or private investment information, treat the reports as informational rather than financial advice, and consider updating dependencies and adding stronger validation before production use.

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

T09 · Insecure Skill Coding Practices

Warning
Location
src/analyzer.ts:25
Finding

Indirect Prompt Injection Through Untrusted Token and News Content

Content
View full analysis
0 ? news.map((n, i) => `[${i + 1}] ${n.title}: ${n.content}`).join('\n') : '뉴스 데이터 없음'; const marketText = market.current_price_usd ? `현재가: $${market.current_price_usd}, 24h 변동: ${market.price_change_24h_pct?.toFixed(2)}%` : '시장 데이터 없음'; const systemPrompt = `크립토 센티먼트 분석 전문가입니다. 주어진 뉴스와 시장 데이터를 분석하여 반드시 아래 JSON 형식으로만 응답하십시오. 순수 JSON만 출력하고 다른 텍스트는 절대 포함하지 마십시오. { "score": 0~100 사이 정수 (0=매우 부정, 50=중립, 100=매우 긍정), "label": "Bullish 또는 Neutral 또는 Bearish", "summary": "센티먼트 판단 근거를 3문장으로 한국어로 설명" }`; const userMessage = `토큰: ${token}\n시장 데이터: ${marketText}\n\n뉴스:\n${newsText}`; ``` The generated summary is subsequently inserted into another prompt: ```ts const userMessage = `토큰: ${token}\n시장 데이터: ${marketText}\n센티먼트: ${sentiment.label} (점수: ${sentiment.score})\n센티먼트 분석: ${sentiment.summary}`; ``` ### Technical Analysis The `token`, news titles, and news contents are untrusted data. News content originates from Tavily search results, while the token value originates from the job payload. These values are concatenated directly into an LLM user message without robust data boundaries or an explicit instruction that embedded commands must be ignored. An attacker can publish search-indexed content containing instructions such as requests to disregard the system prompt, emit attacker-selected JSON, or manipulate sentiment scores. If Tavily returns that content for a token-related query, it becomes part of the model prompt. The risk is amplified because the free-form `summary` produced by the first model invocation is passed into a second invocation. Instructions retained in that summary can therefore influence both sentiment analysis and final report generation. ...[truncated 1408 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
src/llm/gemini.ts:18
Finding

Gemini API Credential Included in Request URL

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
src/handler.ts:7
Finding

Missing Runtime Validation for Job Payload

Content
View full analysis
{ const agentId = 'crypto-lens'; const jobId = `job-${Date.now()}`; const input = payload as CryptoLensInput; // 단계 1: token 필수값 확인 if (!input.token || input.token.trim() === '') { return makeError(agentId, jobId, 'token 필드가 필요합니다.'); } const token = input.token.trim(); const analysisType = input.analysis_type ?? 'full'; ``` ### Technical Analysis The incoming payload is declared as `unknown`, but it is converted to `CryptoLensInput` using a TypeScript assertion. Type assertions are removed during compilation and do not validate runtime values. If the payload is `null` or `undefined`, accessing `input.token` throws. If `token` is a truthy non-string value, calling `.trim()` throws. Additionally, `analysis_type` is not checked against the declared `market`, `sentiment`, and `full` values. An unsupported value can skip both market and news collection while still triggering LLM analysis and report generation. There is also no maximum token length, allowing oversized values to increase search and LLM request sizes and associated processing costs. ### Attack Path 1. An untrusted caller submits a malformed payload such as `null`, `{ "token": {} }`, or a payload with an excessively large token string. 2. The TypeScript assertion accepts the value without runtime checks. 3. Property access or `.trim()` throws for malformed types, causing the job to fail outside the intended structured validation response. 4. Alternatively, an oversized string is propagated to Tavily and the LLM, increasing processing time, token use, and external API costs. 5. An invalid `analysis_type` can also create inconsistent behavior by bypassing expected data collection branches. ...[truncated 423 chars]
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
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (34)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

If the skill lacks actual crypto market collection, sentiment analysis, and processing logic, but only defines a generic LLM interface, then the published purpose is materially misleading. Misrepresentation is security-relevant because it can bypass scrutiny for a broad-capability tool, causing users to disclose data and operators to grant permissions under false assumptions about what the skill really does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

If the skill lacks actual crypto market collection, sentiment analysis, and processing logic, but only defines a generic LLM interface, then the published purpose is materially misleading. Misrepresentation is security-relevant because it can bypass scrutiny for a broad-capability tool, causing users to disclose data and operators to grant permissions under false assumptions about what the skill really does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

If the skill lacks actual crypto market collection, sentiment analysis, and processing logic, but only defines a generic LLM interface, then the published purpose is materially misleading. Misrepresentation is security-relevant because it can bypass scrutiny for a broad-capability tool, causing users to disclose data and operators to grant permissions under false assumptions about what the skill really does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

If the skill lacks actual crypto market collection, sentiment analysis, and processing logic, but only defines a generic LLM interface, then the published purpose is materially misleading. Misrepresentation is security-relevant because it can bypass scrutiny for a broad-capability tool, causing users to disclose data and operators to grant permissions under false assumptions about what the skill really does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

If the skill lacks actual crypto market collection, sentiment analysis, and processing logic, but only defines a generic LLM interface, then the published purpose is materially misleading. Misrepresentation is security-relevant because it can bypass scrutiny for a broad-capability tool, causing users to disclose data and operators to grant permissions under false assumptions about what the skill really does.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: form-data==4.0.5 — 1 advisory(ies): CVE-2026-12143 (form-data: CRLF injection in form-data via unescaped multipart field names and f)

High
Category
Supply Chain
Confidence
94% confidence
Finding

The lockfile pins transitive dependency form-data to 4.0.5, which is flagged for a CRLF injection issue in multipart field names. If this agent or one of its SDK dependencies constructs multipart requests using attacker-controlled field names or filenames, a crafted value could tamper with multipart headers and potentially alter downstream request parsing. In this package, the vulnerable library is transitive via @types/node-fetch rather than directly used, so exploitability depends on actual runtime use and is less certain than a direct import.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · src/analyzer.ts (reported line 7)May include surrounding context.

ts
import * as path from 'path';
import { MarketData } from './types';

// .env 직접 로드
dotenv.config({ path: path.resolve(__dirname, '../.env') });

console.log('[Fetcher] API Key Check:', process.env.TAVILY_API_KEY ? 'FOUND' : 'MISSING');

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · src/fetcher.ts (reported line 6)May include surrounding context.

ts
import * as path from 'path';
import { MarketData } from './types';

// .env 직접 로드
dotenv.config({ path: path.resolve(__dirname, '../.env') });

console.log('[Fetcher] API Key Check:', process.env.TAVILY_API_KEY ? 'FOUND' : 'MISSING');

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · src/analyzer.ts (reported line 8)May include surrounding context.

ts
import { MarketData } from './types';

// .env 직접 로드
dotenv.config({ path: path.resolve(__dirname, '../.env') });

console.log('[Fetcher] API Key Check:', process.env.TAVILY_API_KEY ? 'FOUND' : 'MISSING');

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · src/fetcher.ts (reported line 7)May include surrounding context.

ts
import { MarketData } from './types';

// .env 직접 로드
dotenv.config({ path: path.resolve(__dirname, '../.env') });

console.log('[Fetcher] API Key Check:', process.env.TAVILY_API_KEY ? 'FOUND' : 'MISSING');

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The README explicitly requires Groq and Tavily API keys and references CoinGecko, but it does not warn users that prompts, token names, and other request data may be sent to third-party services. This creates a real transparency and data-handling risk because users may unknowingly transmit sensitive or proprietary inputs to external APIs.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill advertises network-backed market/news analysis but declares no explicit tool scope such as allowed network access or environment usage. That omission weakens reviewability and containment, making it harder to verify what external endpoints may be contacted and whether secrets from environment variables could be exposed through overly broad runtime capabilities.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The natural-language description and feature text are presented exclusively in Korean, with no indication that users can choose another language or that the skill is intentionally region-specific. Per the policy, forcing a specific language without opt-in is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

This TypeScript file makes outbound LLM provider calls via provider.call(systemPrompt, userMessage), and the composed userMessage includes news content, market data, token identifiers, and derived sentiment text. Although there is minimal error logging, there is no confirmation prompt, user-facing notice, or comment/docstring warning that input data will be sent to an external model provider.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The system prompt explicitly requires the summary to be written '한국어로 설명', which forces a specific language for output. The file does not offer any language selection, opt-in, or documented locale justification, which matches the policy category for language or locale constraints.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
78% confidence
Finding

The report prompt is entirely authored in Korean and instructs the model to return a report in that format, implying a fixed-language experience. There is no evidence in this file that users can choose another language or that the Korean-only constraint is documented as a justified regional requirement.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This code contains multiple Korean-only natural-language strings in comments, warnings, errors, and status logs, such as the API-key warning and search-status messages. Because the skill does not provide any opt-in or locale selection mechanism, it effectively forces a specific language, which matches the language/locale policy violation criteria.

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 · src/fetcher.ts (reported line 48)May include surrounding context.

ts
}

  try {
    const response = await fetch('https://api.tavily.com/search', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 · src/fetcher.ts (reported line 48)May include surrounding context.

ts
}

  try {
    const response = await fetch('https://api.tavily.com/search', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 · src/fetcher.ts (reported line 99)May include surrounding context.

ts
// 하지만 CoinGecko 무료 API는 키 없이 가능하므로 실제 호출 시도

    const searchRes = await fetch(
      `https://api.coingecko.com/api/v3/search?query=${encodeURIComponent(tokenSymbol)}`
    );

    if (!searchRes.ok) {

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 · src/fetcher.ts (reported line 120)May include surrounding context.

ts
// 하지만 CoinGecko 무료 API는 키 없이 가능하므로 실제 호출 시도

    const searchRes = await fetch(
      `https://api.coingecko.com/api/v3/search?query=${encodeURIComponent(tokenSymbol)}`
    );

    if (!searchRes.ok) {

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The file contains Korean-only instructional comments and a Korean-only error message ('token 필드가 필요합니다.'). This imposes a specific language in user-visible behavior without offering opt-in, fallback, or documenting a justified locale restriction.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 · src/llm/groq.ts (reported line 15)May include surrounding context.

ts
}
    this.client = new OpenAI({
      apiKey: config.apiKey,
      baseURL: 'https://api.groq.com/openai/v1',
    });
    this.model = config.model || 'llama-3.3-70b-versatile';
  }

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The natural-language description forces a specific language presentation for the skill without any indication that users may choose another language or that the skill is intentionally region-specific. This matches the policy category for language or locale constraints lacking opt-in or justification.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

Omitting a user-facing warning that token/query data is sent to external services and that web content is fetched reduces informed consent and can surprise users about data disclosure. While not directly an exploit primitive, the lack of transparency materially increases privacy and compliance risk, especially when combined with undeclared external AI providers.

Content

No source excerpt is available for this finding.