Back to skill

Security audit

Engineering Manager Intelligence — Team Performance & Project Health

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to be a real engineering reporting tool, but it needs Review because it silently installs dependencies and stores/sends sensitive engineering credentials and reports with weak scoping controls.

Install only if you are comfortable reviewing the setup flow first. Use a virtual environment or container, avoid broad GitHub repo tokens when a fine-grained read-only token will work, protect and exclude the generated .env file, verify GitLab/Jira URLs and Slack webhook destinations, and test with --dry-run or print delivery before sending reports to chat or email.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (29)

subprocess module call

Medium
Category
Dangerous Code Execution
Content
if not req_file.exists():
        return True
    try:
        result = subprocess.run(
            [sys.executable, "-m", "pip", "install", "-r", str(req_file), "-q"],
            capture_output=True,
            text=True,
Confidence
83% confidence
Finding
The wizard automatically runs 'pip install -r requirements.txt' during setup, which executes package installation code from the local repository without explicit user confirmation or integrity verification. If the skill repository or dependency chain is tampered with, setup can trigger untrusted code execution on the user's machine.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
# ── Build Docker image if needed ──────────────────────────────────
    if runtime == "docker":
        print("Building Docker image (first time, ~30s)...")
        build = subprocess.run(
            ["docker", "build", "-t", "em-intel", str(SKILL_DIR), "-q"],
            cwd=str(SKILL_DIR),
        )
Confidence
82% confidence
Finding
Automatically building a Docker image from the local skill directory causes Docker to process the repository's Dockerfile and build context, which may execute attacker-controlled build steps if the skill contents are malicious or altered. In a setup wizard for a third-party skill, this increases the chance of local code execution during onboarding.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
needed = {"requests", "dotenv", "rich", "jinja2", "markdown"}
        missing = [p for p in needed if not importlib.util.find_spec(p)]
        if missing:
            subprocess.run(
                [sys.executable, "-m", "pip", "install", "-r", str(req), "-q"],
                check=False,
                capture_output=True,
Confidence
98% confidence
Finding
The skill automatically invokes pip to install dependencies at import/startup without user confirmation. This creates an unnecessary code-execution and supply-chain risk surface for a reporting tool, because startup behavior now depends on external package resolution and whatever is pinned in requirements.txt.

Tainted flow: 'webhook_url' from os.getenv (line 68, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Content
return _send_print(text, title)

    try:
        resp = requests.post(
            webhook_url,
            json={"text": f"*{title}*\n\n{text}"},
            timeout=15,
Confidence
88% confidence
Finding
The Slack webhook URL is taken directly from an environment variable and used as the full request destination. If an attacker can influence that environment variable, they can redirect report contents to an arbitrary external endpoint, causing exfiltration of potentially sensitive team, project, or ticket data; this skill context increases risk because it aggregates internal engineering intelligence.

Tainted flow: 'url' from os.getenv (line 134, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Content
url = env_checks["GITLAB_URL"].rstrip("/")
            group = quote_plus(env_checks["GITLAB_GROUP"])
            try:
                resp = requests.get(
                    f"{url}/api/v4/groups/{group}/merge_requests",
                    headers={"PRIVATE-TOKEN": env_checks["GITLAB_TOKEN"]},
                    params={"per_page": 1, "state": "merged"},
Confidence
87% confidence
Finding
The code sends the GitLab token to a base URL taken directly from environment configuration. If an attacker can influence GITLAB_URL, the doctor command will transmit credentials to an attacker-controlled host, effectively enabling SSRF-style outbound requests with secret leakage.

Tainted flow: 'jira_url' from os.getenv (line 201, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Content
).decode()
            project = env_checks_t["JIRA_PROJECTS"].split(",")[0].strip()
            try:
                resp = requests.get(
                    f"{jira_url}/rest/api/3/search/jql",
                    headers={
                        "Authorization": f"Basic {creds}",
Confidence
93% confidence
Finding
The Jira doctor check constructs an authenticated request using JIRA_URL from the environment and includes a Basic auth header derived from email and token. If JIRA_URL is malicious or mistyped, credentials can be exfiltrated to an arbitrary endpoint, making this more severe than a simple connectivity check.

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill declares no permissions, yet the instructions clearly invoke shell commands, write a .env file, access environment data, install packages, and contact external services. That mismatch is dangerous because users or platforms may treat the skill as low-privilege while it actually performs sensitive actions including credential handling and network access.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The published description frames the skill as a reporting tool, but the instructions reveal materially broader behavior: interactive credential collection, browser launching, dependency installation, connectivity testing, and shell-based execution. This is risky because operators may authorize or trigger it expecting passive analysis while it performs setup and execution actions that can change the host environment and expose credentials.

Description-Behavior Mismatch

Medium
Confidence
96% confidence
Finding
The setup guide instructs users to create a GitHub token with the broad `repo` scope even though the skill is described as read-oriented analytics and reporting. `repo` grants extensive access to private repositories, including write-capable operations in many contexts, so compromise or misuse of this token could expose source code or enable unauthorized repository actions beyond the skill's stated need.

Context-Inappropriate Capability

Medium
Confidence
98% confidence
Finding
Bootstrapping dependencies by calling pip at startup is unrelated to normal reporting functionality and expands the trust boundary to package indexes and requirements contents every time the tool runs. In an agent skill context, hidden installation behavior is especially risky because users may not expect networked package changes or subprocess execution during simple use.

Description-Behavior Mismatch

Medium
Confidence
90% confidence
Finding
Unlike the other commands, newsletter delivery occurs automatically when not in dry-run mode, without requiring an explicit --send flag. That inconsistency can cause unintended outbound transmission of potentially sensitive team or project data to configured delivery channels.

Context-Inappropriate Capability

Medium
Confidence
93% confidence
Finding
The launcher automatically runs `pip3 install -r requirements.txt -q` before execution, which performs a network fetch and code-supply action without explicit user consent or visibility. For a reporting/analytics skill, silently modifying the host environment and pulling packages at runtime expands the attack surface through dependency compromise, typosquatting, or unintended package execution during install.

Vague Triggers

Medium
Confidence
81% confidence
Finding
The trigger list contains broad natural-language phrases such as "who worked on X," "which tickets are stalled," and "team performance," which can plausibly appear in ordinary conversation. In a skill that can run shell commands, test external connectivity, and potentially send reports, accidental invocation increases the chance of unintended data access or external actions.

Missing User Warnings

Medium
Confidence
84% confidence
Finding
The command generates a personnel activity report that explicitly identifies individual engineers as 'quiet' and lists named contributions without any access-control check, consent indicator, minimization, or user-facing sensitivity warning. In this skill context, the feature is intended for management reporting, which makes the data use legitimate in some environments, but it still increases privacy and workplace-surveillance risk if exposed to broad audiences or routed to Slack/email/Telegram without safeguards.

Missing User Warnings

Medium
Confidence
98% confidence
Finding
The wizard collects multiple sensitive credentials and writes them to a local .env file in plaintext without warning the user about storage, file permissions, or handling expectations. This creates a real risk of credential disclosure through local compromise, backups, accidental commits, or multi-user systems.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
This command generates and displays engineer-identifiable performance data such as quiet-engineer lists, per-author MR trends, cycle times, and contribution mappings without any built-in consent check, audience restriction, minimization, or privacy notice. In an engineering-manager intelligence skill, that data is expected functionality, but exposing individualized productivity metrics can still enable employee surveillance, inappropriate sharing, or policy/regulatory violations if the report is sent to broad channels like Slack, Telegram, or email.

Missing User Warnings

Medium
Confidence
99% confidence
Finding
The subprocess-based dependency installation runs silently, suppressing user awareness and making unexpected environment mutation harder to detect. Silent execution of package installation is unsafe operationally and increases the chance of unnoticed compromise through dependency confusion or malicious package updates.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The script performs a silent network-affecting action by installing Python dependencies with `-q 2>/dev/null`, suppressing useful disclosure and error details. Hidden package installation is risky because users may not realize the launcher is contacting package indexes and executing package install hooks on their machine.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
When `.env` exists, the launcher automatically injects its full contents into the Docker container via `--env-file` without warning or scoping. Since this skill integrates with GitHub/GitLab, Jira, Slack, Telegram, and email, the `.env` likely contains sensitive API tokens, making broad secret exposure to the container more dangerous than in a low-privilege utility.

External Transmission

Medium
Category
Data Exfiltration
Content
return _send_print(text, title)

    try:
        resp = requests.post(
            webhook_url,
            json={"text": f"*{title}*\n\n{text}"},
            timeout=15,
Confidence
84% confidence
Finding
This external transmission uses a fully configurable webhook URL, so the code can send internal report content to any network endpoint, not just Slack. In the context of an engineering intelligence skill, that creates a realistic data exfiltration path if configuration is compromised or mis-set.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests>=2.31.0
python-dotenv>=1.0.0
rich>=13.0.0
jinja2>=3.1.0
Confidence
96% confidence
Finding
The dependency is specified with a lower bound only, which allows future installs to resolve to any newer version, including versions with breaking changes or newly introduced security issues. In a skill that aggregates data from GitHub/GitLab, Jira, and messaging channels, supply-chain instability increases risk because compromised or vulnerable upstream packages could affect sensitive engineering and project data flows.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests>=2.31.0
python-dotenv>=1.0.0
rich>=13.0.0
jinja2>=3.1.0
markdown>=3.5.0
Confidence
94% confidence
Finding
Using an unpinned python-dotenv version makes builds non-reproducible and can silently introduce vulnerable or incompatible releases. While this package is less exposed than network-facing libraries, it often handles environment configuration, so unexpected behavior could influence secret loading or file operations.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests>=2.31.0
python-dotenv>=1.0.0
rich>=13.0.0
jinja2>=3.1.0
markdown>=3.5.0
Confidence
89% confidence
Finding
An unpinned rich dependency primarily creates reproducibility and supply-chain governance risk, even if no specific advisory is cited here. Future versions may introduce regressions or vulnerabilities that are pulled in automatically during deployment.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests>=2.31.0
python-dotenv>=1.0.0
rich>=13.0.0
jinja2>=3.1.0
markdown>=3.5.0
Confidence
97% confidence
Finding
An unpinned jinja2 dependency is particularly risky because templating engines are often involved in rendering untrusted content, and Jinja2 has a history of security issues. Allowing unconstrained upgrades increases the chance of pulling a vulnerable release into a system that may generate reports, newsletters, or chat messages from external issue-tracker content.

Unpinned Dependencies

Low
Category
Supply Chain
Content
python-dotenv>=1.0.0
rich>=13.0.0
jinja2>=3.1.0
markdown>=3.5.0
Confidence
95% confidence
Finding
The markdown package is unpinned, so deployments may drift to newer releases with security defects or behavior changes. Given this skill may render newsletters or summaries for Slack, Telegram, or email, malformed input processed through markdown could become a larger reliability or injection surface when combined with downstream renderers.

Static analysis

No suspicious patterns detected.