T09 · Insecure Skill Coding Practices
- Location
src/config.js:74- Finding
Plaintext Storage and Exposure of Webhook Credentials
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This earthquake alert skill mostly does what it says, but it makes misleading security and data-source claims that could expose webhook secrets or overstate alert reliability.
Review this skill before installing. Do not store token-bearing webhook URLs in its config unless you are comfortable with plaintext local storage, and treat its earthquake alerts as dependent on a third-party aggregator rather than direct verified government feeds. Network polling and local config writes are expected for this kind of skill, but the documentation should be corrected before sensitive use.
src/config.js:74Plaintext Storage and Exposure of Webhook Credentials
src/cenc.js:12Safety-Critical Earthquake Data Is Trusted from an Undisclosed Third-Party Aggregator
The documentation is internally inconsistent: the changelog says encryption for webhook storage was removed, while the Security section still claims webhook URLs are AES-256-CBC encrypted at rest. This can mislead users into storing sensitive webhook secrets under false assumptions, causing credential exposure if configs are plaintext or otherwise recoverable.
The skill advertises shell-capable behavior via required binaries like curl but does not declare any explicit tool scope or permissions boundary. This weakens reviewability and can lead users or hosts to grant broader execution/network capabilities than expected, increasing the risk of misuse or unnoticed command execution.
The skill exposes a configurable webhook feature but does not prominently warn that earthquake data and alert content will be transmitted to an external endpoint controlled by the user. Without clear disclosure, users may unintentionally send sensitive operational context or tokens to third-party services, especially since webhook URLs themselves often embed secrets.
This config sets the language to "en" explicitly, which can constitute a language/locale policy violation when there is no visible opt-in, alternative choice, or documented justification. In a region-specific context centered on a Chinese location, forcing English may conflict with expected user locale behavior.
The skill's stated purpose is real-time earthquake monitoring, which justifies network access to fetch feeds, but not spawning shell commands. Using child_process.exec with curl introduces an execution capability broader than necessary for this monitoring function.
The configuration sets language: 'zh' as the default, which imposes a specific language choice before the user has selected a preference. The policy allows locale constraints only when users are given a choice or when the restriction is clearly justified, neither of which is present here.
The skill's purpose is real-time earthquake monitoring, which justifies outbound network access, but not spawning a shell to run curl. Invoking child_process adds an unnecessary execution capability that is broader than needed for retrieving remote JSON and is not justified by the manifest description.
The module auto-detects output language solely from the data source and falls back to 'zh' for unknown sources. This can force a specific language/locale on users without offering a choice, which matches the policy's language/locale violation criteria.
The skill's stated purpose is real-time earthquake monitoring using external data feeds, which justifies network access, but spawning a subprocess to run curl is not an obvious or necessary capability for that purpose. Using child_process expands the skill's effective capability beyond straightforward data retrieval and introduces command-execution behavior unrelated to the manifest's described monitoring role.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
}
try {
const { stdout } = await execPromise('curl -s --max-time 10 "https://api.wolfx.jp/jma_eqlist.json"');
const json = JSON.parse(stdout);
const data = [];
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
}
try {
const { stdout } = await execPromise('curl -s --max-time 10 "https://api.wolfx.jp/jma_eqlist.json"');
const json = JSON.parse(stdout);
const data = [];
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
}
try {
const { stdout } = await execPromise('curl -s --max-time 10 "https://api.wolfx.jp/jma_eqlist.json"');
const json = JSON.parse(stdout);
const data = [];
The code hard-codes zh as the fallback language when no user language is configured. This creates a locale policy issue because the skill defaults to a specific language rather than offering a user choice or requiring explicit opt-in.
The start(options) section states that the skill performs proactive monitoring with auto-alerts every 60 seconds, which indicates recurring polling and possible downstream notifications. The markdown does not explicitly warn users that enabling this behavior may generate continuous network requests and automated alerts until stopped.
The initialization API documents a default language of 'zh' and the user-facing initialization message presents that language setting as the default behavior. This can violate language/locale policy expectations when a skill selects a specific language without first asking the user or clearly making it opt-in.
The dependency uses a caret range (^8.19.0) rather than an exact pinned version, which makes builds non-reproducible and can cause different installations to resolve to different ws releases over time. In a network-facing skill that relies on WebSocket handling, this increases supply-chain and patch-state uncertainty, though by itself it is not direct code execution.
},
"readme": "SKILL.md",
"dependencies": {
"ws": "^8.19.0"
}
}
The manifest references ws without pinning an exact version, and ws has a history of security advisories including denial-of-service and memory disclosure issues. Because the exact resolved version is not fixed here, it is impossible to verify from this file alone whether deployments will avoid affected releases, which is risky for a real-time earthquake monitoring skill likely to maintain network connections and process remote data.
The module persists configuration data to disk via fs.writeFileSync, which affects user/system data, but the only surrounding messaging is an internal error log on failure. There is no confirmation prompt, user-facing notice, or explanatory comment/docstring warning that configuration changes will be written to config.json.
This file contains natural-language text in a single language ('距离计算 - Haversine 公式') with no indication that the skill offers a language choice or is intentionally limited to a Chinese-speaking context. The policy requires flagging language or locale constraints when they are forced without user opt-in or clear justification.