Back to skill

Security audit

flomo-add

Security checks for vulnerabilities and agentic risk

Overview

This skill does what it says: it sends a user-provided memo to a configured flomo webhook, with some credential-handling and URL-scoping cautions.

Install only if you intend to send note content to flomo. Treat the webhook URL like a password, avoid sharing dry-run output, and verify .flomo.config points to the correct HTTPS flomo webhook before sending sensitive notes.

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 (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/flomo-add.py:56
Finding
Unrestricted Outbound Webhook Destination## Vulnerability Details **File Location**: `scripts/flomo-add.py`, lines 56-72 **Vulnerability Type**: Unvalidated outbound request destination **Risk Level**: Medium **Relevant Code**: ```python url = (args.url or config.get("url", "")).strip() ``` ```python response = requests.post(url, json=payload, headers=headers, timeout=15) ``` ### Technical Analysis The script accepts a destination from either the `--url` argument or the `url` configuration entry and passes it directly to `requests.post`. It only verifies that the value is nonempty. It does not require HTTPS, restrict the hostname to an authorized flomo domain, reject local or private-network addresses, or constrain redirects. Consequently, anyone able to influence the command arguments or `.flomo.config` can direct memo content to an arbitrary server. Because the `requests` library follows redirects by default, an initially acceptable URL could also redirect the request to another destination unless redirects are disabled or each redirect target is validated. ### Attack Path 1. An attacker modifies `.flomo.config`, supplies a prepared invocation, or persuades the user to use `--url` with an attacker-controlled address. 2. The user invokes the Skill with sensitive memo content. 3. The script accepts the address because it is nonempty. 4. The script sends the memo in a JSON POST request to the attacker-controlled server. 5. Alternatively, the supplied destination can reference a reachable internal service, resulting in a limited server-side request forgery primitive. ### Impact Assessment An attacker can receive the complete memo content submitted during the affected invocation. A plaintext HTTP destination can also expose that content to network interception. The script may issue POST requests to internal, loopback, private, or link-local endpoints accessible from the host. This does not directly grant command execution or elevated privileges, but i ...[truncated 220 chars]
Remediation
## Remediation Suggestions - Parse the destination with a standard URL parser and reject malformed URLs. - Require the `https` scheme. - Restrict the hostname to the exact authorized flomo webhook hostname or a narrowly defined allowlist. - Reject embedded credentials, unexpected ports, fragments, and ambiguous hostname encodings. - Resolve the hostname and reject loopback, private, link-local, multicast, reserved, and unspecified IP addresses where appropriate. - Disable redirects with `allow_redirects=False`, or validate the scheme, hostname, port, and resolved address of every redirect target before following it. - Consider removing `--url` if runtime destination overrides are unnecessary. - Add tests covering HTTP URLs, attacker-controlled hosts, loopback addresses, private addresses, IPv6 variants, and redirect-based bypasses.

T09 · Insecure Skill Coding Practices

Note
Location
scripts/flomo-add.py:66
Finding
Webhook Credential Disclosed by Dry-Run Output## Vulnerability Details **File Location**: `scripts/flomo-add.py`, line 66 **Vulnerability Type**: Sensitive credential exposure through application output **Risk Level**: Low **Relevant Code**: ```python print(f"POST {url}") ``` ### Technical Analysis A flomo webhook URL contains a secret path that acts as a write-capability credential. In dry-run mode, the script prints the entire URL without redaction. Although no request is sent in this mode, the credential can be retained in terminal recordings, continuous-integration logs, support bundles, chat transcripts, or other captured output. Possession of the URL may be sufficient to submit content to the associated flomo account without separate authentication. ### Attack Path 1. A user configures a valid secret flomo webhook URL. 2. The user invokes the script with `--dry-run`. 3. The complete webhook URL is printed to standard output. 4. The output is stored, captured, or shared in a location accessible to another party. 5. That party extracts the URL and sends unauthorized POST requests to the webhook. ### Impact Assessment Exposure can permit unauthorized memo submissions through the affected webhook. It does not inherently provide account administration privileges or access to existing memo contents. The scope is limited to the capabilities granted by the leaked webhook and remains active until the webhook is revoked or rotated.
Remediation
## Remediation Suggestions - Never print the complete webhook URL, including in dry-run and error output. - Display only the validated scheme and hostname, or replace the secret path with a fixed redaction marker. - Remove query parameters and user-information components from diagnostic output. - Provide an explicit opt-in diagnostic mechanism if full output is ever required, accompanied by a prominent warning and disabled by default. - Review logs for previous exposure and rotate any webhook URL that may have been disclosed. - Add automated tests confirming that the webhook token and full URL never appear in standard output or standard error.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (6)

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill performs file reads and outbound network actions but does not declare any explicit tool scope or permissions boundary in the manifest. This can cause an agent or user to invoke the skill without clear visibility into its capability to read local configuration and transmit data externally, increasing the chance of unintended data exposure.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The description says the skill adds a memo via a webhook, but it does not clearly warn that the provided memo content will be sent to an external third-party service. Users may provide sensitive notes, secrets, or internal project data without understanding that the content leaves the local environment.

External Transmission

Medium
Category
Data Exfiltration
Content
### 2) 直接使用 curl(macOS / Linux)

```bash
curl -X POST "https://flomoapp.com/iwh/M000000/abcdefg0000000000000000000000000/" \
  -H "Content-Type: application/json" \
  --data-binary '{"content":"Hello, #flomo https://flomoapp.com"}'
```
Confidence
90% confidence
Finding
This skill explicitly instructs users to POST arbitrary memo content to an external flomo webhook, which is a real external transmission path. In context this is the intended function, but it still creates a data exfiltration risk if users pass sensitive content or if a malicious/incorrect webhook URL is configured in .flomo.config.

Skill Enumeration

Medium
Category
Agent Snooping
Content
config = parse_kv_config(config_path)
    except FileNotFoundError as exc:
        print(str(exc), file=sys.stderr)
        print("请先在当前目录创建 .flomo.config 并配置 url=<webhook_url>,格式见 skills/flomo-add/SKILL.md", file=sys.stderr)
        return 2

    url = (args.url or config.get("url", "")).strip()
Confidence
80% confidence
Finding
Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

External Transmission

Medium
Category
Data Exfiltration
Content
return 0

    try:
        response = requests.post(url, json=payload, headers=headers, timeout=15)
        response.raise_for_status()
    except requests.RequestException as exc:
        print(f"请求失败: {exc}", file=sys.stderr)
Confidence
94% confidence
Finding
The script sends user-supplied memo content and a configurable webhook URL to an external destination without validating the destination or constraining where data may be transmitted. In this skill's context, external transmission is expected, but allowing arbitrary URL override via --url and reading the endpoint from a local config increases the risk of accidental or malicious exfiltration of sensitive content to an attacker-controlled server.

Natural-Language Policy Violations

Low
Confidence
97% confidence
Finding
The script's user-facing strings in exceptions, argument descriptions, and error messages are written in Chinese only. This imposes a specific language on all users without any opt-in or alternative locale handling, which matches the natural-language locale policy violation criteria.

Static analysis

No suspicious patterns detected.