Back to skill

Security audit

MorningAI

Security checks for vulnerabilities and agentic risk

Overview

MorningAI is mostly a coherent AI news-report skill, but its installed startup hook automatically executes workspace config files as shell code.

Review before installing. The main news-report functionality is understandable, but do not use this package in untrusted repositories unless the SessionStart hook is removed or changed to parse only a MorningAI-specific config file as data. Expect optional API keys to be read locally and sent only to their respective services, and expect message digest outputs to include MorningAI branding.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
hooks/scripts/check-config.sh:6
Finding

Automatic Arbitrary Shell Execution Through Workspace Environment Files

Content
View full analysis
/dev/null || true set +a fi ``` `PROJECT_ENV` is defined immediately before this range as `.claude/morning-ai.env`. ### Technical Analysis The Skill registers an unconditional `SessionStart` command hook. During session initialization, that hook runs `check-config.sh`, which searches the current workspace for `.claude/morning-ai.env` and `.env`. The selected file is loaded with Bash's `source` command. `source` does not parse a file as passive `KEY=value` configuration; it evaluates the complete file as shell syntax in the current process. Consequently, command substitutions, function calls, redirections, pipelines, and arbitrary shell commands embedded in a workspace environment file are executed. This crosses a significant trust boundary because workspace files may be supplied by an untrusted repository, while the hook executes with the local agent user's permissions. It also exceeds the minimum privileges required to determine which MorningAI configuration options are enabled. The project already contains a non-executing enviro ...[truncated 1692 chars]
Remediation
View remediation

T01 · Skill Instruction Hijacking

Error
Location
skills/gen-message/SKILL.md:138
Finding

Mandatory MorningAI Branding Injected Into Generated Digest Outputs

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (84)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description is highly specific about substantial functionality, but the supplied code chunk contains only a file comment and no executable logic demonstrating those capabilities. While the brief comment loosely aligns with a generic data collection concept, it does not substantiate the claimed primary purpose or features. Therefore, the code as provided does not accurately represent the declared behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The supplied code chunk does not implement scheduled news collection or report generation. Its actual role is an entity-loader/parser subsystem: it reads Markdown files from project and user config directories, parses several entity-table formats, extracts platform handles/queries, and merges them into registries. While this may support a news tracker, the declared description presents the skill as a daily-scheduled collector/report generator and declares no permissions, whereas this code clearly performs local file reads and environment-variable-based configuration lookup. Those are materially different from the stated primary behavior and resource access, so this chunk is a description-behavior mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description is focused on scheduled AI news collection, deduplication, scoring, and Markdown report generation. The supplied code does none of that. Instead, it provides an image generation subsystem that calls third-party image APIs, handles API keys, decodes base64 image responses, and saves image files locally. This is a materially different purpose and introduces undeclared capabilities (external image generation and file output) unrelated to the stated news-tracker functionality. While such code could theoretically be part of a larger project, this specific chunk is not accurately represented by the declared description.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description is about scheduled AI news aggregation, scoring, deduplication, and Markdown report generation. The supplied code does none of that. Instead, it is an image-manipulation helper that opens local image files, resizes them, composites them into one long image, and saves a PNG. This is a materially different primary purpose and introduces undeclared filesystem/image-processing behavior unrelated to the stated news-tracking functionality.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The code chunk does not implement an AI news tracker. Instead, it provides database persistence and comparison logic for leaderboard snapshots. Its primary purpose is leaderboard state storage and change detection, not collecting AI news from multiple sources on a schedule or generating deduplicated Markdown reports. The local SQLite access is also inconsistent with the declared description's stated behavior. This is a material description-behavior mismatch, not merely a supporting utility for the declared functionality, because the code is centered on a different domain object (leaderboards/models/ranks/scores) and lacks the declared news-tracking capabilities.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description is for a scheduled AI news aggregation and reporting skill. The supplied code does not collect news, schedule execution, deduplicate content, score updates, or generate Markdown reports. Instead, it is a local deployment script whose primary purpose is to install/sync the skill into multiple client/tool directories. This is a materially different purpose and introduces undeclared file-system modification capabilities, including creating directories, copying files, and deleting target contents via rsync --delete. Therefore the description does not accurately represent this code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description is for a scheduled news aggregation/reporting tool: it should collect AI news from multiple sources on a daily cadence, deduplicate and score results, and emit Markdown reports. The supplied code does none of that. Instead, it accepts prompts or manifest files, injects style text, calls image-generation functions, saves PNG files, and can stitch images together. There is no evidence of news-source collection, scheduling logic, entity tracking, deduplication, scoring, Markdown report generation, or idempotent date-stamped reporting behavior as the primary purpose. This is a clear purpose and capability mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description is for an automated AI news aggregation and reporting skill with scheduled execution, source collection, deduplication, scoring, and Markdown output. The supplied code chunk does none of that. It is a static configuration module for image/infographic styling, containing text prompt presets for visual themes such as classic, dark, glassmorphism, newspaper, and tech, plus section continuity and background color settings for stitched images. This is a materially different primary purpose, not a supporting implementation detail of the declared news tracker. Therefore, the description does not accurately represent the code.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description describes an automated AI news aggregation and reporting tool. The supplied code instead implements a CLI with two commands: save a dated leaderboard snapshot from provided JSON data and show the latest saved snapshot. It imports snapshot utilities, parses command-line arguments, saves data, computes diffs, and prints JSON. There is no evidence of fetching news from sources, scheduled execution, deduplication/scoring of news, or Markdown report generation. The primary purpose is materially different, so this is a clear mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding

The code substantially aligns with the core declared purpose of collecting AI-related updates over a daily window, scoring, deduplicating, and producing date-based output for automation. However, there are notable description-behavior discrepancies. Most importantly, the script produces JSON output, not Markdown as declared. Also, this code chunk defines only five collectors, whereas the description claims six sources. The daily schedule itself is not implemented here; the script is runnable in unattended contexts, but actual cron/scheduling behavior is external rather than present in the code. Finally, it includes cache-control and cache-clearing features not mentioned in the description. These differences are material enough to count as a mismatch, though the primary purpose is broadly similar.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

The skill explicitly instructs the agent to probe for and then read .env files, including a global config under the user's home directory. Accessing credential-bearing files is sensitive because it expands the skill from public-news collection into local secret discovery, and an agent following the instructions could expose active source configuration or tokens to the conversation or downstream processing.

Content

Scanner excerpt · SKILL.md (reported line 63)May include surrounding context.

Run this command FIRST before doing anything else:

bash
if [ -f "$HOME/.config/morning-ai/.env" ] || [ -f ".claude/morning-ai.env" ] || [ -f ".env" ]; then echo "CONFIG_STATUS=READY"; else echo "CONFIG_STATUS=MISSING"; fi

Branch on the output:

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · entities/custom-example.md (reported line 3)May include surrounding context.

md
# Custom Entity Watchlist — Example

<!-- This is a template. Copy it to create your own watchlist:
     cp entities/custom-example.md entities/custom/my-watchlist.md
     Then edit the copy. Files in entities/custom/ are gitignored. -->

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 114)May include surrounding context.

md
set -euo pipefail

PROJECT_ENV=".claude/morning-ai.env"
GLOBAL_ENV="$HOME/.config/morning-ai/.env"

# Find active config
ACTIVE_ENV=""

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · hooks/scripts/check-config.sh (reported line 6)May include surrounding context.

sh
set -euo pipefail

PROJECT_ENV=".claude/morning-ai.env"
GLOBAL_ENV="$HOME/.config/morning-ai/.env"

# Find active config
ACTIVE_ENV=""

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · hooks/scripts/check-config.sh (reported line 12)May include surrounding context.

sh
set -euo pipefail

PROJECT_ENV=".claude/morning-ai.env"
GLOBAL_ENV="$HOME/.config/morning-ai/.env"

# Find active config
ACTIVE_ENV=""

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · hooks/scripts/check-config.sh (reported line 13)May include surrounding context.

sh
set -euo pipefail

PROJECT_ENV=".claude/morning-ai.env"
GLOBAL_ENV="$HOME/.config/morning-ai/.env"

# Find active config
ACTIVE_ENV=""

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · lib/env.py (reported line 51)May include surrounding context.

python
set -euo pipefail

PROJECT_ENV=".claude/morning-ai.env"
GLOBAL_ENV="$HOME/.config/morning-ai/.env"

# Find active config
ACTIVE_ENV=""

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · lib/env.py (reported line 53)May include surrounding context.

python
set -euo pipefail

PROJECT_ENV=".claude/morning-ai.env"
GLOBAL_ENV="$HOME/.config/morning-ai/.env"

# Find active config
ACTIVE_ENV=""

Lp1

High
Category
MCP Least Privilege
Confidence
75% confidence
Finding

The skill uses 'env' capability that is not listed in its permissions. This may indicate deceptive intent or missing permission declarations.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · lib/env.py (reported line 54)May include surrounding context.

python
global_env = load_env_file(str(Path.home() / ".config" / "morning-ai" / ".env"))
    project_claude_env = load_env_file(".claude/morning-ai.env")
    project_env = load_env_file(".env")
    local_env = load_env_file(".env.local")

    config = {}
    config.update(global_env)

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
70% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · lib/env.py (reported line 61)May include surrounding context.

python
config.update(project_claude_env)
    config.update(project_env)
    config.update(local_env)
    config.update({k: v for k, v in os.environ.items() if k.startswith(("MORNING_AI_", "GITHUB_", "IMAGE_GEN_", "IMAGE_STYLE", "GEMINI_", "MINIMAX_", "SOCIAL_", "MESSAGE_"))})

    return config

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 119)May include surrounding context.

md
from typing import Any, Dict, List, Optional

from . import http
from .env import get_key

IMAGE_GEN_TIMEOUT = 120

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 468)May include surrounding context.

md
from typing import Any, Dict, List, Optional

from . import http
from .env import get_key

IMAGE_GEN_TIMEOUT = 120

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · hooks/scripts/check-config.sh (reported line 56)May include surrounding context.

sh
from typing import Any, Dict, List, Optional

from . import http
from .env import get_key

IMAGE_GEN_TIMEOUT = 120

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · lib/env.py (reported line 28)May include surrounding context.

python
from typing import Any, Dict, List, Optional

from . import http
from .env import get_key

IMAGE_GEN_TIMEOUT = 120

Static analysis

No suspicious patterns detected.