AI Daily News

Security checks across malware telemetry and agentic risk

Overview

This AI news skill is mostly purpose-aligned, but it needs review because it can send user parameters and optional access tokens to configurable remote endpoints and keeps under-disclosed local ad/delivery logs.

Install only if you trust the publisher's AI Daily News service and are comfortable with remote API calls, optional token use for Pro features, and local cache/ad-delivery logging. Do not set AINEWS_SERVICE_URL or --base-url to an untrusted host, and avoid passing sensitive text through remote capabilities unless you intend to send it to that service.

SkillSpector

By NVIDIA
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (11)

Tainted flow: 'req' from os.getenv (line 250, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
url = f"{base_url or DEFAULT_SERVICE_URL}/v1/manifest"
    try:
        req = urllib.request.Request(url, headers=_build_headers())
        with urllib.request.urlopen(req, timeout=timeout) as resp:
            return json.loads(resp.read().decode("utf-8"))
    except urllib.error.HTTPError as e:
        raise NetworkError(f"Manifest HTTP error: {e.code}")
Confidence
93% confidence
Finding
with urllib.request.urlopen(req, timeout=timeout) as resp:

Tainted flow: 'req' from os.getenv (line 250, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
try:
        req = urllib.request.Request(url, headers=headers)
        # urllib.request.urlopen defaults allow_redirects=True
        with urllib.request.urlopen(req, timeout=timeout) as resp:
            return resp.read()
    except urllib.error.HTTPError as e:
        if e.code == 404:
Confidence
97% confidence
Finding
with urllib.request.urlopen(req, timeout=timeout) as resp:

Tainted flow: 'req' from os.getenv (line 250, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
headers = _build_headers(api_key)
    try:
        req = urllib.request.Request(url, headers=headers)
        with urllib.request.urlopen(req, timeout=timeout) as resp:
            return resp.read()
    except urllib.error.HTTPError as e:
        if e.code == 401:
Confidence
98% confidence
Finding
with urllib.request.urlopen(req, timeout=timeout) as resp:

Tainted flow: 'req' from os.getenv (line 250, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
try:
        req = urllib.request.Request(url, data=payload, headers=headers, method="POST")
        with urllib.request.urlopen(req, timeout=timeout) as resp:
            return json.loads(resp.read().decode("utf-8"))
    except urllib.error.HTTPError as e:
        raise NetworkError(f"Execute HTTP error: {e.code}")
Confidence
98% confidence
Finding
with urllib.request.urlopen(req, timeout=timeout) as resp:

Tainted flow: 'req' from os.getenv (line 250, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
headers = _build_headers(api_key)
    try:
        req = urllib.request.Request(url, headers=headers)
        with urllib.request.urlopen(req, timeout=timeout) as resp:
            return json.loads(resp.read().decode("utf-8"))
    except urllib.error.HTTPError as e:
        if e.code == 401:
Confidence
93% confidence
Finding
with urllib.request.urlopen(req, timeout=timeout) as resp:

Tainted flow: 'req' from os.getenv (line 250, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
headers = _build_headers(api_key)
    try:
        req = urllib.request.Request(url, headers=headers)
        with urllib.request.urlopen(req, timeout=timeout) as resp:
            return json.loads(resp.read().decode("utf-8"))
    except urllib.error.HTTPError as e:
        if e.code == 401:
Confidence
94% confidence
Finding
with urllib.request.urlopen(req, timeout=timeout) as resp:

Tainted flow: 'req' from os.getenv (line 250, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
headers = _build_headers(api_key)
    try:
        req = urllib.request.Request(url, headers=headers)
        with urllib.request.urlopen(req, timeout=timeout) as resp:
            return json.loads(resp.read().decode("utf-8"))
    except urllib.error.HTTPError as e:
        if e.code == 401:
Confidence
95% confidence
Finding
with urllib.request.urlopen(req, timeout=timeout) as resp:

Description-Behavior Mismatch

High
Confidence
96% confidence
Finding
This script is a generic remote capability invoker that can call any capability returned by the synced manifest, while the skill metadata says the skill should be used only for AI or machine-learning news. Because there is no allowlist or topic-specific enforcement, a user or upstream component could invoke unrelated or more sensitive remote actions through this skill, expanding its authority beyond its declared purpose.

Context-Inappropriate Capability

Medium
Confidence
93% confidence
Finding
The code synchronizes all remote capabilities from the server and then permits arbitrary selection by name, without verifying that the chosen capability is justified for AI-news processing. In a skill context, this broad discovery-and-execute pattern increases attack surface and can enable misuse of remote functions that were never intended to be reachable from this skill.

Context-Inappropriate Capability

Medium
Confidence
82% confidence
Finding
This code implements delivery and ad-impression logging unrelated to the declared AI news purpose, creating undisclosed behavioral tracking within the skill. Even though the data is stored locally, such hidden telemetry expands the skill's data collection surface and can be misused for profiling, audit evasion, or policy bypass when the user expects only news retrieval.

Vague Triggers

Medium
Confidence
87% confidence
Finding
The hint 'Advanced analysis, what can you do' combined with guidance to use invoke_remote_capability is insufficiently scoped and can route generic conversational queries into remote functionality. In this manifest, that risk is elevated because the same file advertises remote capabilities and instructs the agent to 'Always sync_capabilities first,' which can expand behavior based on server-controlled metadata and increase the chance of unintended remote calls.

VirusTotal

VirusTotal findings are pending for this skill version.

View on VirusTotal