T09 · Insecure Skill Coding Practices
- Location
scripts/classify_task.py:165- Finding
Shell Command Injection Through Unescaped Task Description
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill is not malicious, but it needs review because it stores AI API keys and steers potentially sensitive work to third-party models without clear disclosure or reliable provider scoping.
Review carefully before installing. Use this only if you are comfortable storing provider API keys locally in ~/.model-router and manually checking every generated sessions_spawn command. Do not send confidential code, logs, documents, images, customer data, regulated data, or business proposals through the suggested models unless the destination provider is explicitly approved. Treat the model aliases as untrusted until they are reconciled to canonical provider/model IDs.
scripts/classify_task.py:165Shell Command Injection Through Unescaped Task Description
scripts/classify_task.py:38Misleading Model Aliases Can Redirect Tasks to an Unexpected Provider
The skill claims secure multi-provider routing, setup, storage, and delegation features that are not actually substantiated by the described implementation, which appears to be only lightweight keyword classification with hardcoded model names. Security claims that overstate protections or capabilities are dangerous because users may entrust API keys, sensitive prompts, or operational decisions to a system that lacks the promised safeguards.
The skill instructs users to send tasks to a specifically selected external model/provider via sessions_spawn without any adjacent warning about data disclosure, provider trust boundaries, or approval requirements. In context, this is more dangerous because the skill is explicitly designed to automate routing, which can make external transmission of sensitive prompts routine and less visible.
# Spawn with recommended model
sessions_spawn --task "Debug this memory leak" --model claude-sonnet
# Use aliases for quick access
sessions_spawn --task "What's the weather?" --model haiku
This example routes a task derived from CSV data to an external provider, which may include sensitive business information, without any disclosure or constraint. The danger is amplified because users may copy the pattern into production workflows and unintentionally export internal datasets.
python3 scripts/classify_task.py "Extract prices from this CSV"
# Result: simple task → use glm-4.5-air
sessions_spawn --task "Extract prices" --model glm-4.5-air
# Then analyze with better model if needed
sessions_spawn --task "Analyze price trends" --model claude-sonnet
The follow-up analytics example sends potentially sensitive pricing information to another external model with no mention of confidentiality or provider exposure. Chained routing across multiple providers can compound disclosure risk by duplicating sensitive content across services.
sessions_spawn --task "Extract prices" --model glm-4.5-air
sessions_spawn --task "Analyze price trends" --model claude-sonnet
### Example 2: Progressive Escalation
The bug-fixing example encourages sending debugging content to an external model, which often includes source code, stack traces, credentials, or infrastructure details. Without safeguards or warnings, users may expose internal codebases or secrets during troubleshooting.
# Try cheap model first (60s timeout)
sessions_spawn --task "Fix this bug" --model glm-4.5-air --runTimeoutSeconds 60
# If fails, escalate to premium
sessions_spawn --task "Fix complex architecture bug" --model claude-opus
Escalating 'complex architecture' debugging to a premium external model implies sending even more sensitive system-design and code context outside the environment. Architecture-level prompts can reveal internal topology, trust boundaries, and weaknesses valuable to attackers if mishandled.
sessions_spawn --task "Fix this bug" --model glm-4.5-air --runTimeoutSeconds 60
sessions_spawn --task "Fix complex architecture bug" --model claude-opus
### Example 3: Parallel Processing
Parallel submission of multiple document summarization tasks increases the volume and speed of external disclosure with no user warning. Batch fan-out can magnify accidental leakage and make it harder to track which provider received which document.
# Batch simple tasks in parallel with cheap model
sessions_spawn --task "Summarize doc A" --model glm-4.5-air &
sessions_spawn --task "Summarize doc B" --model glm-4.5-air &
sessions_spawn --task "Summarize doc C" --model glm-4.5-air &
wait
This is another instance of the same risky batch pattern: routing a document to an external model without any sensitivity caveat. Repetition in examples reinforces unsafe default behavior and makes the omission more material, not less.
# Batch simple tasks in parallel with cheap model
sessions_spawn --task "Summarize doc A" --model glm-4.5-air &
sessions_spawn --task "Summarize doc B" --model glm-4.5-air &
sessions_spawn --task "Summarize doc C" --model glm-4.5-air &
wait
The third parallel summarization example continues the pattern of normalizing bulk export of document content to outside providers. In aggregate, these examples suggest scale-out external processing without corresponding security controls or privacy disclosures.
sessions_spawn --task "Summarize doc A" --model glm-4.5-air & sessions_spawn --task "Summarize doc B" --model glm-4.5-air & sessions_spawn --task "Summarize doc C" --model glm-4.5-air & wait
The vision example routes 100 images to an external model with no warning about possible exposure of personal, confidential, or biometric data. Image corpora often carry sensitive metadata and visual identifiers, so the privacy impact can be substantial.
# Vision task with 2M token context
sessions_spawn --task "Analyze these 100 images" --model gemini-1.5-pro
This example routes source-derived internal project content ('auth implementation') to an external provider without any trust-boundary warning, data classification check, or redaction step. That can expose proprietary code, secrets accidentally present in comments/config, or security-sensitive implementation details to third-party model providers.
sessions_spawn --task "Write comprehensive unit tests for auth module" --model sonnet --label "auth-tests" --timeoutSeconds 300
sessions_spawn --task "Generate README and inline code comments from auth implementation" --model GLM --label "auth-documentation" --cleanup delete
**Optimal routing:**
Proofreading a newsletter with an external model still sends potentially unpublished business content to a third-party provider. While lower risk than source code or credentials, it can leak confidential communications, embargoed content, or customer-identifying information if users copy real drafts into the workflow.
sessions_spawn --task "Write engaging newsletter draft incorporating research findings" --model opus --label "newsletter-draft" --timeoutSeconds 900
# Proofread: Quick review
sessions_spawn --task "Proofread newsletter for grammar and clarity" --model GLM --label "newsletter-proofread" --cleanup delete
# Summarize: Social media posts
sessions_spawn --task "Create 3 social media posts summarizing key newsletter points" --model haiku-4.5 --label "social-posts" --cleanup delete
Verification of a production fix often requires logs, stack traces, code snippets, and architecture context; routing that to an external provider can disclose sensitive operational and security information. In an outage or incident context, users are especially likely to paste secrets or internal details under time pressure, increasing real-world risk.
sessions_spawn --task "Analyze complex race condition in payment processing" --model codex-5.2 --label "debug-race-condition" --timeoutSeconds 600
sessions_spawn --task "Verify fix works and doesn't break other features" --model GLM --label "verify-fix" --cleanup delete
**Emergency routing:**
A 'clean report of processing results' may contain extracted entities, document summaries, or personal/business data from the batch input set. Sending aggregated results to an external provider can leak sensitive information across documents, even if the final step seems low risk.
sessions_spawn --task "Summarize, extract entities, and classify all extracted documents" --model sonnet --label "batch-process" --timeoutSeconds 600
sessions_spawn --task "Create clean report of processing results" --model GLM --label "batch-report" --cleanup delete
---
Polishing a critical business proposal with an external model can expose sensitive commercial terms, strategy, pricing, or client information to a third party. The example frames this as a routine optimization step and does not surface the confidentiality tradeoff, which makes unsafe use more likely.
sessions_spawn --task "Review draft for completeness, clarity, and persuasiveness" --model sonnet --label "proposal-review" --timeoutSeconds 600
sessions_spawn --task "Polish language and ensure professional tone" --model GLM --label "proposal-polish" --cleanup delete
**Routing rationale:**
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.
# Ask to configure another provider
another = input(f"\n{Colors.OKCYAN}Configure another provider? (y/N): {Colors.ENDC}").strip().lower()
if another == 'y':
return prompt_provider_setup()
except (ValueError, IndexError):
print_error("Invalid selection.")
The skill documents shell commands, local file writes, and credential storage behavior, but does not declare any explicit tool scope or allowed-tools boundary. In an agent ecosystem, undocumented shell/file capabilities increase the chance that the skill is invoked with broader privileges than users expect, especially because it handles API keys and configuration files.
The setup instructions encourage users to add multiple third-party provider API keys locally but do not clearly disclose that user task contents may later be transmitted to those external services. This creates a privacy and compliance risk because users may route confidential prompts, code, documents, or regulated data to providers without informed consent.
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
~/.model-router/
├── config.json # Model mappings (chmod 600)
└── .api-keys # API keys (chmod 600)
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
~/.model-router/
├── config.json # Model mappings (chmod 600)
└── .api-keys # API keys (chmod 600)
Code scans file system directories looking for sensitive files. This could be reconnaissance for credential theft.
1. **Never commit** `.api-keys` to version control
2. **Use environment variables** for production deployments
3. **Rotate keys** regularly via the wizard
4. **Audit access** with `ls -la ~/.model-router/`
## 📖 Usage Examples
The examples explicitly route arbitrary tasks, documents, bugs, CSV-derived work, and images to external models without warning that this may expose proprietary or personal data. Because the examples are operational and easy to copy-paste, they normalize sending potentially sensitive material to third-party AI services.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
- [OpenAI](https://platform.openai.com/docs)
- [Gemini](https://ai.google.dev/docs)
- [Moonshot](https://platform.moonshot.cn/docs)
- [Z.ai](https://api.z.ai/docs)
- [GLM](https://open.bigmodel.cn/dev/api)
- **Setup:** Run `python3 scripts/setup-wizard.py`
This file uses a fixed list of English keywords such as "quick", "research", and "code" to classify tasks, which implicitly assumes the user's task description will be in English. Under the policy, forcing a specific language or locale without offering a choice or documenting the constraint is a natural-language policy violation.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
base_url = None
if provider in ["openai", "moonshot", "glm"]:
default_url = {
"openai": "https://api.openai.com/v1",
"moonshot": "https://api.moonshot.cn/v1",
"glm": "https://open.bigmodel.cn/api/paas/v4"
}.get(provider)
No suspicious patterns detected.