Back to skill

Security audit

Crisp Skill

Security checks for vulnerabilities and agentic risk

Overview

This Crisp support skill is coherent and not malicious, but it gives an agent real read/write access to customer conversations without enforced confirmation for customer-visible and ticket-closing actions.

Review this before installing in an account with production customer data. Use a least-privilege Crisp plugin token, keep credentials out of shared shell profiles when possible, require explicit human approval before sending customer replies or resolving tickets, and consider pinning dependencies in a virtual environment.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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)

T08 · Insecure Dependencies

Warning
Location
README.md:46
Finding
Unpinned Third-Party Dependency Installation## Vulnerability Details **File Location**: `README.md`, lines 46–50 **Vulnerability Type**: Unpinned and unverifiable third-party dependency **Risk Level**: Medium ### Vulnerable Code ```markdown ### 4. Install Dependencies The script uses Python 3 and the `requests` library. ```bash pip3 install requests ``` ``` ### Technical Analysis The documented installation command retrieves the latest available version of `requests` from the package index configured for the user's Python environment. The project provides no version constraint, lockfile, integrity hash, explicit trusted index, or isolated-environment requirement. Consequently, installations are not reproducible and implicitly trust both the configured package index and the dependency version available at installation time. If the package source, package maintainer account, index configuration, or network trust boundary is compromised, unintended code could be installed. Python packages can execute code during installation and whenever imported; `scripts/crisp.py` imports `requests` at startup. This finding is limited to supply-chain hardening. The audited code does not itself download or execute an unknown remote payload at runtime. ### Attack Path 1. An attacker compromises a relevant package distribution account or causes the victim's pip configuration to reference an attacker-controlled index or mirror. 2. The user follows the documented `pip3 install requests` command. 3. Because no reviewed version or integrity hash is required, pip resolves and installs the package supplied by the selected index. 4. Malicious code executes during package installation or later when `scripts/crisp.py` imports `requests`. 5. The payload runs with the privileges of the user performing the installation or invoking the Skill. ### Impact Assessment Successful exploitation could provide arbitrary code execution under the Skill operator's account. The resulting proces ...[truncated 595 chars]
Remediation
## Remediation Suggestions 1. Add a reviewed, version-pinned dependency file, such as: ```text requests==<reviewed-version> ``` 2. Generate and enforce cryptographic hashes for the package and its transitive dependencies, then install with: ```bash python3 -m pip install --require-hashes -r requirements.txt ``` 3. Commit a lockfile or fully hashed requirements file so installations are reproducible. 4. Install dependencies inside a dedicated virtual environment rather than the system Python environment. 5. Use an explicitly configured trusted package index or an internally controlled package mirror. 6. Periodically review and update pinned versions after vulnerability and compatibility testing. 7. Document that credentials should be injected only at runtime and should not be present while installing dependencies.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (15)

Tainted flow: 'url' from os.environ.get (line 53, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Content
url = f"{API_BASE}/{WEBSITE_ID}/{endpoint}"
    try:
        if method == "GET":
            resp = requests.get(url, headers=headers, params=data, timeout=10)
        elif method == "POST":
            resp = requests.post(url, headers=headers, json=data, timeout=10)
        elif method == "PATCH":
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Tainted flow: 'url' from os.environ.get (line 53, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Content
if method == "GET":
            resp = requests.get(url, headers=headers, params=data, timeout=10)
        elif method == "POST":
            resp = requests.post(url, headers=headers, json=data, timeout=10)
        elif method == "PATCH":
            resp = requests.patch(url, headers=headers, json=data, timeout=10)
        elif method == "DELETE":
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Tainted flow: 'url' from os.environ.get (line 53, credential/environment) → requests.patch (network output)

Critical
Category
Data Flow
Content
elif method == "POST":
            resp = requests.post(url, headers=headers, json=data, timeout=10)
        elif method == "PATCH":
            resp = requests.patch(url, headers=headers, json=data, timeout=10)
        elif method == "DELETE":
            resp = requests.delete(url, headers=headers, timeout=10)
        else:
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The README explicitly promotes capabilities to reply to customers and send messages through the Crisp API, but it does not warn that these actions create external, user-visible side effects. In an agentic setting, this can lead operators to invoke the skill without realizing it may contact real customers, causing unintended communications, reputational harm, or unauthorized outbound actions.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The README instructs users to store long-lived Crisp credentials in shell environment variables and even includes a realistic example token format, but it does not warn that these secrets grant inbox read/write access and may be exposed through shell history, process inspection, logs, screenshots, or inherited environments. Because the token scopes include reading conversations and sending messages, credential exposure could enable unauthorized access to customer communications and impersonation via the support channel.

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill clearly relies on sensitive capabilities: reading environment variables for Crisp credentials and making outbound network requests to the Crisp API, yet it does not declare any explicit tool scope such as permissions or allowed-tools. This weakens least-privilege controls and increases the chance the agent can access secrets or perform external actions without transparent policy boundaries.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
This markdown file describes use of authentication credentials via environment variables and later documents endpoints returning visitor metadata such as email, phone, IP address, and device details. Under the markdown-specific warning rule, the document should warn users that the skill may access and process sensitive personal data and secrets.

External Transmission

Medium
Category
Data Exfiltration
Content
sys.exit(1)

# Configuration
API_BASE = "https://api.crisp.chat/v1/website"
WEBSITE_ID = os.environ.get("CRISP_WEBSITE_ID")
TOKEN_ID = os.environ.get("CRISP_TOKEN_ID")
TOKEN_KEY = os.environ.get("CRISP_TOKEN_KEY")
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
sys.exit(1)

# Configuration
API_BASE = "https://api.crisp.chat/v1/website"
WEBSITE_ID = os.environ.get("CRISP_WEBSITE_ID")
TOKEN_ID = os.environ.get("CRISP_TOKEN_ID")
TOKEN_KEY = os.environ.get("CRISP_TOKEN_KEY")
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
if method == "GET":
            resp = requests.get(url, headers=headers, params=data, timeout=10)
        elif method == "POST":
            resp = requests.post(url, headers=headers, json=data, timeout=10)
        elif method == "PATCH":
            resp = requests.patch(url, headers=headers, json=data, timeout=10)
        elif method == "DELETE":
Confidence
80% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Description-Behavior Mismatch

Medium
Confidence
91% confidence
Finding
The undocumented 'websites' command expands the tool's real capability beyond the declared customer-support inbox scope and prints raw API response structures. In an agent setting, hidden command surface is dangerous because it can expose broader account metadata than users or orchestrators expect, weakening least-privilege and making prompt-driven misuse easier.

Context-Inappropriate Capability

Medium
Confidence
90% confidence
Finding
This branch emits full raw response content for a debug/introspection action that is not justified by normal inbox operations. In practice, such debug output can disclose account structure, conversation metadata, or future API fields containing sensitive information to downstream logs, users, or other tools.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The tool performs state-changing actions such as marking conversations read or resolved immediately, with no confirmation, dry-run mode, or safety interlock. In an agent context, this increases the chance of unintended business actions from ambiguous prompts, prompt injection in message content, or simple operator error.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
Outbound message sending occurs directly from command input without a pre-send review step. For support tooling used by agents, this is risky because a malformed prompt, prompt injection, or misunderstanding can cause unauthorized or harmful communications to real customers.

Intent-Code Divergence

Low
Confidence
81% confidence
Finding
The usage documentation omits an implemented command, causing the published interface to diverge from the actual executable surface. In an agent ecosystem, undocumented capabilities undermine review and policy enforcement because operators may approve a skill based on incomplete understanding of what it can do.

Static analysis

No suspicious patterns detected.