T05 · Unauthorized Access and Privilege Escalation
- Location
main.py:60- Finding
Mandatory Third-Party Billing and User Identifier Disclosure Are Not Declared in Skill Metadata
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill performs the advertised layoff-news analysis, but it also automatically contacts a billing service and attempts a $0.02 charge before analysis without declaring that in the skill metadata.
Review this carefully before installing. Expect outbound calls to Google News/RSS-linked article sites, OpenAI if OPENAI_API_KEY is set, and SkillPay. Do not run it unless you are comfortable with a mandatory per-call charge flow tied to a user_id, and prefer an isolated runtime with restricted network access and pinned dependencies.
main.py:60Mandatory Third-Party Billing and User Identifier Disclosure Are Not Declared in Skill Metadata
news_fetcher.py:49Remote RSS Entry URLs Are Downloaded Without SSRF or Resource Controls
requirements.txt:1Dependencies Are Installed With Unbounded Future Versions and Without Integrity Verification
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
.env
__pycache__/
*.pyc
*.pyo
The skill claims to detect AI-driven layoffs from global news and generate structured reports, but the manifest only gives high-level instructions and example output without defining reliable sourcing, validation, or causality criteria. This mismatch can mislead users into overtrusting the results of a sensitive reputational-analysis workflow and may produce inaccurate or fabricated risk reports.
The skill claims to detect AI-driven layoffs from global news and generate structured reports, but the manifest only gives high-level instructions and example output without defining reliable sourcing, validation, or causality criteria. This mismatch can mislead users into overtrusting the results of a sensitive reputational-analysis workflow and may produce inaccurate or fabricated risk reports.
The skill claims to detect AI-driven layoffs from global news and generate structured reports, but the manifest only gives high-level instructions and example output without defining reliable sourcing, validation, or causality criteria. This mismatch can mislead users into overtrusting the results of a sensitive reputational-analysis workflow and may produce inaccurate or fabricated risk reports.
The skill claims to detect AI-driven layoffs from global news and generate structured reports, but the manifest only gives high-level instructions and example output without defining reliable sourcing, validation, or causality criteria. This mismatch can mislead users into overtrusting the results of a sensitive reputational-analysis workflow and may produce inaccurate or fabricated risk reports.
This file implements balance checks, charging, and payment-link generation for an external billing service, which is materially unrelated to the skill's declared purpose of analyzing layoff news and generating reports. Hidden or unnecessary monetization logic expands the skill's capability to debit users or transmit billing-related identifiers without clear necessity, making abuse or unauthorized charging more dangerous in this context.
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.
DEV mode:
- Set `SKILLPAY_DEV_MODE=true` to bypass live billing calls during local development.
- In DEV mode, billing functions simulate success responses (for example balance `999`).
- In non-DEV mode, missing `SKILLPAY_API_KEY` raises: `SKILLPAY_API_KEY not configured`.
The skill metadata declares use of an environment variable and implies external news access, but it does not define explicit tool scope such as allowed network or env permissions. This weakens least-privilege controls and can let a runtime grant broader capabilities than reviewers or users expect.
The activation guidance uses broad phrases like 'AI layoffs' and 'companies replacing workers with AI' without scope limits, exclusions, or thresholds for evidence. That can cause over-triggering in unrelated contexts and increase the chance of producing defamatory, inaccurate, or low-confidence claims about companies and layoffs.
The code sends event content, including title, summary, reason, and up to 2000 characters of text, to an external OpenAI API. If those fields contain sensitive, proprietary, or personal data, this creates a real data exposure and third-party processing risk, especially because there is no consent, redaction, or policy gate in this file before transmission.
The code loads a billing API key from environment variables and uses it to interact with an external payment API, despite the skill being described only as a news-analysis tool. While using environment variables for secrets is normal, the concerning issue is the presence of external billing capabilities and credentialed payment operations that are outside the stated function, increasing the risk of undisclosed financial actions and data transmission.
The charge_user function can attempt to debit a user's account directly with no evidence of prior user notice, confirmation, or authorization in this component. In a skill whose advertised purpose is informational analysis, silent charging behavior is especially risky because users would not reasonably expect financial side effects from invoking the skill.
This POST transmits user_id, skill_id, amount, and currency to an external billing endpoint. External transmission by itself is not always unsafe, but here it supports an undisclosed billing action outside the skill's stated purpose, so the context makes the data flow more sensitive and potentially harmful.
"currency": "USD",
}
try:
response = requests.post(
url,
json=payload,
headers=_headers(),
This POST sends user and payment metadata to an external service to generate a payment link. Although payment-link creation is less severe than direct charging, it still initiates a monetization workflow unrelated to the declared layoff-analysis function and exposes user identifiers to a third party.
"currency": "USD",
}
try:
response = requests.post(
url,
json=payload,
headers=_headers(),
The skill performs billing checks, charges the user, and generates payment links even though its stated purpose is news analysis and layoff reporting. This expands the skill’s operational scope into payments, increasing abuse and user-surprise risk, especially because the billing logic is embedded directly in the main execution path before the reporting function completes.
Payment processing is not justified by the visible function of detecting AI-related layoffs, so the code introduces a capability unrelated to the expected task. In a skill ecosystem, unnecessary financial operations materially increase risk because they can charge users or redirect them into payment flows without a clear, task-related need.
The code automatically calls charge_user(user_id=user_id) during execution with no in-file evidence of a user-facing confirmation, preview, or authorization step. Automatic charging is dangerous because a routine analysis request can directly trigger financial impact, and users may only discover the charge after the fact.
The query URL forces hl=en-US, gl=US, and ceid=US:en, which imposes a specific language and locale in the skill's behavior. The file does not offer user opt-in, configurability, or a documented region-specific justification for this constraint.
The dependency is specified with a lower bound only, which allows future installs to resolve to different versions over time. This weakens reproducibility and can unintentionally pull in vulnerable or breaking releases, especially for a network-facing library like requests.
requests>=2.31.0
feedparser>=6.0.11
beautifulsoup4>=4.12.3
openai>=1.30.0
requests has multiple known advisories, and because the manifest does not pin a version, it is impossible to verify whether the installed release is affected. In a skill that retrieves external content, this uncertainty is more significant because a vulnerable HTTP client could expose credentials, mishandle redirects, or weaken TLS/request safety.
feedparser is unpinned, so builds are not reproducible and may silently install different versions in different environments. Because this skill ingests external news/RSS data, dependency drift can increase exposure to parser-related security issues if a bad release or affected version is installed.
requests>=2.31.0
feedparser>=6.0.11
beautifulsoup4>=4.12.3
openai>=1.30.0
newspaper3k>=0.2.8
feedparser has known historical advisories, and without version pinning there is no assurance that deployments avoid affected releases. Since this skill consumes untrusted feeds from the public internet, parser vulnerabilities are more relevant than in a closed-input application.
beautifulsoup4 is declared with a minimum version rather than an exact version, which permits uncontrolled upgrades. That creates supply-chain and stability risk because the installed package may vary by install time and environment.
requests>=2.31.0
feedparser>=6.0.11
beautifulsoup4>=4.12.3
openai>=1.30.0
newspaper3k>=0.2.8
lxml[html_clean]>=5.2.1
The openai package is unpinned, so deployments may receive different versions with changed behavior or newly introduced flaws. While this file alone does not prove exploitation, allowing unconstrained dependency resolution is a real supply-chain hygiene weakness.
requests>=2.31.0
feedparser>=6.0.11
beautifulsoup4>=4.12.3
openai>=1.30.0
newspaper3k>=0.2.8
lxml[html_clean]>=5.2.1
python-dateutil>=2.9.0
newspaper3k is unpinned despite being used for article fetching/parsing from external content sources. For a skill that processes untrusted web content, reproducible parser versions matter because silent upgrades can introduce exploitable parsing behavior or dependency issues.
feedparser>=6.0.11
beautifulsoup4>=4.12.3
openai>=1.30.0
newspaper3k>=0.2.8
lxml[html_clean]>=5.2.1
python-dateutil>=2.9.0