Back to skill

Security audit

AppFlowy API

Security checks for vulnerabilities and agentic risk

Overview

This AppFlowy API skill is purpose-aligned but needs review because it can change live workspace data and handles passwords/tokens with under-disclosed security risks.

Install only if you understand it can modify real AppFlowy workspace content. Use a test workspace first, prefer HTTPS endpoints, avoid passing passwords directly on the command line, redact token output from logs/transcripts, and review every workspace/view/database ID before running write or cleanup commands.

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/appflowy_client.py:64
Finding

Credentials and Bearer Tokens May Be Transmitted Over Plaintext HTTP

Content
View full analysis
Dict[str, str]: headers = { "client-version": self.client_version, "client-timestamp": str(now_millis()), "device-id": self.device_id, } if token: headers["Authorization"] = f"Bearer {token}" return headers ``` ```python def login_password(self, email: str, password: str) -> Dict[str, Any]: base = self._require_gotrue_url() url = f"{base}/token" return self._request_json( "POST", url, params={"grant_type": "password"}, json_body={"email": email, "password": password}, token=None, ) ``` The distributed example configuration explicitly selects plaintext HTTP: ```json { "base_url": "http://10.60.0.189", "gotrue_url": "http://10.60.0.189/gotrue" } ``` ### Technical Analysis The client accepts arbitrary URL schemes without requiring TLS. It then sends account credentials in a JSON request body and bearer tokens in the `Authorization` header to those endpoints. The project documentation and example configuration encourage use of `http://`, making this m ...[truncated 1932 chars]
Remediation
View remediation
str: parsed = urlparse(url) if parsed.scheme != "https": if not allow_insecure_http: raise AppFlowyError( "HTTPS is required for endpoints carrying credentials or tokens." ) return url.rstrip("/") ``` ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/get_token.py:6
Finding

Passwords and Authentication Tokens Are Exposed Through Process Arguments and Standard Output

Content
View full analysis
int: parser = argparse.ArgumentParser(description="Fetch GoTrue access token.") parser.add_argument("--email", required=True) parser.add_argument("--password", required=True) parser.add_argument("--config", default=None, help="Path to config JSON (optional).") parser.add_argument("--env", default=None, help="Path to .env file (optional, opt-in).") parser.add_argument("--base-url", default=None) parser.add_argument("--gotrue-url", default=None) parser.add_argument("--client-version", default=None) parser.add_argument("--device-id", default=None) args = parser.parse_args() client = build_client(args) token = client.login_password(args.email, args.password) print_json(token) return 0 ``` ### Technical Analysis The utility requires the password as a command-line argument. Depending on the operating system and execution environment, command-line arguments may be exposed through: - Shell history. - Process inspection tools and process metadata. - CI/CD command logs. - Job schedulers and orchestration telemetry. - Agent tool-call transcripts or debugging output. The utility then prints the complete GoTrue authentication response. Such responses commonly contain an access token, refresh token, expiration data, and account metadata. Printing the complete object sends those secrets to terminal scrollback and any system collecting standard output. Although obtaining a token is declared functionality, exposing the password through the process command line and returning more authentication data than necessary violate secure secret-handling and least-disclosure principles. ### Attack Path 1. A user invokes the ...[truncated 1461 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • 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
Findings (61)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The description presents the skill as a general AppFlowy API authentication/calling aid, but the documented behavior includes destructive and state-changing operations such as in-place document modification, grid rebuilding, schema changes, and project-specific content generation. This mismatch is dangerous because operators may authorize or invoke the skill expecting low-risk API testing while it can actually alter remote data structures and content.

Content

No source excerpt is available for this finding.

Hidden Instructions

High
Category
Prompt Injection
Confidence
60% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · scripts/collab_delete_blocks.mjs (reported line 1)May include surrounding context.

js
import fs from "fs";
import * as Y from "yjs";

function readStdin() {

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/get_token.py (reported line 6)May include surrounding context.

python
def main() -> int:
    parser = argparse.ArgumentParser(description="Fetch GoTrue access token.")
    parser.add_argument("--email", required=True)
    parser.add_argument("--password", required=True)
    parser.add_argument("--config", default=None, help="Path to config JSON (optional).")

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/add_db_field.py (reported line 16)May include surrounding context.

python
parser.add_argument("--email", required=True)
    parser.add_argument("--password", required=True)
    parser.add_argument("--config", default=None, help="Path to config JSON (optional).")
    parser.add_argument("--env", default=None, help="Path to .env file (optional, opt-in).")
    parser.add_argument("--base-url", default=None)
    parser.add_argument("--gotrue-url", default=None)
    parser.add_argument("--client-version", default=None)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/append_block.py (reported line 16)May include surrounding context.

python
parser.add_argument("--email", required=True)
    parser.add_argument("--password", required=True)
    parser.add_argument("--config", default=None, help="Path to config JSON (optional).")
    parser.add_argument("--env", default=None, help="Path to .env file (optional, opt-in).")
    parser.add_argument("--base-url", default=None)
    parser.add_argument("--gotrue-url", default=None)
    parser.add_argument("--client-version", default=None)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/appflowy_client.py (reported line 36)May include surrounding context.

python
parser.add_argument("--email", required=True)
    parser.add_argument("--password", required=True)
    parser.add_argument("--config", default=None, help="Path to config JSON (optional).")
    parser.add_argument("--env", default=None, help="Path to .env file (optional, opt-in).")
    parser.add_argument("--base-url", default=None)
    parser.add_argument("--gotrue-url", default=None)
    parser.add_argument("--client-version", default=None)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/create_page_view.py (reported line 15)May include surrounding context.

python
parser.add_argument("--email", required=True)
    parser.add_argument("--password", required=True)
    parser.add_argument("--config", default=None, help="Path to config JSON (optional).")
    parser.add_argument("--env", default=None, help="Path to .env file (optional, opt-in).")
    parser.add_argument("--base-url", default=None)
    parser.add_argument("--gotrue-url", default=None)
    parser.add_argument("--client-version", default=None)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/create_user_management_doc.py (reported line 51)May include surrounding context.

python
parser.add_argument("--email", required=True)
    parser.add_argument("--password", required=True)
    parser.add_argument("--config", default=None, help="Path to config JSON (optional).")
    parser.add_argument("--env", default=None, help="Path to .env file (optional, opt-in).")
    parser.add_argument("--base-url", default=None)
    parser.add_argument("--gotrue-url", default=None)
    parser.add_argument("--client-version", default=None)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/doctor.py (reported line 46)May include surrounding context.

python
parser.add_argument("--email", required=True)
    parser.add_argument("--password", required=True)
    parser.add_argument("--config", default=None, help="Path to config JSON (optional).")
    parser.add_argument("--env", default=None, help="Path to .env file (optional, opt-in).")
    parser.add_argument("--base-url", default=None)
    parser.add_argument("--gotrue-url", default=None)
    parser.add_argument("--client-version", default=None)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/get_row_detail.py (reported line 15)May include surrounding context.

python
parser.add_argument("--email", required=True)
    parser.add_argument("--password", required=True)
    parser.add_argument("--config", default=None, help="Path to config JSON (optional).")
    parser.add_argument("--env", default=None, help="Path to .env file (optional, opt-in).")
    parser.add_argument("--base-url", default=None)
    parser.add_argument("--gotrue-url", default=None)
    parser.add_argument("--client-version", default=None)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/get_token.py (reported line 10)May include surrounding context.

python
parser.add_argument("--email", required=True)
    parser.add_argument("--password", required=True)
    parser.add_argument("--config", default=None, help="Path to config JSON (optional).")
    parser.add_argument("--env", default=None, help="Path to .env file (optional, opt-in).")
    parser.add_argument("--base-url", default=None)
    parser.add_argument("--gotrue-url", default=None)
    parser.add_argument("--client-version", default=None)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/list_databases.py (reported line 13)May include surrounding context.

python
parser.add_argument("--email", required=True)
    parser.add_argument("--password", required=True)
    parser.add_argument("--config", default=None, help="Path to config JSON (optional).")
    parser.add_argument("--env", default=None, help="Path to .env file (optional, opt-in).")
    parser.add_argument("--base-url", default=None)
    parser.add_argument("--gotrue-url", default=None)
    parser.add_argument("--client-version", default=None)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/list_row_ids.py (reported line 14)May include surrounding context.

python
parser.add_argument("--email", required=True)
    parser.add_argument("--password", required=True)
    parser.add_argument("--config", default=None, help="Path to config JSON (optional).")
    parser.add_argument("--env", default=None, help="Path to .env file (optional, opt-in).")
    parser.add_argument("--base-url", default=None)
    parser.add_argument("--gotrue-url", default=None)
    parser.add_argument("--client-version", default=None)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/list_workspaces.py (reported line 12)May include surrounding context.

python
parser.add_argument("--email", required=True)
    parser.add_argument("--password", required=True)
    parser.add_argument("--config", default=None, help="Path to config JSON (optional).")
    parser.add_argument("--env", default=None, help="Path to .env file (optional, opt-in).")
    parser.add_argument("--base-url", default=None)
    parser.add_argument("--gotrue-url", default=None)
    parser.add_argument("--client-version", default=None)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/search.py (reported line 14)May include surrounding context.

python
parser.add_argument("--email", required=True)
    parser.add_argument("--password", required=True)
    parser.add_argument("--config", default=None, help="Path to config JSON (optional).")
    parser.add_argument("--env", default=None, help="Path to .env file (optional, opt-in).")
    parser.add_argument("--base-url", default=None)
    parser.add_argument("--gotrue-url", default=None)
    parser.add_argument("--client-version", default=None)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/upsert_row.py (reported line 16)May include surrounding context.

python
parser.add_argument("--email", required=True)
    parser.add_argument("--password", required=True)
    parser.add_argument("--config", default=None, help="Path to config JSON (optional).")
    parser.add_argument("--env", default=None, help="Path to .env file (optional, opt-in).")
    parser.add_argument("--base-url", default=None)
    parser.add_argument("--gotrue-url", default=None)
    parser.add_argument("--client-version", default=None)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The README explicitly demonstrates authenticated operations and an 'in-place modification' workflow against remote AppFlowy resources without a clear warning that the command can change live workspace data. In an automation/debugging skill, users may copy-paste examples directly, so the absence of a safety notice increases the risk of accidental destructive or unintended modifications to production content.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill advertises and documents capabilities that can read configuration, use credentials, invoke shell commands, and make network requests, but it does not declare any explicit tool or permission scope. That omission weakens least-privilege controls and makes it easier for an agent or user to invoke higher-risk operations without clear boundaries or review.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The skill instructs users to submit email/password credentials and then use bearer access tokens, but it does not warn about protecting those secrets from shell history, logs, screenshots, shared terminals, or insecure transport. Because these tokens and credentials grant access to AppFlowy resources, accidental disclosure could lead to unauthorized access and subsequent data theft or modification.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
97% confidence
Finding

The example sends user credentials to a plain HTTP endpoint at a private IP address, meaning passwords and returned tokens could be intercepted by anyone with network visibility on the local or routed path. Even in internal environments, using unencrypted transport for authentication materially increases the risk of credential theft and account compromise.

Content

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

bash
# 获取 token
curl -sS -X POST "http://10.60.0.189/gotrue/token?grant_type=password" \
  -H "Content-Type: application/json" \
  -d '{"email":"<email>","password":"<password>"}'

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The documented update scripts perform in-place document and grid modifications, including cleanup of default rows, but there is no explicit warning that these actions change or may delete remote user data. In practice, this can cause accidental data loss or unintended edits if a user runs the commands against the wrong workspace, view, or production environment.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The manifest’s user-facing description and default prompt are written only in Chinese, which imposes a specific language/locale expectation without indicating user choice. Under the language/locale policy rule, this is a natural-language policy concern because no opt-in or alternative language is offered.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The README provides write-oriented examples that apply templates and update documents in a remote AppFlowy workspace without warning that they modify live remote content. Users may run these commands against production workspaces or the wrong view/workspace IDs, causing unintended data changes or overwrites; in this API-client context, that makes the omission more dangerous because the examples are directly operational.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The example commands instruct users to pass email and password directly on the command line, which can expose credentials through shell history, process listings, audit logs, CI logs, or terminal recordings. Because this skill is specifically for authenticating to a cloud API, the credentials are real account secrets and their exposure can lead to unauthorized access to workspaces and data.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This markdown file documents a password-grant login flow and required authorization headers, which involves sensitive credentials and access tokens. Under the markdown-specific warning criterion, the file should disclose privacy/security implications of exposing or storing passwords and bearer tokens, but it currently presents the flow without any cautionary note.

Content

No source excerpt is available for this finding.