Back to skill

Security audit

Flomo Via App

Security checks for vulnerabilities and agentic risk

Overview

This skill is meant to send notes to flomo, but its instructions and scripts have important inconsistencies and unsafe configuration handling that users should review before installing.

Install only if you are comfortable running local shell scripts and sending note content through a flomo webhook. Treat the webhook token as a secret, prefer a local permission-restricted config over shell-profile persistence, and inspect any token or URL before saving it. The package should be fixed to align the URL Scheme documentation with actual behavior and to validate or safely serialize configuration values.

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

Error
Location
scripts/configure.sh:30
Finding
Arbitrary Command Execution Through Unsafe Configuration Serialization## Vulnerability Details **File Location**: `scripts/configure.sh:30-100`; configuration is subsequently executed by `scripts/flomo_send.sh:14-19` **Vulnerability Type**: Shell command injection through sourced configuration **Risk Level**: High ### Vulnerable Code `scripts/configure.sh` accepts a webhook value without validating or escaping shell metacharacters: ```bash read -rp "Webhook token (or full URL): " WEBHOOK_INPUT if [ -z "$WEBHOOK_INPUT" ]; then echo "⚠️ No webhook provided. You can configure it later by running this script again." exit 0 fi # Detect if user pasted full URL or just token if echo "$WEBHOOK_INPUT" | grep -q "^https://flomoapp.com/iwh/"; then # Full URL provided WEBHOOK_URL="$WEBHOOK_INPUT" WEBHOOK_TOKEN=$(echo "$WEBHOOK_URL" | sed 's|https://flomoapp.com/iwh/||') else # Just token provided WEBHOOK_TOKEN="$WEBHOOK_INPUT" WEBHOOK_URL="https://flomoapp.com/iwh/$WEBHOOK_TOKEN" fi ``` The unescaped value is written as executable shell syntax to either a shell startup file: ```bash echo "" >> "$SHELL_CONFIG" echo "# Flomo Skill Configuration" >> "$SHELL_CONFIG" echo "export FLOMO_WEBHOOK_TOKEN=$WEBHOOK_TOKEN" >> "$SHELL_CONFIG" ``` Or to the local `.env` file: ```bash ENV_FILE="$(dirname "$0")/../.env" echo "# Flomo Skill Configuration" > "$ENV_FILE" echo "FLOMO_WEBHOOK_TOKEN=$WEBHOOK_TOKEN" >> "$ENV_FILE" echo "# FLOMO_WEBHOOK_URL=$WEBHOOK_URL" >> "$ENV_FILE" chmod 600 "$ENV_FILE" ``` `scripts/flomo_send.sh` later executes the generated `.env` file as shell code: ```bash ENV_FILE="$(dirname "$0")/../.env" if [ -f "$ENV_FILE" ]; then set -o allexport # shellcheck disable=SC1090 source "$ENV_FILE" set +o allexport fi ``` ### Technical Analysis The webhook token crosses a trust boundary from interactive user input into a shell program. It is serialized by concatenating it directly into an ...[truncated 2187 chars]
Remediation
## Remediation Suggestions 1. Validate token-only input against the exact character set and length allowed by flomo. Reject whitespace, control characters, shell metacharacters, and unexpected URL syntax. 2. Prefer accepting only a token and constructing the fixed webhook URL internally. Do not accept arbitrary shell expressions or unrestricted URLs. 3. Do not load data files with `source`. Store configuration in a non-executable format, such as JSON, and parse the required field with a data parser. 4. If shell-compatible output is unavoidable, serialize values safely with `printf '%q'` rather than string concatenation: ```bash { printf '%s\n' '# Flomo Skill Configuration' printf 'FLOMO_WEBHOOK_TOKEN=%q\n' "$WEBHOOK_TOKEN" } > "$ENV_FILE" chmod 600 "$ENV_FILE" ``` 5. Avoid writing credentials to shell startup files. Use the permission-restricted, non-executable application configuration file instead. 6. Write configuration atomically using a securely created temporary file, set restrictive permissions before adding the secret, and then rename it into place. 7. Add regression tests using values containing semicolons, command substitutions, quotes, backticks, spaces, and redirection operators. All malformed values should be rejected without executing any command.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/flomo_send.sh:69
Finding
Unrestricted Webhook URL Allows Note Exfiltration and Arbitrary HTTP POST Requests## Vulnerability Details **File Location**: `scripts/flomo_send.sh:69-88` **Vulnerability Type**: Unvalidated outbound request destination **Risk Level**: Medium ### Vulnerable Code ```bash send_webhook() { if [ -n "$FLOMO_WEBHOOK_URL" ]; then WEBHOOK_URL="$FLOMO_WEBHOOK_URL" elif [ -n "$FLOMO_WEBHOOK_TOKEN" ]; then WEBHOOK_URL="https://flomoapp.com/iwh/$FLOMO_WEBHOOK_TOKEN" else return 2 fi # Build JSON payload safely (handles quotes/newlines in content). if command -v python3 >/dev/null 2>&1; then PAYLOAD=$(printf '%s' "$FULL_CONTENT" | python3 -c 'import sys,json;print(json.dumps({"content": sys.stdin.read()}))') else # Fallback: escape simple cases (less safe for arbitrary input) ESCAPED=$(printf '%s' "$FULL_CONTENT" | sed -e 's/\\/\\\\/g' -e 's/"/\\\"/g' -e ':a;N;$!ba;s/\n/\\n/g') PAYLOAD="{\"content\": \"$ESCAPED\"}" fi RESP=$(curl -sS -w "\n%{http_code}" -X POST "$WEBHOOK_URL" -H "Content-Type: application/json" -d "$PAYLOAD" || true) ``` ### Technical Analysis When `FLOMO_WEBHOOK_URL` is defined, the script passes its value directly to `curl` without verifying the URL scheme, hostname, port, or path. Although project documentation presents `https://flomoapp.com/iwh/...` as the expected format, executable code does not enforce that restriction. Consequently, anyone able to influence the process environment or local configuration can redirect the complete note payload to an attacker-controlled server. The same behavior may also be used to issue a JSON HTTP POST from the victim's network context to an internal or local HTTP service. Quoting `"$WEBHOOK_URL"` prevents shell argument injection, but it does not make the network destination trustworthy. ### Attack Path 1. An attacker causes `FLOMO_WEBHOOK_URL` to be set to an attacker-controlled URL, or modifies the Skill's local configuration to define s ...[truncated 1063 chars]
Remediation
## Remediation Suggestions 1. Prefer removing `FLOMO_WEBHOOK_URL` support and accept only a strictly validated webhook token. 2. Construct the destination internally from a constant origin: ```bash WEBHOOK_URL="https://flomoapp.com/iwh/$FLOMO_WEBHOOK_TOKEN" ``` 3. Validate the token against flomo's documented character set and length before constructing the URL. 4. If full URL support is required, parse the URL with a proper URL parser and require: - The `https` scheme. - The exact `flomoapp.com` hostname. - The expected port or no explicit port. - A path beginning with `/iwh/`. - No user-information component. - No control characters or malformed encoding. 5. Configure `curl` to fail explicitly on HTTP errors and apply conservative connection and request timeouts. 6. Reject non-Flomo destinations before handling or transmitting note content, and return an actionable error without including the secret webhook value. 7. Add tests confirming that alternate domains, subdomain lookalikes, HTTP URLs, localhost addresses, private-network addresses, user-information tricks, and alternate ports are rejected.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • 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 (34)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The README claims URL-scheme delivery, automatic app detection, and webhook fallback behavior that the static analysis indicates are not actually implemented. This mismatch can mislead users about where their note content goes and under what conditions network transmission occurs, which is a security-relevant deception even if not overtly malicious.

Ae1

High
Category
analysis-evasion
Content
scripts/flomo_send.sh "Your note content" "#tag1 #tag2"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
scripts/flomo_send.sh "Your note content" "#tag1 #tag2"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
scripts/flomo_send.sh "Your note content" "#tag1 #tag2"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
scripts/flomo_send.sh "Your note content" "#tag1 #tag2"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
scripts/flomo_send.sh "Your note content" "#tag1 #tag2"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
scripts/flomo_send.sh "Your note content" "#tag1 #tag2"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
scripts/flomo_send.sh "Your note content" "#tag1 #tag2"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
scripts/flomo_send.sh "Your note content" "#tag1 #tag2"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
scripts/flomo_send.sh "Your note content" "#tag1 #tag2"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
scripts/flomo_send.sh "Your note content" "#tag1 #tag2"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
scripts/flomo_send.sh "Your note content" "#tag1 #tag2"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
scripts/flomo_send.sh "Your note content" "#tag1 #tag2"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
scripts/flomo_send.sh "Your note content" "#tag1 #tag2"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
scripts/flomo_send.sh "Your note content" "#tag1 #tag2"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Credential Access

High
Category
Privilege Escalation
Content
fi
                ;;
            *)
                # Save to .env file (default)
                ENV_FILE="$(dirname "$0")/../.env"
                echo "# Flomo Skill Configuration" > "$ENV_FILE"
                echo "FLOMO_WEBHOOK_TOKEN=$WEBHOOK_TOKEN" >> "$ENV_FILE"
Confidence
88% confidence
Finding
This script writes the flomo webhook token to a plaintext `.env` file in the skill directory. Although intended for convenience, storing long-lived credentials in a local file can expose them to other local processes, accidental inclusion in backups, sync tools, or source control if the directory is mishandled.

Credential Access

High
Category
Privilege Escalation
Content
;;
            *)
                # Save to .env file (default)
                ENV_FILE="$(dirname "$0")/../.env"
                echo "# Flomo Skill Configuration" > "$ENV_FILE"
                echo "FLOMO_WEBHOOK_TOKEN=$WEBHOOK_TOKEN" >> "$ENV_FILE"
                echo "# FLOMO_WEBHOOK_URL=$WEBHOOK_URL" >> "$ENV_FILE"
Confidence
95% confidence
Finding
Writing `FLOMO_WEBHOOK_TOKEN` directly into a plaintext `.env` file persists a usable authentication secret on disk. If that file is read by unauthorized local users, malware, or accidentally committed/shared, an attacker could send notes to the user's flomo inbox via the webhook.

Credential Access

High
Category
Privilege Escalation
Content
set -e

# Load local .env if present (export variables so they're available to curl/python)
ENV_FILE="$(dirname "$0")/../.env"
if [ -f "$ENV_FILE" ]; then
    set -o allexport
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
set -e

# Load local .env if present (export variables so they're available to curl/python)
ENV_FILE="$(dirname "$0")/../.env"
if [ -f "$ENV_FILE" ]; then
    set -o allexport
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
set -e

# Load local .env if present (export variables so they're available to curl/python)
ENV_FILE="$(dirname "$0")/../.env"
if [ -f "$ENV_FILE" ]; then
    set -o allexport
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
set -e

# Load local .env if present (export variables so they're available to curl/python)
ENV_FILE="$(dirname "$0")/../.env"
if [ -f "$ENV_FILE" ]; then
    set -o allexport
    # shellcheck disable=SC1090
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Intent-Code Divergence

Medium
Confidence
98% confidence
Finding
The manifest says the skill sends notes via URL Scheme with automatic webhook fallback and supports quick capture workflows on macOS. In contrast, the README explicitly states that URL Scheme mode has been cancelled/removed and that the skill now uniformly uses the Webhook API, which is a direct contradiction in documented intent.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The README instructs users to store a sensitive webhook token in shell profiles or a local .env file without any warning about file permissions, accidental source control commits, shell history exposure, or broader environment leakage. In this skill's context, the token grants the ability to submit content into the user's flomo inbox, so disclosure could enable unauthorized note injection or abuse of the webhook endpoint.

Intent-Code Divergence

Medium
Confidence
97% confidence
Finding
The manifest presents URL Scheme delivery with webhook fallback as a core feature. This README section explicitly says direct URL Scheme invocation has been removed and users should use only the Webhook API, which is an active contradiction rather than a mere omission.

Lp3

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding
The skill documentation directs users to run shell scripts (`./scripts/configure.sh`, `./scripts/flomo_send.sh`) but does not declare any corresponding tool scope or permissions. This weakens the trust boundary for users and reviewers because shell execution capability is implied but not transparently declared, increasing the chance that users execute local code without adequate scrutiny.

Static analysis

No suspicious patterns detected.