Back to skill

Security audit

专为百度秒哒应用打造的SecondMe OAuth2登录和API集成工具,完成Connect to SecondMe OAuth2接入

Security checks for vulnerabilities and agentic risk

Overview

This looks like a genuine integration template, but it handles login tokens in a way that can expose a user's SecondMe account if the app is compromised or misconfigured.

Review before installing. This template should be changed so SecondMe access and refresh tokens stay in server-only storage, frontend code calls scoped backend endpoints instead of reading bearer tokens, OAuth state is cryptographically generated and validated server-side, and profile update permissions exclude credential columns.

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

Error
Location
templates/src/pages/AuthCallbackPage.tsx:34
Finding

OAuth State Is Not Cryptographically Generated or Validated by the Privileged Backend

Content
View full analysis
{ // 生成state防CSRF const state = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15); sessionStorage.setItem('oauth_state', state); // 跳转授权页 const authUrl = new URL('https://go.second-me.cn/oauth/'); authUrl.searchParams.append('client_id', import.meta.env.VITE_SECONDME_CLIENT_ID); authUrl.searchParams.append('redirect_uri', import.meta.env.VITE_SECONDME_REDIRECT_URI); authUrl.searchParams.append('response_type', 'code'); authUrl.searchParams.append('state', state); window.location.href = authUrl.toString(); }; ``` ```typescript // templates/src/hooks/useSecondMe.ts:59-72 const login = useCallback(() => { const state = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15); sessionStorage.setItem('oauth_state', state); const authUrl = new URL('https://go.second-me.cn/oauth/'); authUrl.searchParams.append('client_id', import.meta.env.VITE_SECONDME_CLIENT_ID); authUrl.searchParams.append('redirect_uri', import.meta.env.VITE_SECONDME_REDIRECT_URI); authUrl.searchParams.append('response_type', 'code'); authUrl.searchParams.append('state', state); window.location.href = authUrl.toString(); }, []); ``` ```typescript // templates/src/pages/AuthCallbackPage.tsx:34-48 // 验证state const savedState = sessionStorage.getItem('oauth_state'); if (state !== savedState) { setError('安全验证失败'); setLoading(false); return; } sessionStorage.removeItem('oauth_s ...[truncated 2950 chars]
Remediation
View remediation
b.toString(16).padStart(2, '0')).join(''); ``` 2. Store a hash of the state server-side with: - A short expiration time. - Single-use semantics. - The intended redirect URI. - A binding to the initiating browser transaction. 3. Submit both `code` and `state` to the Edge Function. 4. Atomically validate and consume state in the Edge Function before exchanging the authorization code. Reject missing, expired, reused, or mismatched values. 5. Add OAuth PKCE: - Generate a cryptographically secure `code_verifier`. - Send its derived `code_challenge` in the authorization request. - Require the verifier during backend code exchange. 6. Remove the client-side state only after the backend transaction and Supabase session creation succeed. 7. Apply request rate limiting and return generic authentication errors without exposing internal details. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
templates/src/hooks/useSecondMe.ts:45
Finding

Long-Lived SecondMe Access and Refresh Tokens Are Exposed to Browser Code

Content
View full analysis
{ const { data } = await supabase .from('profiles') .select('*') .eq('id', userId) .single(); setProfile(data); if (data?.secondme_access_token) { setApi(new SecondMeAPI(data.secondme_access_token)); } }; ``` ```typescript // templates/src/lib/secondme-api.ts:157-169 export async function getSecondMeAccessToken(): Promise { const { data: { session } } = await supabase.auth.getSession(); if (!session?.user) return null; const { data: profile } = await supabase .from('profiles') .select('secondme_access_token') .eq('id', session.user.id) .single(); return profile?.secondme_access_token || null; } ``` ### Technical Analysis RLS limits which row an authenticated user can access, but it does not protect secrets from JavaScript running in that user's browser. Th ...[truncated 2160 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
templates/database/profiles.sql:25
Finding

Authenticated Users Can Modify OAuth Credential Columns Under the Shipped Update Policy

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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (28)

Credential Access

High
Category
Privilege Escalation
Confidence
92% confidence
Finding

The README explicitly states that SecondMe access tokens are stored in the database and that authenticated users may read their own token. Storing long-lived third-party OAuth access tokens in a user-readable table increases the blast radius of any XSS, account compromise, overly broad client privileges, or RLS misconfiguration, allowing attackers to exfiltrate tokens and call SecondMe APIs as the user.

Content

Scanner excerpt · README.md (reported line 22)May include surrounding context.

md
- ✅ 仅配置在Edge Function环境变量
- ❌ 绝不提交到代码仓库或前端

### Access Token 存储说明

**存储方式**:
- SecondMe access_token 存储在数据库 `profiles` 表

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The code does support substantial SecondMe API access, which aligns with the 'complete API calling' portion of the description. However, the description prominently claims 'one-click OAuth2 login,' but this code does not implement any OAuth2 authorization flow, token exchange, callback handling, or login initiation. Instead, it assumes an access token already exists and fetches it from a Supabase-backed profile record using the current session. That makes the actual behavior narrower and materially different from the declared login/integration promise. Additionally, the code depends on Supabase auth and database access to retrieve the token, which is an external resource/integration not disclosed in the stated purpose.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The declared description promises a complete SecondMe integration layer with one-click OAuth2 login and full API access. However, the supplied code chunk merely configures a Supabase client and defines a profile data shape. While the profile includes an optional secondme_access_token field, there is no actual OAuth2 handling, SecondMe API integration, or app integration workflow in this code. Supabase usage is also an undeclared external service dependency, making the actual behavior materially different from the stated purpose.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

The skill explicitly documents storing a ThirdMe OAuth access token in profiles.secondme_access_token and allowing authenticated users to read it from the frontend. Even with RLS, browser-accessible bearer tokens are high-risk secrets: compromise of the web client, token theft via XSS, insecure logging, or policy mistakes can lead to account/API abuse and data exposure in the external SecondMe ecosystem.

Content

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

md
- ✅ 仅在Edge Function中使用
- ❌ 绝不在前端配置

### 🎫 Access Token 存储与访问

**存储方式**:
- SecondMe access_token 存储在数据库 `profiles.secondme_access_token` 字段

Credential Access

High
Category
Privilege Escalation
Confidence
91% confidence
Finding

The document explicitly instructs storing OAuth access tokens in a user profile table and states that authenticated users can read their own access_token from the frontend. Exposing bearer tokens to client-side code greatly increases theft risk via XSS, browser extensions, logs, or accidental disclosure; RLS only limits cross-user access and does not protect against compromise within the user's browser context.

Content

Scanner excerpt · templates/INTEGRATION.md (reported line 7)May include surrounding context.

md
## ⚠️ 重要安全说明

### Access Token 存储与访问

**存储方式**:
- SecondMe `access_token` 存储在数据库 `profiles.secondme_access_token` 字段

Credential Access

High
Category
Privilege Escalation
Confidence
88% confidence
Finding

The function retrieves a Third-Party access token from the profiles table and returns it to client-side code, which increases exposure of a bearer credential that can authorize API actions if stolen via XSS, browser compromise, or unintended logging. Storing and using long-lived provider tokens in frontend-accessible storage materially raises account takeover and data access risk.

Content

Scanner excerpt · templates/src/lib/secondme-api.ts (reported line 158)May include surrounding context.

ts
}
}

// 工具函数:从当前session获取SecondMe access token
export async function getSecondMeAccessToken(): Promise<string | null> {
  const { data: { session } } = await supabase.auth.getSession();
  if (!session?.user) return null;

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The function stores OAuth access and refresh tokens in the profiles table while comments state the frontend can later retrieve them from profile data. If that table is readable by clients through permissive Supabase RLS or exposed API usage, long-lived third-party credentials can be disclosed, enabling account takeover or API abuse against the linked SecondMe account. In this skill context, the danger is elevated because this function is explicitly designed to bridge frontend login and backend token handling, making accidental client exposure of stored secrets more likely.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The introduction promotes OAuth2 login, user profile access, chat, memory search/management, community features, and voice synthesis, but it does not clearly warn users that the skill may access privacy-sensitive data or trigger data-affecting actions. In an identity and API-integration skill, omission of these disclosures can mislead deployers and end users about what data is accessed or modified, increasing the risk of overbroad integration and unsafe consent flows.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The skill documentation is written almost entirely in Chinese and presents all usage guidance, warnings, and examples in that language, while the skill itself is described as a general integration tool rather than a China-only or Chinese-only tool. Because no language choice or opt-in is offered and no locale limitation is explicitly justified, this creates a natural-language locale policy concern.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The manifest description and all user-facing documentation are written exclusively in Chinese and repeatedly position the skill specifically for '百度秒哒' users, with no indication that another language can be selected. Under the stated policy, forcing a language/locale without opt-in is a natural-language policy violation unless the constraint is explicitly documented and justified as region-specific.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The document presents 'not returning the access token' as a security property, while also explicitly allowing the frontend to read each user's stored OAuth access token from the database. That undermines the stated trust boundary: any XSS in the app, overly broad client code, or RLS mistake can expose ThirdMe tokens to the browser context and enable unauthorized API use.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The hook reads secondme_access_token from the user profile and immediately instantiates an API client with it. There is no confirmation prompt, logging, comment, or docstring warning users that stored credentials are being accessed and used for downstream API calls.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The chat, searchMemory, addNote, and getPlazaFeed helpers invoke remote API methods, and at least some of them send user-provided content such as messages, queries, or notes. The file contains no visible warning, comment, or user-facing disclosure that these actions transmit data to an external service.

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 · templates/src/lib/secondme-api.ts (reported line 6)May include surrounding context.

ts
import { supabase } from './supabase';

const SECONDME_API_BASE = 'https://api.mindverse.com/gate/lab/api/secondme';

export class SecondMeAPI {
  private accessToken: string;

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 · templates/supabase/functions/secondme-oauth-callback/index.ts (reported line 70)May include surrounding context.

ts
import { supabase } from './supabase';

const SECONDME_API_BASE = 'https://api.mindverse.com/gate/lab/api/secondme';

export class SecondMeAPI {
  private accessToken: string;

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 · templates/supabase/functions/secondme-oauth-callback/index.ts (reported line 82)May include surrounding context.

ts
import { supabase } from './supabase';

const SECONDME_API_BASE = 'https://api.mindverse.com/gate/lab/api/secondme';

export class SecondMeAPI {
  private accessToken: string;

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This code sends user-provided chat content to a remote SecondMe service via HTTP, and similar transmission patterns also appear in memory search, note creation, post creation, and text-to-speech requests. Although these network calls are central to the API wrapper's purpose, the file itself contains no user-facing disclosure, confirmation, or warning that user text and related data will be sent to an external service.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This TypeScript/TSX code contains user-facing strings such as '授权失败或被取消', '缺少必要参数', and '正在登录...' entirely in Chinese. Under the policy rule for natural-language violations, forcing a specific language without user opt-in is a reportable issue unless the locale restriction is explicitly justified, which is not shown in this file.

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 · templates/supabase/functions/secondme-oauth-callback/index.ts (reported line 70)May include surrounding context.

ts
client_secret: clientSecret,
    });

    const tokenRes = await fetch('https://api.mindverse.com/gate/lab/api/oauth/token/code', {
      method: 'POST',
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
      body: tokenParams.toString(),

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

该集成指南从标题到正文均以中文编写,未说明这是面向特定中文用户群体的区域性文档,也未提供其他语言选项或用户可选语言说明。按规则,强制单一语言且无用户选择可能构成语言/locale 策略问题。

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The file's natural-language comments and user-facing status text are entirely in Chinese, including the final status/reminder messages. The policy allows locale constraints only when users are given a choice or when the regional/language requirement is clearly justified, which is not stated here.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

The file contains a Chinese comment ('路由配置'), which indicates the skill content is authored in a specific language without any indication of user language choice or opt-in. Under the stated policy, forcing a specific language can be a natural-language policy violation when no language choice is offered or justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

This code contains natural-language content in Chinese comments and English UI strings such as 'Login with SecondMe' and 'Logout', but does not indicate that the language is configurable or chosen by the user. Under the policy rule for language/locale constraints, hardcoded language presentation without opt-in can be a policy concern.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

This file includes user- and developer-facing natural-language text in Chinese, such as the header comment and later error strings like 未登录, with no indication that another language is available. That can violate a language/locale policy when a skill imposes a specific language without user opt-in or documented regional scope.

Content

No source excerpt is available for this finding.