Back to skill

Security audit

Web Star Studio's Flow CRM

Security checks for vulnerabilities and agentic risk

Overview

The skill is a real FlowDeck API helper, but it exposes broader and riskier actions than its CRM description clearly tells users.

Review this before installing if your FlowDeck API key can modify or delete real CRM or project data. Use a least-privilege key, keep FLOWDECK_BASE_URL pinned to the legitimate FlowDeck endpoint, and require explicit user confirmation before update or delete commands.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/flow_api.py:66
Finding

Bearer Credentials Can Be Forwarded to an Untrusted Configurable Endpoint

Content
View full analysis

Vulnerability Details

File Location: scripts/flow_api.py, lines 66–69 and 132–141
Vulnerability Type: Unrestricted transmission of credentials and sensitive data
Risk Level: High

Vulnerable Code

python
def get_base_url(provided: str | None) -> str:
    if provided:
        return provided.rstrip("/")
    val = os.environ.get("FLOWDECK_BASE_URL", "https://mycivgjuujlnyoycuwrz.supabase.co/functions/v1/api-gateway")
    return val.rstrip("/")
python
def make_request(method: str, url: str, api_key: str,
                 query_params: dict | None = None,
                 body: dict | None = None):
    headers = {
        "Authorization": f"Bearer {api_key}",
        "Content-Type": "application/json",
    }
    response = httpx.request(
        method,
        url,
        headers=headers,
        params=query_params,
        json=body,
        timeout=30,
    )
    return response

Technical Analysis

The API base URL is read directly from the FLOWDECK_BASE_URL environment variable without validation. The implementation does not enforce HTTPS, verify that the destination belongs to FlowDeck or the expected Supabase deployment, reject embedded user information, or restrict nonstandard ports.

Every request subsequently sends the FlowDeck API key in the Authorization header. Create and update requests may also include sensitive CRM information in the JSON body, such as contact details, addresses, financial information, and tax identifiers.

Consequently, any party capable of influencing the runtime environment can redirect authenticated requests to an endpoint under its control. This turns the configurable base URL into a credential- and data-forwarding mechanism.

Attack Path

  1. An attacker, compromised launcher, or unsafe execution environment sets FLOWDECK_BASE_URL to an attacker-controlled HTTP or HTTPS endpoint.
  2. The user or agent invokes ...[truncated 993 chars]
Remediation
View remediation

Remediation Suggestions

  • Permit only HTTPS endpoints in production.
  • Parse the configured URL using a standard URL parser and reject malformed URLs, embedded credentials, fragments, unexpected ports, and non-HTTPS schemes.
  • Maintain an explicit allowlist of approved FlowDeck or Supabase hostnames rather than accepting arbitrary destinations.
  • If development endpoints are required, enable them only through an explicit development mode that does not use production credentials.
  • Do not attach the Authorization header until the destination has passed validation.
  • Consider using separate credentials with minimal scopes for CRM and project-management operations.
  • Add automated tests covering malicious hosts, HTTP URLs, user-information components, redirects, and nonstandard ports.
  • Disable or strictly validate cross-origin redirects so credentials cannot be forwarded to a different host.

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/flow_api.py:39
Finding

Executable API Scope Exceeds the Skill’s Declared CRM Scope

Content
View full analysis

Vulnerability Details

File Location: scripts/flow_api.py, lines 39–43 and 148–200; SKILL.md, lines 3 and 71–79
Vulnerability Type: Excessive and insufficiently disclosed API capabilities
Risk Level: High

Vulnerable Code

python
SUPPORTED_RESOURCES = {
    "clients": {"base": "/clients", "path_param": False},
    "contacts": {"base": "/contacts/{id}", "path_param": True, "parent_base": "/projects/{projectId}/contacts"},
    "deals": {"base": "/deals", "path_param": False},
    "proposals": {"base": "/proposals", "path_param": False},
    "receivables": {"base": "/receivables", "path_param": False},
    "expenses": {"base": "/expenses", "path_param": False},
    "projects": {"base": "/projects", "path_param": False},
    "cycles": {"base": "/cycles/{id}", "path_param": True, "parent_base": "/projects/{projectId}/cycles"},
    "tasks": {"base": "/tasks/{id}", "path_param": True, "parent_base": "/projects/{projectId}/tasks"},
    "comments": {"base": "/comments/{id}", "path_param": True, "parent_base": "/tasks/{taskId}/comments"},
}
python
# delete
delete_p = subparsers.add_parser("delete", help="Delete resource")
delete_p.add_argument("resource", choices=SUPPORTED_RESOURCES.keys())
delete_p.add_argument("--id", required=True)
python
elif args.action == "delete":
    resp = make_request("DELETE", url, api_key)

The declared Skill resource table is narrower:

markdown
| Resource     | Endpoint         | Notes                          |
|-------------|------------------|--------------------------------|
| `clients`   | `/clients`       | Clients & suppliers (finance_parties) |
| `contacts`  | `/projects/{id}/contacts` | Project-scoped contacts |
| `deals`     | `/deals`         | CRM opportunities (crm_deals)  |
| `proposals` | `/proposals`     | Commercial proposals           |
| `receivables` | `/receivables` | Accounts receivable            |

...[truncated 1977 chars]
Remediation
View remediation

Remediation Suggestions

  • Remove projects, cycles, tasks, and comments from this CRM-focused Skill unless they are required for its declared purpose.
  • If those resources are intentional, document them prominently in SKILL.md, including every supported action and its potential impact.
  • Separate CRM and project-management functionality into distinct Skills and credentials.
  • Use resource-scoped API keys with the minimum necessary server-side permissions.
  • Require explicit user confirmation before delete operations and other high-impact changes.
  • Consider disabling generic deletion and implementing an allowlist of permitted resource/action combinations.
  • Add authorization checks on the server; client-side restrictions must not be treated as the primary security boundary.
  • Log destructive operations with the acting identity, affected resource, timestamp, and request identifier.

T08 · Insecure Dependencies

Warning
Location
scripts/flow_api.py:2
Finding

Runtime Dependency Is Not Reproducibly Pinned

Content
View full analysis

Vulnerability Details

File Location: scripts/flow_api.py, lines 2–6
Vulnerability Type: Unbounded dependency resolution within a major version
Risk Level: Medium

Vulnerable Code

python
# /// script
# requires-python = ">=3.10"
# dependencies = [
#     "httpx>=0.27.0",
# ]
# ///

Technical Analysis

The script declares httpx>=0.27.0 without an exact version, upper bound, lockfile, or integrity hash. Running the script through uv run can therefore resolve a later package release rather than a specifically audited artifact.

This prevents reproducible dependency installation and increases exposure to supply-chain compromise, malicious package publication, or security and compatibility regressions in future releases. The imported package executes in the same Python process as the Skill and therefore shares access to environment variables, bearer credentials, request bodies, and network communication.

The package name itself is not shown to be typosquatted or malicious. The risk arises from unrestricted future resolution and lack of artifact verification.

Attack Path

  1. The Skill is run in an environment without a previously locked and verified dependency set.
  2. uv resolves a newer version satisfying httpx>=0.27.0.
  3. If a satisfying release or its distribution channel has been compromised, the altered package is downloaded and imported.
  4. Package initialization or invoked HTTP functionality executes inside the Skill process.
  5. Malicious dependency code reads FLOWDECK_API_KEY, captures request bodies, modifies requests, or transmits information externally.

Impact Assessment

A compromised dependency would execute with the same operating-system privileges as the user running the Skill. It could access the FlowDeck API key, CRM data handled by the process, readable local files available to that user, and permitted network resources.

Exploitation depends on a ma ...[truncated 150 chars]

Remediation
View remediation

Remediation Suggestions

  • Pin httpx to a specific audited version rather than using only a minimum version constraint.
  • Generate and commit a lockfile that records the complete transitive dependency graph.
  • Use package hashes or an equivalent integrity-verification mechanism.
  • Update dependencies through a controlled review process with automated vulnerability scanning.
  • Configure package resolution to use trusted indexes only.
  • Rebuild and test the Skill after dependency updates before deployment.
  • Consider running the Skill in a restricted environment with minimal filesystem access and only the network destinations it requires.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Rogue AgentSelf-Modification, Session Persistence
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (9)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The documented purpose is limited to CRM operations, but the behavior described by analysis includes additional project-management resources and a generic standalone CLI surface. This mismatch is dangerous because hidden or under-declared capabilities expand what the agent can do, reducing user awareness and increasing the chance of unintended access or modification beyond CRM scope.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The implementation exposes project-management endpoints such as projects, cycles, tasks, and comments that are outside the stated CRM scope. In an agent setting, hidden or undocumented extra capabilities are dangerous because the tool can be induced to perform actions on resources users did not authorize or expect, expanding blast radius beyond the advertised purpose.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill invokes a local script that uses environment variables and makes outbound network requests, but the manifest does not declare any tool scope or permissions. This weakens reviewability and consent boundaries because an agent could access secrets like FLOWDECK_API_KEY and perform live CRM actions without explicit capability disclosure.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill documents update and delete operations without any warning, confirmation, or safety guidance for destructive changes to business records. In an agent-driven workflow, that increases the risk of accidental data loss, unauthorized modification, or irreversible deletion of CRM data.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

SQP-3 applies to all file types and covers language or locale policy violations. This instruction mandates a specific language style for user interaction, but the document does not provide user opt-in or explain that the skill is intentionally limited to a Portuguese-speaking context.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

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

uv run ~/.codex/skills/flow-crm/scripts/flow_api.py list clients --status active --limit 20

text

**Create a deal:**
```bash
uv run ~/.codex/skills/flow-crm/scripts/flow_api.py create deals \
  --data '{"title":"Website Redesign","client_id":"<uuid>","value":50000,"stage":"lead"}'

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The file-level documentation advertises project-management capabilities even though the skill metadata describes a CRM-focused integration. This mismatch can mislead operators and downstream agents into invoking broader functionality than intended, increasing the chance of unauthorized access to project/task/comment data and violating least-privilege expectations.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

This code exposes a delete command and directly issues an HTTP DELETE request without a confirmation prompt or any user-facing disclosure at execution time. Although the module docstring lists the command, there is no explicit warning that the operation is destructive or irreversible.

Content

No source excerpt is available for this finding.

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/flow_api.py (reported line 75)May include surrounding context.

python
"assignee_id", "stage", "party_id", "category_id",
                 "type", "due_date_from", "due_date_to", "date_from",
                 "date_to"):
        val = getattr(args, key, None)
        if val is not None:
            params[key] = str(val)
    return params

Static analysis

No suspicious patterns detected.