T09 · Insecure Skill Coding Practices
- Location
research.sh:12- Finding
Hardcoded Brave Search API Credential
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This research skill is mostly purpose-aligned, but it has under-disclosed credential use, external data transfer, and unsafe helper execution behavior that users should review before installing.
Review and modify this skill before installation. Remove the built-in Brave token, require explicit per-skill API keys, disable the main-agent auth-profile fallback, avoid running a mutable helper outside the skill directory, use private cache paths, and require TLS/authenticated endpoints for Redis and Qdrant. Do not use it for confidential research topics unless these data-handling paths are understood and controlled.
research.sh:12Hardcoded Brave Search API Credential
vectorize.sh:31Undisclosed Access to the Main Agent Authentication Profile
vectorize.sh:14Creation and Execution of a Mutable Helper Outside the Skill Directory
vectorize.sh:66Undisclosed Transmission of Research Content to OpenAI
search-cache.sh:22Predictable Shared Temporary Cache Permits Disclosure and Symlink Attacks
search-cache.sh:13Redis Credentials and Qdrant Research Data Use Insecure Transport
vectorize.sh:74Vectorization Chunking Algorithm Can Loop Indefinitely
Referenced artifact was not completely inspected
2. Calls `research.sh` with appropriate parameters
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
fi
# Clear file cache
rm -rf "$FILE_CACHE_DIR"/*
mkdir -p "$FILE_CACHE_DIR"
echo "Cache cleared"
The skill documentation describes autonomous research, storage in an Obsidian vault, and vectorization into Qdrant, but it does not prominently warn users that their prompts, derived content, and metadata may be written locally and transmitted to external services. This can lead users to submit sensitive topics or proprietary data without informed consent, causing unintended disclosure or retention across multiple systems.
The configuration section exposes that the skill communicates with Brave Search, Qdrant, and Redis, including default network endpoints, but it does not clearly warn that using the skill triggers outbound requests to third-party or self-hosted services. Users may assume research is local-only and unknowingly transmit sensitive queries, topics, or generated content over the network to services with different trust boundaries and retention policies.
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.
---
*Generated by OpenClaw Auto-Research Agent v1.0*
*For questions or improvements, see: `clawhub-skills/auto-research/SKILL.md`*
The script contains a hard-coded Brave API key and automatically transmits user-supplied research topics to Brave Search without an explicit warning or consent prompt. Research queries can contain proprietary, strategic, or personal information, so silent third-party transmission creates a real confidentiality and privacy risk, amplified by embedding a credential directly in the skill.
This curl call sends the user-provided search query to an external service, which is an actual data egress event. In the context of a research assistant, users may input confidential project names, incident details, or internal topics; transmitting them off-host without prominent disclosure can leak sensitive information to a third party.
API_RESPONSE=$(curl -s --max-time 30 \
-H "Accept: application/json" \
-H "X-Subscription-Token: $BRAVE_API_KEY" \
"https://api.search.brave.com/res/v1/web/search?q=$(printf '%s' "$SEARCH_QUERY" | jq -sRr @uri)&count=$SOURCE_COUNT&freshness=py&result_filter=web") || {
echo -e "${RED}✗ Search API call failed${NC}"
exit 1
}
The file is documented and structured as a research orchestrator that searches for sources and compiles a briefing, but these lines additionally invoke a separate vectorization pipeline and update the output file to reflect ingestion status. Writing research notes into a Qdrant-backed vector store is a distinct capability not justified by the visible purpose of producing a research briefing when no manifest scope declares it.
With no manifest available, the code's own description frames this as a cache helper for storing and retrieving research results. Line L017 adds an additional capability by invoking a separate secrets-retrieval tool to obtain REDIS_PASSWORD, which goes beyond basic cache manipulation and introduces credential access behavior not implied by the script's stated purpose.
The clear_cache function deletes all matching Redis cache keys and removes all files under the cache directory, which is a destructive operation. While the script comments and usage text describe the command, there is no confirmation prompt or stronger user-facing warning at the point of execution before data is removed.
The script silently falls back to reading an OpenAI API key from a local auth-profiles file instead of requiring the caller to provide credentials explicitly. That behavior expands the script's access to local secrets and can cause unintended credential use or disclosure, especially for a utility whose purpose is file vectorization rather than credential management.
The script dynamically writes an executable Python program into the user's workspace and then later executes it. Self-installing code increases the attack surface, creates persistence on disk, and makes review harder because the behavior is split between the shell script and generated code.
The generated ingestion tool sends document content to the OpenAI embeddings API, which is an external service, but this file does not provide a clear user-facing disclosure or consent step. Research documents may contain confidential or proprietary information, so silent transmission materially increases data exposure risk.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
return
# Create collection
resp = requests.put(
f"{QDRANT_URL}/collections/{COLLECTION}",
json={
"vectors": {
This request sends vector payloads containing chunked research text and metadata to Qdrant over HTTP to a configured host. Because the default URL is unencrypted HTTP to a private IP and the payload includes user content and file metadata, interception, unintended retention, or internal data leakage are credible risks.
for i in range(0, len(points), batch_size):
batch = points[i:i+batch_size]
try:
resp = requests.put(
f"{QDRANT_URL}/collections/{COLLECTION}/points?wait=true",
json={"points": batch}
)
The tool uploads chunked document text and metadata into Qdrant without an explicit disclosure in the script's interface. Even if Qdrant is internal, this is still a data write to a network service and may store sensitive content, source URLs, file paths, and topic metadata beyond the user's expectations.
The script creates an output directory and writes a markdown research report into the user's Obsidian vault, then later modifies that file again to update vectorization status. Although there are status messages after the fact, there is no clear up-front disclosure in the usage/help text or comments warning users that running the skill will create and edit files in a local notes repository.
The comment says the file is updated "using a safe replacement," but the implementation performs in-place or temporary-file mutation with chained fallbacks and suppressed errors. That is not a direct contradiction about core purpose, but it overstates the safety of the operation compared with the actual best-effort editing behavior.
The script reads a Redis password from the environment or a secrets helper, which is access to sensitive credentials. Although this is functionally necessary, the file does not include any explicit user-facing notice that credentials will be accessed when connecting to Redis.
Reading API credentials from a local auth profile without prominently disclosing that behavior can violate user expectations and lead to accidental use of secrets. In this context it is less severe than direct exfiltration, but it still reflects hidden secret access by the skill.
Creating and later executing a helper file on disk without explicit warning hides material behavior from the user and can leave behind executable artifacts. In an agent skill context, undisclosed code generation is more dangerous because users may assume they are only running the visible script.