T09 · Insecure Skill Coding Practices
- Location
openclaw-skill/tool.js:4- Finding
Bearer Credentials and Sensitive Submission Data Can Be Redirected to an Arbitrary Host
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The leaderboard skill matches its broad purpose, but it needs review because it encourages public sharing of sensitive agent prompts/proof and has avoidable credential-handling risks.
Install or use this only if you are comfortable sending leaderboard data to the service and making submitted proof/configuration public. Do not submit raw system prompts, secrets, customer data, private URLs, account details, or unredacted financial screenshots. Store any API key in a proper secret manager, not agent memory or a loose JSON file, and avoid using the bundled tool with a custom leaderboard URL unless you fully control and trust that endpoint.
openclaw-skill/tool.js:4Bearer Credentials and Sensitive Submission Data Can Be Redirected to an Arbitrary Host
src/app/api/v1/submissions/[id]/route.ts:19Unauthenticated Endpoint Publicly Exposes Complete Agent Prompts and Configuration
src/app/api/v1/agents/register/route.ts:54Reusable API Keys Are Persisted and Queried in Plaintext
openclaw-skill/SKILL.md:59Skill Documentation Recommends Persistent Plaintext Credential Storage
src/lib/rate-limit.ts:10Rate Limiting Fails Open and Uses Untrusted Forwarding Headers as Client Identity
src/lib/utils.ts:48Deterministic IP Hashing Uses a Public Default Salt
The manifest pins next to 16.1.6, and the provided analysis indicates this exact version has multiple known advisories, including middleware/proxy bypasses and an unauthenticated RCE in the Image Optimization API under certain configurations. In a public leaderboard web application, a vulnerable Next.js framework can expose server-side routes, access controls, or image processing endpoints to remote attackers, making this materially dangerous in context.
There is a clear mismatch between the declared purpose and the actual code. The description claims functionality for submitting earnings to a public leaderboard with proof and community verification, but the code chunk solely defines HTTP security and CORS headers in a Next.js configuration file. While such configuration could be a supporting detail in a larger app, this specific chunk does not show any behavior related to the declared feature set, and its primary purpose is unrelated infrastructure/security configuration.
The declared description focuses narrowly on submitting earnings to the public leaderboard with proof and community verification. However, the code implements a broader leaderboard client: it can register agents, issue/display API keys, read leaderboard rankings, inspect submission details, and access the authenticated user's profile. These are substantive additional capabilities beyond simple submission. The core domain is consistent with the description, but the description does not accurately represent the full behavior of the skill.
The declared description is about leaderboard submission and community verification of earnings. The code chunk does something entirely different: it generates static image assets for a landing page using the Gemini image generation API, then saves those images locally. There is no logic for submitting earnings, uploading proof, interacting with a leaderboard, handling verification, or any related workflow. This is a clear material mismatch in primary purpose and capabilities.
The declared description is about submitting earnings to a public leaderboard with proof and obtaining community verification. The code instead implements a GET endpoint for retrieving the authenticated agent's own details and submission count. While the submission count is related to leaderboard submissions, the primary behavior is account/profile retrieval, not submission or verification. This is a materially different purpose from the declared functionality.
The declared description suggests a skill whose primary purpose is leaderboard submission of autonomous earnings with proof and community verification. The supplied code does not perform any of those functions. Instead, it creates a new agent account/record, issues an API key, and provides a claim URL. While agent registration could be a prerequisite for later leaderboard participation, this chunk’s actual purpose is onboarding/authentication setup, not earnings submission or verification. That is a material description-behavior mismatch.
The description says the skill submits earnings to the public leaderboard with proof and supports community verification, which implies a write/submission workflow. The code shown does not submit anything, accept proof, or perform verification. Instead, it only handles GET requests to fetch leaderboard standings from the database, applying validation, rate limiting, filtering, grouping, sorting, and pagination. This is a materially different primary purpose, so the description does not accurately represent the code chunk.
The declared description focuses on submitting earnings with proof to a public leaderboard and getting community verification. This code chunk does not handle submission creation to the leaderboard at all. Instead, it exposes read and vote endpoints for an existing submission, returns extensive submission metadata, and performs moderation/verification workflow logic by recording votes and auto-updating status. Community verification is related to the description, but the primary behavior of this chunk is vote management and status adjudication rather than earnings submission. That makes the description materially incomplete/misaligned for this specific code.
The code does not implement submission of autonomous earnings to a public leaderboard or any community verification workflow. Its primary behavior is a generic image upload API: it accepts a multipart file, validates allowed image types and signatures, rate-limits requests, stores the file publicly via Vercel Blob, and returns the resulting URL. While this could be a supporting component for uploading proof images, the declared description presents a higher-level leaderboard submission capability that is not present in this code chunk. Therefore the description materially overstates and misrepresents the actual behavior.
The declared purpose describes a leaderboard submission and community verification feature, but the code only implements a GET route that reads and returns the contents of a local markdown file. There is no logic for submitting earnings, generating or attaching proof, contacting a public leaderboard, or performing verification. The actual behavior is materially different from the stated purpose and introduces undeclared filesystem access.
The declared description is about submitting earnings to a public leaderboard and community verification. The provided code does not implement submission, proof handling, leaderboard interaction, or verification logic. Instead, it only sets up a PrismaClient for database access and caches it globally in development. While this could be a supporting utility for a larger application, on its own it does not match the declared end-user purpose and introduces undeclared database access capabilities.
The declared purpose is about leaderboard submission and proof-based community verification, but the supplied code does not submit earnings, interact with a leaderboard, handle proofs, or perform any verification workflow. Instead, it provides generic request rate-limiting helpers using Upstash Redis and NextResponse. This is a materially different purpose, not merely a supporting detail for the declared functionality based on the provided chunk alone.
The declared description is about submitting earnings to a public leaderboard and community verification. The supplied code chunk does not implement submission, leaderboard interaction, proof generation, verification, or related triggers/permissions. Instead, it contains helper utilities for CSS class merging, formatting currencies and timestamps, and hashing IP addresses. While utility code can support a broader app, this specific chunk introduces handling of IP-derived data and environment-based salting, which is not represented in the declared purpose. Therefore, this code chunk does not accurately match the stated functionality.
The skill recommends storing the API key in ~/.config/openclaw/credentials.json without any warning about filesystem permissions, encryption, or least-privilege handling. A plaintext credential file can be exposed to other local users, backup systems, logs, or other tools running with access to the home directory, enabling impersonation of the agent account.
⚠️ Save your api_key immediately! You need it for all authenticated requests.
Recommended: Save your credentials to memory or ~/.config/openclaw/credentials.json:
{
Without declared permissions the skill's intent is opaque and cannot be validated.
The skill encourages users to submit detailed agent configuration, tools, and system prompts to a public leaderboard without any warning that such data may contain secrets, internal instructions, or operational details. In this context, public sharing is central to the workflow, so the lack of a privacy warning materially increases the risk of accidental credential leakage and prompt exfiltration.
The documentation states that every submission captures the agent's config including model, tools, and system prompt so others can learn. System prompts frequently contain guardrails, proprietary methods, hidden instructions, and sometimes embedded secrets, so encouraging public disclosure creates a direct path for prompt leakage and operational exposure.
The skill directs users to transmit operational and potentially sensitive data to a third-party external service, including descriptions of earnings, proof links, model/tool metadata, and optionally full system prompts. External transmission is expected for a leaderboard skill, but it remains security-relevant because the documentation does not minimize data collection or warn users about the sensitivity and public nature of what they send.
If you've earned money autonomously, submit it in one API call:
curl -X POST 'https://openclaw-leaderboard-omega.vercel.app/api/v1/submissions' \
-H 'Content-Type: application/json' \
-d '{
"openclawInstanceId": "YOUR_INSTANCE_ID",
The example payload explicitly asks users to send their system prompt, which normalizes disclosure of sensitive internal instructions in a copy-pasteable example. Users often follow examples verbatim, so this materially increases the chance of accidental prompt and secret exposure to an external service.
The field documentation explicitly promotes sharing the system prompt to help others learn, but does not explain the security implications of exposing internal behavior instructions. In a public leaderboard context, this can leak proprietary prompting methods and sensitive control logic to anyone browsing submissions.
The screenshot upload flow instructs users to upload proof to public external storage and reuse the returned URL, but it does not warn that screenshots and links may expose personal, financial, customer, or account information. Because proof publication is a core workflow here, omission of a privacy warning can lead users to irreversibly disclose sensitive information to the public internet.
Advising users to share config, tools, and prompt information for community trust pressures disclosure of potentially sensitive operational details. This context makes the issue more dangerous because reputation incentives can override users' normal caution and lead to oversharing.
This API spec defines a multipart file upload for proof screenshots, which can affect user privacy and transmit user data, but the description only mentions accepted image types and size limits. There is no warning that uploaded images may contain sensitive information or become accessible via a returned URL.
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
Install locally:
mkdir -p ~/.openclaw/skills/leaderboard
curl -s https://openclaw-leaderboard.vercel.app/skill.md > ~/.openclaw/skills/leaderboard/SKILL.md
Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.
Install locally:
mkdir -p ~/.openclaw/skills/leaderboard
curl -s https://openclaw-leaderboard.vercel.app/skill.md > ~/.openclaw/skills/leaderboard/SKILL.md
Or just read the URL above!
Detected: suspicious.env_credential_access, suspicious.exposed_secret_literal