Back to skill

Security audit

PMO

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches a PMO workflow, but it should be reviewed because it can read connected project tools, retain local project/risk records, and automatically send reports or alerts externally.

Install only if you are comfortable granting it access to project-management data and letting it retain local project/risk summaries. Prefer a fine-grained read-only GitHub token supplied by environment variable, disable or review any automatic channel sending, and narrow activation to explicit /pmo commands where possible.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • 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 (1)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/github_fetch.py:118
Finding

GitHub Access Token Exposed Through Command-Line Arguments

Content
View full analysis

Vulnerability Details

File Location: scripts/github_fetch.py, lines 118–123 and 128–130
Vulnerability Type: Command-line secret exposure
Risk Level: Medium

Vulnerable Code

python
parser.add_argument(
    "--token",
    dest="token_value",
    default=None,
    help="Direct token value (use sparingly — prefer --token-env)",
)
python
# Resolve token
if args.token_value:
    token = args.token_value
else:
    token = os.environ.get(args.token_env)

Technical Analysis

The script allows a GitHub access token to be supplied directly through the --token command-line argument. Command-line arguments are not an appropriate secret transport mechanism because plaintext arguments may be exposed through:

  • Shell command history
  • Process inspection utilities and process metadata
  • Endpoint monitoring or audit systems
  • CI/CD job logs and diagnostic output
  • Wrapper scripts or automation logs that record commands

The environment-variable mechanism already provided by the script is sufficient for its declared functionality. Therefore, accepting the token through the command line exceeds the minimum secret-handling interface necessary for the GitHub Issues integration.

The token is not hardcoded, printed by the script, or sent to an unrelated service. Elsewhere, it is used as a bearer token for the fixed HTTPS GitHub API origin. The exposure requires another local user, monitoring service, or logging system to obtain the command line or history.

Attack Path

  1. A user or automated process invokes the integration with a plaintext token, for example:

    bash
    python scripts/github_fetch.py \
      --owner my-org \
      --repo my-project \
      --token github_pat_example
    
  2. The complete command is retained in shell history, process metadata, a CI log, or an endpoint-monitoring record.

  3. An attacker or unauthorized operator with access to t ...[truncated 852 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove the --token argument and accept credentials only through an environment variable or secure credential provider:

    python
    token = os.environ.get(args.token_env)
    if not token:
        print(
            f"Error: required credential environment variable "
            f"{args.token_env!r} is not set.",
            file=sys.stderr,
        )
        sys.exit(1)
    
  2. In automation, inject the token through the platform's protected secret store rather than including it in a command, configuration file, or loggable parameter.

  3. Require a fine-grained GitHub token restricted to the necessary repositories and read-only Issues/metadata permissions.

  4. Document token rotation and immediate revocation procedures for credentials that may have been supplied through --token.

  5. Ensure errors, subprocess wrappers, and diagnostic systems never print or serialize credential values.

  6. Where available, prefer short-lived GitHub App installation tokens over long-lived personal access tokens.

  7. Update SKILL.md and command examples to state explicitly that plaintext command-line credentials are unsupported.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (9)

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · scripts/github_fetch.py (reported line 11)May include surrounding context.

python
python github_fetch.py --owner my-org --repo my-project [--token-env GH_TOKEN]

Environment:
    GH_TOKEN: GitHub personal access token (or via --token flag)
"""

import argparse

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill documents capabilities that require environment access and outbound network use, but the manifest declares no explicit tool scope or permission boundaries. In practice, this creates an over-privileged and under-specified integration surface where the runtime may grant broader access than reviewers or users expect, increasing the chance of unintended secret exposure or unauthorized external access.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The description says the skill does not store project data, but the implementation clearly persists project registry, risk records, event logs, and caches locally. That mismatch is security-relevant because it can mislead users and reviewers about what data is retained, which undermines informed consent, data handling reviews, and retention controls.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill is configured to auto-activate on broad terms like 'portfolio,' 'weekly report,' 'risk,' 'stale,' and 'blocked,' which are common in ordinary conversation and unrelated contexts. Over-broad triggering can cause unintended access to connected systems, unnecessary data aggregation, or surprising execution of PMO workflows without clear user intent.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The trigger rules include regex and substring matches that can fire on ambiguous phrases, including generic words like 'dependency' or 'blocked' and even project-ID-shaped text. In a skill with external integrations and automated actions, ambiguous routing increases the likelihood of unauthorized or unintended data access and action execution.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill describes automatic weekly report sending and notifications to external channels without a clear runtime warning, confirmation flow, or data-classification guardrail. Because project summaries and risk alerts may contain sensitive operational details, automatic outbound transmission can leak internal information to messaging platforms or unintended recipients.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The documented design permits subprocess execution to invoke a Python script, which is a much broader capability than simple API fetching and materially expands the attack surface. If any inputs, paths, environment, or script contents are influenced by untrusted data, this can lead to arbitrary code execution, secret leakage, or abuse of the host environment.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/github_fetch.py (reported line 47)May include surrounding context.

python
Fetch all issues for a repo (open + closed).
    Returns structured data for PMO analysis.
    """
    base_url = f"https://api.github.com/repos/{owner}/{repo}"

    # Fetch open issues
    open_url = f"{base_url}/issues?state=open&per_page=100"

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
73% confidence
Finding

The prohibition states the skill is read-only for external tools and only writes to local files, which conveys a constrained integration model. Later documentation shows handlers invoking scripts/github_fetch.py through subprocess.run, adding command execution behavior not reflected in that intent statement; while the script appears read-only, the documented mechanism contradicts the implied no-execution glue behavior.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.