T08 · Insecure Dependencies
- Location
scripts/fetch_and_digest.py:12- Finding
Unpinned Dependencies Are Installed Automatically at Runtime
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This is a mostly coherent news digest skill, but it can silently install unpinned Python packages at runtime and fetch or post to user-configured network URLs, so it needs review before use.
Install only if you are comfortable reviewing and controlling the runtime environment. Preinstall pinned dependencies instead of allowing automatic pip installs, use only trusted RSS and webhook URLs, avoid running it with access to internal networks or sensitive environment variables, and verify any cron schedule and destination channel before enabling recurring delivery.
scripts/fetch_and_digest.py:12Unpinned Dependencies Are Installed Automatically at Runtime
scripts/fetch_and_digest.py:35Unrestricted Configurable URLs Permit Server-Side Request Forgery
scripts/fetch_and_digest.py:89Network Operations Lack Timeouts and Can Block Scheduled Runs Indefinitely
The skill description promises RSS retrieval and webhook delivery but does not accurately represent implementation details or privilege needs, especially the undeclared outbound network access. Description-behavior mismatches are dangerous because operators may approve or invoke the skill under false assumptions, leading to unexpected data egress, package installation, or messaging actions.
Automatic dependency installation via shell commands is not necessary for the stated business logic of fetching feeds and sending digests. In this context, it is more dangerous because the script is intended to run unattended on a schedule, so it may repeatedly execute package-installation code and silently pull remote code into a privileged environment.
The script executes a shell command at runtime to install a missing dependency. Even though the package name is hardcoded, invoking pip from the running process causes unreviewed code from an external package index to be fetched and executed automatically, which is risky in an automation skill and expands the attack surface considerably.
import feedparser
except ImportError:
print("Installing required package: feedparser")
os.system(f"{sys.executable} -m pip install feedparser")
import feedparser
# HTTP requests
This repeats the same unsafe behavior for the requests package: the script launches a shell command to install code at execution time. That enables automatic retrieval and execution of third-party code without review or user approval, which is unjustified for a news aggregation utility.
import requests
except ImportError:
print("Installing required package: requests")
os.system(f"{sys.executable} -m pip install requests")
import requests
The example trigger phrases are very broad and can cause the skill to activate in response to common user requests without clearly signaling that it will fetch external content and potentially distribute outputs. In a skill that performs scheduled aggregation and outbound delivery, vague activation language increases the risk of unintended invocation and data handling beyond user expectations.
The README explicitly advertises sending news to Feishu but does not warn that content will be transmitted to an external messaging platform. This can mislead users about where data goes, and in practice could expose article selections, generated summaries, or configuration metadata to third-party services without informed consent.
Describing scheduled push functionality without warning about automatic outbound delivery obscures that the skill may continue sending content on a recurring basis after initial setup. In an automation context, this raises the risk of unintended persistent data transmission, spam, or delivery to the wrong destination if configuration is mistaken or outdated.
The skill declares operational behavior that requires environment access, file reads, network access, and shell execution, but it does not declare any tool scope or permissions. This creates a transparency and containment problem: an agent or reviewer cannot accurately assess what the skill is allowed to do, increasing the chance of unintended outbound requests or secret handling without explicit approval.
The manifest description says to use the skill whenever a user wants daily news summaries, RSS aggregation, or scheduled content delivery, which are broad intents that can overlap with common requests and many other skills. It does not define specific trigger phrases, scope limits, or exclusion conditions that clarify when this skill should activate versus when it should not.
The top-level docstring explicitly states that the script summarizes articles using an LLM. The actual implementation only parses RSS feeds and truncates entry summaries in fetch_feeds and generate_digest, so the documentation actively misrepresents the behavior.
Both the manifest and module docstring claim the skill aggregates articles using LLM summarization. In practice, the code only reads the existing RSS 'summary' field and truncates it to fixed lengths when storing and rendering articles, with no LLM invocation or article summarization logic present.
Installing packages automatically without user confirmation is unsafe operationally and security-wise, especially for a scheduled agent skill. The code changes the runtime environment and executes remote package installation implicitly, which can surprise operators and undermine change control even if no direct command injection is present.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
"content": chunk,
"username": "News Digest"
}
response = requests.post(webhook_url, json=payload)
if response.status_code != 204:
print(f"Discord error: {response.status_code} - {response.text}")
else:
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
"content": chunk,
"username": "News Digest"
}
response = requests.post(webhook_url, json=payload)
if response.status_code != 204:
print(f"Discord error: {response.status_code} - {response.text}")
else:
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
"content": chunk,
"username": "News Digest"
}
response = requests.post(webhook_url, json=payload)
if response.status_code != 204:
print(f"Discord error: {response.status_code} - {response.text}")
else:
The functional description and usage examples are entirely in Chinese, and the examples imply operation in that language only. Because no user language choice or locale justification is documented, this may violate the policy against forcing a specific language without opt-in.
No suspicious patterns detected.