Back to skill

Security audit

System Monitor

Security checks for vulnerabilities and agentic risk

Overview

This system-monitoring skill is mostly purpose-aligned, but it can expose process command lines even when the user asks for narrower metrics.

Review before installing on shared, production, or privileged systems. The skill does not appear malicious, but its JSON/status output can include process command lines that may contain tokens, paths, or operational details; run it with the least-privileged account and avoid forwarding its JSON to broad logs or dashboards unless process output is removed or redacted.

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/monitor.py:135
Finding

Unconditional Process Enumeration and Disclosure in JSON Output

Content
View full analysis

Vulnerability Details

File Location: scripts/monitor.py:135-168 and scripts/monitor.py:238-241
Vulnerability Type: Sensitive process information exposure caused by excessive data collection
Risk Level: Medium

Vulnerable Code

python
def get_top_processes(limit=5):
    """Get top processes by CPU usage."""
    try:
        import subprocess
        result = subprocess.run(
            ['ps', 'aux', '--sort=-%cpu'],
            capture_output=True, text=True
        )
        lines = result.stdout.strip().split('\n')[1:limit+1]
        
        processes = []
        for line in lines:
            fields = line.split()
            if len(fields) >= 11:
                processes.append({
                    'pid': fields[1],
                    'user': fields[0],
                    'cpu': float(fields[2]),
                    'mem': float(fields[3]),
                    'command': ' '.join(fields[10:])
                })
        return processes
    except:
        return []


def get_status():
    """Get complete system status."""
    return {
        'cpu': get_cpu_usage(),
        'memory': get_memory_usage(),
        'disk': get_disk_usage(),
        'network': get_network_stats(),
        'uptime': get_uptime(),
        'load': get_load_average(),
        'processes': get_top_processes(5)
    }
python
status = get_status()

if args.json:
    print(json.dumps(status, indent=2))
    if not args.watch:
        break

Technical Analysis

Every invocation calls get_status(), which unconditionally invokes get_top_processes(5). That function executes ps aux and collects process owners, process identifiers, CPU and memory utilization, and full command-line arguments.

Metric-selection options such as --cpu, --memory, --disk, and --network do not limit the information collected. Furthermore, JSON mode always serializes the processes field, even when the caller did not request --processes.

Process command l ...[truncated 1895 chars]

Remediation
View remediation

Remediation Suggestions

  1. Collect process information only when explicitly requested through --processes.
  2. Build the result according to selected metrics rather than always calling get_status().
  3. Omit the processes property entirely when process reporting is not requested.
  4. Avoid returning full command-line arguments by default. Prefer executable names or redact arguments that resemble secrets.
  5. Ensure JSON and human-readable modes enforce the same metric-selection policy.
  6. Document that process inspection can expose sensitive operational information.
  7. Run the monitor with the least-privileged account capable of reading the required metrics.

A safer implementation pattern is:

python
status = {}

if args.status or args.cpu:
    status['cpu'] = get_cpu_usage()
if args.status or args.memory:
    status['memory'] = get_memory_usage()
if args.status or args.disk:
    status['disk'] = get_disk_usage()
if args.status or args.network:
    status['network'] = get_network_stats()
if args.status:
    status['uptime'] = get_uptime()
    status['load'] = get_load_average()
if args.processes:
    status['processes'] = get_top_processes(5)

If aggregate --status output is intended to include process information, that behavior should be explicitly documented, while narrow metric options must not collect or emit it.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (7)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding

The skill advertises shell and file-read capable usage via commands in the documentation, but it does not declare any explicit tool scope such as allowed-tools or permissions. That creates an authorization ambiguity where an agent may invoke broader local capabilities than intended, increasing the risk of unintended command execution or filesystem access when the skill is selected.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
79% confidence
Finding

The manifest describes monitoring system metrics, which is generally satisfied by reading system interfaces or APIs. Invoking subprocesses to execute external binaries adds execution capability that is broader and more sensitive than necessary for the stated purpose, especially when used to inspect processes and filesystem state.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/monitor.py (reported line 63)May include surrounding context.

python
"""Get disk usage for mounted partitions."""
    try:
        import subprocess
        result = subprocess.run(['df', '-B1', '-T'], capture_output=True, text=True)
        lines = result.stdout.strip().split('\n')[1:]  # Skip header
        
        disks = []

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill goes beyond aggregate system metrics and enumerates processes with usernames and full command lines, which can expose secrets, internal service names, file paths, and activities of other users on the host. In agent contexts, this broadens data access in a way users may not expect from a simple monitoring tool and can leak sensitive operational information.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/monitor.py (reported line 140)May include surrounding context.

python
"""Get top processes by CPU usage."""
    try:
        import subprocess
        result = subprocess.run(
            ['ps', 'aux', '--sort=-%cpu'],
            capture_output=True, text=True
        )

Vague Triggers

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

The manifest description says to use the skill whenever a user needs to track server performance, set up alerts, monitor uptime, check process status, or create health reports, but it does not define clear trigger boundaries or exclusions. This broad natural-language scope could overlap with many general ops or troubleshooting requests and may cause unintended invocation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

Listing other users' processes and command lines without warning can disclose credentials passed as arguments, administrative operations, internal endpoints, or tenant activity. In a monitoring skill, this is especially risky because users may assume only coarse system-health metrics are being collected, not cross-user process surveillance.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.