Back to skill

Security audit

UseMemos

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent UseMemos helper, but it encourages and permits sending a bearer token and private memo data over plaintext HTTP, including with long-lived tokens.

Install only if you are comfortable granting this skill access to your UseMemos account. Use HTTPS for USEMEMOS_URL, avoid non-expiring tokens, keep the .env file private, rotate/revoke the token if exposed, and be careful with delete/comment operations because they mutate remote memo data.

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

Error
Location
SKILL.md:23
Finding
Bearer Tokens and Private UseMemos Content Can Be Transmitted over Plaintext HTTP<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:23-29`; `README.md:31-38`; network requests in `scripts/create_memo.py:32-44`, `scripts/list_memos.py:30-41`, `scripts/search_memos.py:38-49`, `scripts/memo_comments.py:27-39`, `scripts/upload_attachment.py:40-52`, `scripts/upload_and_link_attachment.py:53-61,76-83,102-110`, and `tests/test_image_upload.py:80-112` **Vulnerability Type**: Plaintext transmission of bearer credentials and private content **Risk Level**: High The documented configuration explicitly permits and demonstrates unencrypted HTTP: ```text Create a `.env` file in the skill directory (`skills/usememos/.env`): ``` ```text USEMEMOS_URL=http://192.168.0.157:5230 USEMEMOS_TOKEN=your_access_token_here ``` The same documentation recommends a token without expiration: ```text Get your `USEMEMOS_TOKEN` from UseMemos instance, login and go to: Settings > My Account > Access Tokens, create one there, do not forget to assign expiration (i use Never to avoid troubles, but hey there are also arguments against that) ``` The scripts then send that bearer token and user data directly to the configured URL without validating its scheme. For example, `scripts/upload_attachment.py:40-52` contains: ```python req = urllib.request.Request( f"{base_url}/api/v1/attachments", data=payload, headers={ 'Authorization': f'Bearer {token}', 'Content-Type': 'application/json', 'Accept': 'application/json' }, method='POST' ) try: with urllib.request.urlopen(req) as resp: data = json.loads(resp.read().decode()) ``` Similarly, the common request logic in `scripts/memo_comments.py:27-39` is: ```python def api_request(base_url, token, path, method='GET', data=None): body = json.dumps(data).encode() if data else None req = urllib.request.Request( f"{base_url}{path}", data=body, headers={ 'Authorization': f'Bearer {token}', 'Content-Type': 'appli ...[truncated 3059 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Require HTTPS by default** - Parse `USEMEMOS_URL` with `urllib.parse.urlsplit`. - Accept only `https` for normal deployments. - Reject missing, malformed, or unsupported URL schemes before constructing requests. 2. **Restrict plaintext HTTP to explicit local exceptions** - If loopback development must remain supported, allow HTTP only for `localhost`, `127.0.0.1`, or `::1`. - For other HTTP destinations, require an explicit option such as `USEMEMOS_ALLOW_INSECURE_HTTP=true`. - Emit a prominent warning when this exception is enabled. 3. **Enforce a safe redirect policy** - Disable automatic redirects for authenticated API requests, or permit them only when the destination retains the original HTTPS scheme, host, and effective port. - Never forward the `Authorization` header across origins. - Reject HTTPS-to-HTTP downgrade redirects. 4. **Improve token guidance** - Remove the recommendation to select a `Never` expiration. - Recommend short-lived, revocable, least-privilege access tokens. - Document token rotation and immediate revocation after suspected exposure. 5. **Protect local token storage** - Advise users to set restrictive permissions, such as `chmod 600 .env`. - Ensure `.env` is excluded from version control and packaged releases. - Prefer a platform secret store or injected environment variable where available. 6. **Update examples** - Replace all non-loopback HTTP examples with `https://` URLs. - Clearly state that Base64 is only an API encoding and does not protect attachment confidentiality. ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (49)

Tainted flow: 'req' from os.environ.get (line 32, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
)

    try:
        with urllib.request.urlopen(req) as resp:
            data = json.loads(resp.read().decode())
            memos = data.get('memos', [])
            if not memos:
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Tainted flow: 'req' from os.environ.get (line 32, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
)

    try:
        with urllib.request.urlopen(req) as resp:
            data = json.loads(resp.read().decode())
            memos = data.get('memos', [])
            if not memos:
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Tainted flow: 'req' from os.environ.get (line 40, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
)

    try:
        with urllib.request.urlopen(req) as resp:
            data = json.loads(resp.read().decode())
            memos = data.get('memos', [])
            if not memos:
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Tainted flow: 'req' from os.environ.get (line 40, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
)

    try:
        with urllib.request.urlopen(req) as resp:
            data = json.loads(resp.read().decode())
            memos = data.get('memos', [])
            if not memos:
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Tainted flow: 'req' from os.environ.get (line 102, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
)

    try:
        with urllib.request.urlopen(req) as resp:
            attachment = json.loads(resp.read().decode())
    except urllib.error.HTTPError as e:
        print(f"Upload failed: {e.code} - {e.read().decode()}", file=sys.stderr)
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Tainted flow: 'req' from os.environ.get (line 102, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
)

    try:
        with urllib.request.urlopen(req) as resp:
            attachment = json.loads(resp.read().decode())
    except urllib.error.HTTPError as e:
        print(f"Upload failed: {e.code} - {e.read().decode()}", file=sys.stderr)
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Tainted flow: 'get_req' from os.environ.get (line 76, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
)

    try:
        with urllib.request.urlopen(get_req) as resp:
            memo_data = json.loads(resp.read().decode())
    except urllib.error.HTTPError as e:
        print(f"Failed to get memo: {e.code} - {e.read().decode()}", file=sys.stderr)
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Tainted flow: 'req' from os.environ.get (line 109, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
req = urllib.request.Request(
        f'{BASE_URL}{path}', data=body, headers=headers, method=method,
    )
    with urllib.request.urlopen(req) as resp:
        return json.loads(resp.read().decode())
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Tainted flow: 'req' from os.environ.get (line 109, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
req = urllib.request.Request(
        f'{BASE_URL}{path}', data=body, headers=headers, method=method,
    )
    with urllib.request.urlopen(req) as resp:
        return json.loads(resp.read().decode())
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Credential Access

High
Category
Privilege Escalation
Content
1. Copy the example environment file and fill in your values:

```bash
cp .env.example .env
```

2. Edit `.env` with your UseMemos instance URL and access token:
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
cp .env.example .env
```

2. Edit `.env` with your UseMemos instance URL and access token:

```
USEMEMOS_URL=http://localhost:5230
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
cp .env.example .env
```

2. Edit `.env` with your UseMemos instance URL and access token:

```
USEMEMOS_URL=http://localhost:5230
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The declared description omits comment management and especially comment deletion, which is a destructive capability. This mismatch can mislead users and reviewers about what actions the skill may take, creating a risk of unauthorized or unexpected data modification in the UseMemos instance.

Credential Access

High
Category
Privilege Escalation
Content
USEMEMOS_TOKEN=your_access_token_here
```

Get your ```USEMEMOS_TOKEN``` from UseMemos instance, login and go to: **Settings > My Account > Access Tokens**, create one there, do not forget to assign expiration (i use **Never** to avoid troubles, but hey there are also arguments against that)

**Note:** All scripts automatically load the `.env` file from the skill directory. No need to export variables manually.
Confidence
92% confidence
Finding
The skill workflow centers on obtaining and storing an access token, and the text explicitly suggests using a token that never expires. In the context of a network-enabled skill that performs authenticated actions against a self-hosted memo system, compromise of that token could allow persistent unauthorized access, data exfiltration, and destructive operations.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
**Delete Memo**
```
DELETE /api/v1/memos/{id}
```

### Comments
Confidence
80% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Tool Parameter Abuse

High
Category
Tool Misuse
Content
Use the standard delete memo endpoint with the comment's memo ID:
```
DELETE /api/v1/memos/{comment_id}
```

### Attachments
Confidence
80% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Tool Parameter Abuse

High
Category
Tool Misuse
Content
**Delete Attachment**
```
DELETE /api/v1/attachments/{id}
```

### Tags
Confidence
80% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Credential Access

High
Category
Privilege Escalation
Content
#!/usr/bin/env python3
"""Load .env file from the skill directory."""
import os
import sys
from pathlib import Path
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
#!/usr/bin/env python3
"""Load .env file from the skill directory."""
import os
import sys
from pathlib import Path
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
#!/usr/bin/env python3
"""Load .env file from the skill directory."""
import os
import sys
from pathlib import Path
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
#!/usr/bin/env python3
"""Load .env file from the skill directory."""
import os
import sys
from pathlib import Path
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
#!/usr/bin/env python3
"""Load .env file from the skill directory."""
import os
import sys
from pathlib import Path
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
#!/usr/bin/env python3
"""Load .env file from the skill directory."""
import os
import sys
from pathlib import Path
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
#!/usr/bin/env python3
"""Load .env file from the skill directory."""
import os
import sys
from pathlib import Path
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
#!/usr/bin/env python3
"""Load .env file from the skill directory."""
import os
import sys
from pathlib import Path
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Static analysis

No suspicious patterns detected.