T09 · Insecure Skill Coding Practices
- Location
scripts/inspect.py:155- Finding
Remote Command Injection Through Invalid Service Names
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is a coherent SSH server health checker, but it contains a real service-name injection path that can execute unintended commands on a configured server.
Review before installing. The service-name handling should be fixed so invalid service names are rejected locally and never sent to bash over SSH. Use a pinned installer version, pre-populate known_hosts instead of relying on accept-new, protect targets.yaml and checks.yaml from untrusted edits, run with a least-privilege SSH inspection account, and treat generated reports as sensitive system data.
scripts/inspect.py:155Remote Command Injection Through Invalid Service Names
README.en.md:28Mutable Package Execution Through an Unpinned npx Installation Command
The static finding indicates the implementation does more than the skill declares: it can write reports to arbitrary local paths, execute built-in commands outside the stated checks.yaml allowlist, and auto-trust new SSH host keys via accept-new. This mismatch is dangerous because users and orchestrators may rely on the documented read-only, tightly constrained behavior while the actual code permits broader file modification and weaker SSH trust guarantees, enabling tampering or man-in-the-middle exposure.
The security comments explicitly promise the script never writes files, but the implementation later conditionally calls writeFile(args.output, report). This kind of mismatch is dangerous because operators and higher-level agents may trust the documented read-only behavior and grant the skill broader use, enabling unexpected local file writes and possible clobbering of important files.
The security documentation says the tool never writes files, but later code conditionally persists reports to disk. This kind of false security claim materially increases operational risk because reviewers, agents, or permission systems may authorize the skill under the assumption that it is read-only locally, when in fact it can create or overwrite files containing sensitive infrastructure data.
The script documentation asserts it 'NEVER ... writes files', but the code accepts an arbitrary --output path and writes the full inspection report there. In an agent setting, that mismatch is dangerous because callers or orchestrators may trust the no-write guarantee and permit execution in contexts where local file creation can overwrite files, leak sensitive server data into unexpected locations, or violate sandbox assumptions.
This markdown file contains user-facing instructions only in German, which effectively forces a specific language on users without any opt-in or alternative. Under the policy, locale or language constraints should either be optional for the user or clearly justified as region-specific.
The skill is described as read-only server inspection, but the extension guide adds a database check using mysql -e 'SHOW STATUS...', expanding the skill into direct database command execution. Even though the example appears read-only, this broadens the operational scope from host inspection to database access, increases credential and data exposure risk, and normalizes adding commands that may no longer fit the claimed safety boundary.
L'intero file di documentazione è scritto in italiano e non indica alternative linguistiche, opt-in dell'utente o che la skill sia limitata a un contesto italofono specifico. In base alla policy, imporre una lingua senza scelta esplicita può costituire una violazione di policy linguistica/locale.
O arquivo de documentação está integralmente em português e não oferece alternativa de idioma, opt-in do usuário, nem explica que a habilidade é destinada exclusivamente a um público lusófono ou contexto regional específico. Pelas regras, impor um idioma sem escolha explícita configura violação de política de linguagem/locale em linguagem natural.
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.
Suspicious Unicode normalization or mixed-script content
The installation example uses npx clawhub@latest install li_sentry_check, which relies on an unpinned package version at execution time. If the upstream package is compromised or a breaking release is published, users may execute unintended code during installation, creating a supply-chain risk.
The skill advertises significant capabilities in prose, but does not declare an explicit tool scope such as permissions or allowed-tools. In an agent environment, missing tool scoping can let the runtime expose broader file, shell, environment, and network access than the README-style safety claims imply, weakening enforcement and increasing the blast radius if the implementation is compromised or behaves unexpectedly.
The invocation guidance is broad enough that the skill may trigger on generic requests about server status, inspection, or reports. In an agent system with SSH and shell access, over-broad activation can cause the skill to run in contexts the user did not specifically intend, increasing the chance of unnecessary remote access, disclosure of system data, or use against the wrong target.
Skill grants unrestricted tool access without appropriate constraints. An agent with unfettered tool access can perform arbitrary actions including file modification, network requests, and code execution.
- ❌ Exfiltrate data to external services
- ❌ Access local files other than: `references/targets.yaml`, `references/checks.yaml`, and the SSH private key specified in `keyPath`
- ❌ Make any network connections other than SSH to the target server specified in `targets.yaml`
- ❌ Execute arbitrary commands — only commands from `references/checks.yaml` are allowed
**This skill ONLY:**
- ✅ Reads system information via predefined read-only commands
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
## Security Best Practices
- **Key permissions**: `chmod 600 ~/.ssh/li_sentry_check`
- **Host verification**: For production, pre-populate `known_hosts` instead of `accept-new`
- **Service names**: Only alphanumeric, hyphens, underscores allowed (validated before use)
- **Command allowlist**: Never modify `checks.yaml` with state-changing commands
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
## Security Best Practices
- **Key permissions**: `chmod 600 ~/.ssh/li_sentry_check`
- **Host verification**: For production, pre-populate `known_hosts` instead of `accept-new`
- **Service names**: Only alphanumeric, hyphens, underscores allowed (validated before use)
- **Command allowlist**: Never modify `checks.yaml` with state-changing commands
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
## Security Best Practices
- **Key permissions**: `chmod 600 ~/.ssh/li_sentry_check`
- **Host verification**: For production, pre-populate `known_hosts` instead of `accept-new`
- **Service names**: Only alphanumeric, hyphens, underscores allowed (validated before use)
- **Command allowlist**: Never modify `checks.yaml` with state-changing commands