T09 · Insecure Skill Coding Practices
- Location
scripts/fact_check.py:141- Finding
API Credentials and Article Content Can Be Sent to an Unrestricted Custom Endpoint
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This appears to be a legitimate data-quality skill, but it can send user datasets, articles, claims, and API keys to external or custom providers without strong disclosure or endpoint safeguards.
Install only if you are comfortable with Dingo reading the files you select and, for LLM or fact-checking modes, sending their contents or derived claims to configured model/search providers. Prefer rule-based local evaluators for confidential data, avoid untrusted OPENAI_BASE_URL values, use least-privilege provider keys, and review or delete generated outputs that may contain original article text or evaluation details.
scripts/fact_check.py:141API Credentials and Article Content Can Be Sent to an Unrestricted Custom Endpoint
SKILL.md:12Unpinned Third-Party Packages Create a Mutable Supply-Chain Boundary
Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.
## How to contribute
1. Fork the [Dingo repository](https://github.com/MigoXLab/dingo)
2. Edit skill files in `clawhub/` (`SKILL.md`, `_meta.json`)
3. Test locally by placing `SKILL.md` in your `~/.openclaw/skills/` directory
4. Submit a pull request
The skill provides LLM-based evaluation examples that send user dataset fields such as content, responses, references, and retrieved contexts to third-party API endpoints, but it does not present an explicit user-facing privacy or data-sharing warning before recommending those workflows. In a data-quality skill, users may reasonably run it on proprietary, regulated, or sensitive datasets, so omission of consent and disclosure guidance materially increases the risk of unintended external disclosure.
This example explicitly configures an external API endpoint for LLM evaluation, which means dataset content mapped into the evaluation request can leave the local environment. In context this is expected functionality, but without nearby disclosure and consent guidance it still represents a real external-transmission risk for sensitive user data.
"config": {
"model": "deepseek-chat",
"key": "${OPENAI_API_KEY}",
"api_url": "https://api.deepseek.com/v1"
}
}
]
The RAG evaluation example sends user_input, response, retrieved_contexts, and reference fields to an external LLM endpoint, which can expose potentially sensitive prompts, retrieved documents, and ground-truth data. Because RAG datasets often contain internal knowledge-base content, the context makes this transmission especially privacy-relevant.
"reference": "reference"
},
"evals": [
{"name": "Faithfulness", "config": {"model": "deepseek-chat", "key": "${OPENAI_API_KEY}", "api_url": "https://api.deepseek.com/v1"}},
{"name": "ContextPrecision", "config": {"model": "deepseek-chat", "key": "${OPENAI_API_KEY}", "api_url": "https://api.deepseek.com/v1"}}
]
}
This second external endpoint use in the same RAG example reinforces that multiple evaluators may each transmit the same dataset fields externally, increasing disclosure surface and repetition of sensitive content. The risk is not malicious behavior but insufficiently signposted outbound sharing of user data.
},
"evals": [
{"name": "Faithfulness", "config": {"model": "deepseek-chat", "key": "${OPENAI_API_KEY}", "api_url": "https://api.deepseek.com/v1"}},
{"name": "ContextPrecision", "config": {"model": "deepseek-chat", "key": "${OPENAI_API_KEY}", "api_url": "https://api.deepseek.com/v1"}}
]
}
]
Documenting a default external base URL is normal, but in this skill it contributes to a workflow that can transmit user data off-host without a strong privacy warning. By itself this line is mostly informational, so the security concern is lower than the concrete examples that actually package dataset fields for transmission.
| Variable | Description |
|---|---|
| `OPENAI_API_KEY` | API key for LLM-based evaluation |
| `OPENAI_BASE_URL` | Custom API endpoint (default: `https://api.openai.com/v1`) |
| `OPENAI_MODEL` | Model name (default: `gpt-4`) |
## Supported input formats
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.
When using this skill on behalf of the user:
* **Always write a config file** before running CLI evaluation. Don't try to pass complex JSON inline.
* **Quote file paths** with spaces in commands: `dingo eval --input "my config.json"`
* **Wrap main code in `if __name__ == '__main__':`** when writing Python scripts — Dingo uses multiprocessing internally, which fails on macOS without this guard.
* **Infer format from extension**: `.jsonl` → `jsonl`, `.json` → `json`, `.csv` → `csv`, `.txt` → `plaintext`.
The MCP server section exposes tool-driven evaluation over SSE/stdio for AI agents, but it does not warn that MCP-invoked tools may read local files and, depending on evaluator configuration, forward contents to external APIs. This creates a meaningful transparency and data-boundary problem because remote or semi-autonomous agent integrations can make file access and network exfiltration less visible to the end user.
The ArticleFactChecker SDK example sends article content and extracted claims to an external OpenAI-compatible endpoint for analysis. Articles may contain unpublished, proprietary, or personal information, and the autonomous fact-checking workflow increases the amount of derived content transmitted externally.
"config": {
"key": os.environ["OPENAI_API_KEY"],
"model": os.getenv("OPENAI_MODEL", "gpt-5.4-mini"),
"api_url": os.getenv("OPENAI_BASE_URL", "https://api.openai.com/v1"),
"parameters": {
"temperature": 0,
"agent_config": {
This configuration additionally enables external claim extraction and optional Tavily web search, creating multiple outbound transmission paths for user-supplied article content or derived claims. Multi-provider agent workflows amplify privacy and confidentiality risk because data may be shared across several services during verification.
"claims_extractor": {
"api_key": os.environ["OPENAI_API_KEY"],
"model": os.getenv("OPENAI_MODEL", "gpt-5.4-mini"),
"base_url": os.getenv("OPENAI_BASE_URL", "https://api.openai.com/v1"),
"max_claims": 50
},
"arxiv_search": {"max_results": 5},
The documentation states that the tool saves original article text and detailed verification artifacts locally, but it does not warn users that potentially sensitive input content will be retained on disk. This creates a real privacy and data-handling risk because users may process confidential articles or proprietary drafts without realizing persistent local copies and structured outputs are being created.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
'pip install "dingo-python[agent]"'
)
api_url = os.getenv("OPENAI_BASE_URL", "https://api.openai.com/v1")
model = args.model or os.getenv("OPENAI_MODEL", "gpt-5.4-mini")
tavily_key = os.getenv("TAVILY_API_KEY")
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
'pip install "dingo-python[agent]"'
)
api_url = os.getenv("OPENAI_BASE_URL", "https://api.openai.com/v1")
model = args.model or os.getenv("OPENAI_MODEL", "gpt-5.4-mini")
tavily_key = os.getenv("TAVILY_API_KEY")
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
'pip install "dingo-python[agent]"'
)
api_url = os.getenv("OPENAI_BASE_URL", "https://api.openai.com/v1")
model = args.model or os.getenv("OPENAI_MODEL", "gpt-5.4-mini")
tavily_key = os.getenv("TAVILY_API_KEY")
This manifest is a JSON file, so vague-trigger review applies. The description says the skill is a "Comprehensive AI Data, Model and Application Quality Evaluation Tool," which is very broad and does not define specific trigger phrases, contexts, or exclusions, making intended invocation scope unclear.
No suspicious patterns detected.