T08 · Insecure Dependencies
- Location
SKILL.md:43- Finding
Unpinned External CLI Dependency Creates a Supply-Chain Trust Gap
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This is a coherent Shodan integration, but it needs Review because it uses an unpinned external CLI and defaults to running credit-consuming, mutating, scanning, and destructive operations without confirmation.
Install only if you trust the exact external shodan-skill package you install and are comfortable with an agent executing explicit Shodan requests immediately. For scans, deletions, organization changes, credit-consuming searches, and overwrites, prefer strict mode or dry-run unless you have already reviewed the exact target, account impact, and cost.
SKILL.md:43Unpinned External CLI Dependency Creates a Supply-Chain Trust Gap
SKILL.md:20High-Impact Shodan Operations Execute Without Confirmation by Default
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
Repository live tests remain fail-closed and independent from normal direct-mode CLI execution. Validate every dynamic URL path segment before constructing a transport so an identifier cannot alter the requested endpoint. Redact API keys, authorization headers, bearer tokens, cookies, provider arguments (including routing keys and webhook URLs), signed URLs, and credential-like values from all outputs and errors.
The HTTP transport ignores ambient `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, and `.netrc` settings. Use only an explicitly reviewed `SHODAN_PROXY` or root-level `--proxy` value; a proxy can observe Shodan query authentication. Prefer the environment variable when the proxy URL contains credentials, and keep every timeout finite.
Do not automatically retry credit-consuming GET requests. A user may retry explicitly after reviewing the failure; no-credit GET requests may use the bounded transport retry policy.
The snapshot enumerates numerous state-changing and potentially destructive operations, including scan initiation, alert management, notifier management, and organization membership changes, without any embedded constraints, approval gates, or trigger scoping. In this skill’s context, the metadata explicitly says to treat the user’s request as authorization to execute without second confirmation, which increases the chance of unsafe or over-broad actions being performed from loosely scoped prompts.
The file explicitly documents that state-changing operations run in a default direct mode that continues without confirmation or an authorization acknowledgement. In a skill that can create scans, alerts, and notifiers or delete and modify them, this enables autonomous execution of impactful external actions from a user's prompt, increasing the risk of unintended scans, monitoring changes, destructive deletions, and credit consumption.
shodan-skill notifier delete <NOTIFIER_ID>
Every mutation emits a deterministic JSON preview before sending HTTP. The preview includes the operation, identifiers, target count when calculable, credit impact, and reversibility. Default `direct` mode continues without confirmation or an authorization acknowledgement. Use `--dry-run` to stop after preview, or select `strict` mode to restore the compatibility gates.
On-demand scans can consume scan credits. Internet-wide scans require Enterprise access. Validate every target, custom service, alert/notifier ID, trigger, and ignored `IP:PORT` service before creating a transport. Reject separators and traversal segments in every dynamic URL path segment so the requested operation cannot be rewritten.
Skill allows unbounded resource consumption (API calls, storage, compute). Without rate limits or quotas, a compromised or misbehaving agent can cause denial-of-service or cost overruns.
Trends.search(query, facets)
Trends.search_filters()
Trends.search_facets()
Stream.banners(raw=False, timeout=None)
Stream.asn(asn, raw=False, timeout=None)
Stream.countries(countries, raw=False, timeout=None)
Stream.ports(ports, raw=False, timeout=None)
Skill allows unbounded resource consumption (API calls, storage, compute). Without rate limits or quotas, a compromised or misbehaving agent can cause denial-of-service or cost overruns.
Trends.search(query, facets)
Trends.search_filters()
Trends.search_facets()
Stream.banners(raw=False, timeout=None)
Stream.asn(asn, raw=False, timeout=None)
Stream.countries(countries, raw=False, timeout=None)
Stream.ports(ports, raw=False, timeout=None)
Skill allows unbounded resource consumption (API calls, storage, compute). Without rate limits or quotas, a compromised or misbehaving agent can cause denial-of-service or cost overruns.
Trends.search(query, facets)
Trends.search_filters()
Trends.search_facets()
Stream.banners(raw=False, timeout=None)
Stream.asn(asn, raw=False, timeout=None)
Stream.countries(countries, raw=False, timeout=None)
Stream.ports(ports, raw=False, timeout=None)
Skill allows unbounded resource consumption (API calls, storage, compute). Without rate limits or quotas, a compromised or misbehaving agent can cause denial-of-service or cost overruns.
Trends.search(query, facets)
Trends.search_filters()
Trends.search_facets()
Stream.banners(raw=False, timeout=None)
Stream.asn(asn, raw=False, timeout=None)
Stream.countries(countries, raw=False, timeout=None)
Stream.ports(ports, raw=False, timeout=None)
Skill allows unbounded resource consumption (API calls, storage, compute). Without rate limits or quotas, a compromised or misbehaving agent can cause denial-of-service or cost overruns.
Trends.search(query, facets)
Trends.search_filters()
Trends.search_facets()
Stream.banners(raw=False, timeout=None)
Stream.asn(asn, raw=False, timeout=None)
Stream.countries(countries, raw=False, timeout=None)
Stream.ports(ports, raw=False, timeout=None)
Skill allows unbounded resource consumption (API calls, storage, compute). Without rate limits or quotas, a compromised or misbehaving agent can cause denial-of-service or cost overruns.
Trends.search(query, facets)
Trends.search_filters()
Trends.search_facets()
Stream.banners(raw=False, timeout=None)
Stream.asn(asn, raw=False, timeout=None)
Stream.countries(countries, raw=False, timeout=None)
Stream.ports(ports, raw=False, timeout=None)
Skill allows unbounded resource consumption (API calls, storage, compute). Without rate limits or quotas, a compromised or misbehaving agent can cause denial-of-service or cost overruns.
Trends.search(query, facets)
Trends.search_filters()
Trends.search_facets()
Stream.banners(raw=False, timeout=None)
Stream.asn(asn, raw=False, timeout=None)
Stream.countries(countries, raw=False, timeout=None)
Stream.ports(ports, raw=False, timeout=None)
Skill allows unbounded resource consumption (API calls, storage, compute). Without rate limits or quotas, a compromised or misbehaving agent can cause denial-of-service or cost overruns.
Trends.search(query, facets)
Trends.search_filters()
Trends.search_facets()
Stream.banners(raw=False, timeout=None)
Stream.asn(asn, raw=False, timeout=None)
Stream.countries(countries, raw=False, timeout=None)
Stream.ports(ports, raw=False, timeout=None)
This markdown file states that exploit code is preserved by default and only mentions optional flags to omit or truncate it. Because displaying or handling exploit code can affect user safety and downstream use, the description should include an explicit warning so users understand the sensitivity of the content.
The manifest references English-language developer documentation URLs only, and there is no indication that language selection is configurable or user-chosen. If this snapshot is used to govern skill behavior or documentation lookup, it may implicitly force a single language/locale without user opt-in.