Back to skill

Security audit

Twenty CRM

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real Twenty CRM helper, but it can make authenticated CRM changes and deletions, including a destroy mode, without built-in safeguards.

Review before installing. Use a least-privilege Twenty API key, point TWENTY_BASE_URL only at the CRM instance you intend to manage, keep any config file private and user-owned, and require explicit human approval before an agent runs DELETE or destroy operations.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/twenty-config.sh:11
Finding
Arbitrary Shell Execution Through Unsafe Configuration Loading## Vulnerability Details **File Location**: `scripts/twenty-config.sh:11, 29-31` **Vulnerability Type**: Executable configuration file / arbitrary shell command execution **Risk Level**: Medium ### Vulnerable Code ```bash CONFIG_FILE="${TWENTY_CONFIG_FILE:-$DEFAULT_CONFIG_FILE}" if [ -f "$CONFIG_FILE" ]; then # shellcheck disable=SC1090 source "$CONFIG_FILE" fi ``` ### Technical Analysis The script treats `config/twenty.env` as a data-based environment file but loads it with Bash's `source` built-in. Sourcing a file executes its entire contents in the current shell rather than parsing only environment-variable assignments. Consequently, a configuration file can contain arbitrary shell commands, command substitutions, functions, redirections, or other Bash syntax. The `TWENTY_CONFIG_FILE` environment variable also allows the caller to select any readable file as the configuration source. This becomes exploitable when an attacker can modify the default configuration file, influence `TWENTY_CONFIG_FILE`, or otherwise cause a malicious file to be loaded. The injected commands execute with the same operating-system privileges and environment as the invoked CRM helper. ### Attack Path 1. An attacker gains control over `config/twenty.env` or influences the process environment to set `TWENTY_CONFIG_FILE` to an attacker-controlled readable file. 2. The attacker places shell commands in that file, potentially alongside valid `TWENTY_BASE_URL` and `TWENTY_API_KEY` assignments. 3. A user or agent invokes any helper that sources `twenty-config.sh`. 4. `twenty-config.sh` executes `source "$CONFIG_FILE"`. 5. The attacker's commands run before the intended CRM API request and inherit the helper's privileges and environment. ### Impact Assessment Successful exploitation permits arbitrary command execution under the account running the Skill. The attacker could read files available to that account, access the configured Twenty CRM API key, alter local data, or mak ...[truncated 327 chars]
Remediation
## Remediation Suggestions Replace `source` with a non-executing configuration parser: 1. Accept only an explicit allowlist of keys, namely `TWENTY_BASE_URL` and `TWENTY_API_KEY`. 2. Parse assignment lines as data without `eval`, `source`, or shell expansion. 3. Reject command substitutions, shell operators, functions, redirections, unrecognized keys, and malformed lines. 4. Prefer direct environment-variable configuration or a structured format parsed by a safe standard parser. 5. If `TWENTY_CONFIG_FILE` remains supported, resolve and validate the path and ensure that the file is a regular file owned by the expected user. 6. Reject configuration files writable by group or other users and recommend mode `0600`. 7. Avoid exporting the API key unless child processes genuinely require it; pass secrets only to the specific command that needs them.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (11)

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
## Secret handling

- Do not commit `TWENTY_API_KEY`.
- If using `config/twenty.env`, keep it private (for example: `chmod 600 config/twenty.env`).

## Scope
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
## Secret handling

- Do not commit `TWENTY_API_KEY`.
- If using `config/twenty.env`, keep it private (for example: `chmod 600 config/twenty.env`).

## Scope
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill exposes shell-capable scripts but does not declare any explicit tool scope such as permissions or allowed-tools. That increases the chance an agent can invoke broader shell behavior than intended, reducing policy visibility and making misuse of the skill harder to constrain or audit.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The documentation includes a DELETE helper for CRM objects without any warning, confirmation step, or guidance on safe use. In a CRM context, accidental or agent-initiated deletions can permanently remove business records, making destructive actions easier to trigger unintentionally.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
## Security

- Keep `TWENTY_API_KEY` out of git and avoid storing it in shared/world-readable files.
- If you use `config/twenty.env`, prefer restrictive permissions (for example `chmod 600 config/twenty.env`).
- Pass REST query parameters as separate `key=value` arguments; do not append raw query strings to REST paths.
Confidence
70% confidence
Finding
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

External Transmission

Medium
Category
Data Exfiltration
Content
BODY=$(printf '{"query":%s}' "$QUERY_JSON")
fi

curl -sS -X POST "$TWENTY_BASE_URL/graphql" \
  -H "Authorization: Bearer $TWENTY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
Confidence
70% 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
90% confidence
Finding
The skill manifest says the skill interacts with Twenty CRM via REST/GraphQL, which is broad, but this file specifically implements DELETE operations and an optional `/destroy` endpoint for stronger destructive action. That behavior is more dangerous than generic interaction and is not signaled anywhere in the file documentation or manifest description excerpt.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
This script performs irreversible or potentially irreversible DELETE operations, including an optional /destroy mode, without any confirmation prompt, dry-run mode, or secondary validation beyond path format checking. In an agentic or automated context, that increases the chance of accidental record loss from malformed inputs, misuse, or prompt-induced actions, especially because the command directly authenticates and executes against the live API.

External Transmission

Medium
Category
Data Exfiltration
Content
fi
validate_rest_path "$PATH_PART"

curl -sS -X PATCH "$TWENTY_BASE_URL/rest${PATH_PART}" \
  -H "Authorization: Bearer $TWENTY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The script performs a network PATCH request with a JSON payload and sends a bearer token from an environment-sourced configuration, but there is no confirmation prompt, user-facing log message, or explanatory comment near the operation. For code files, outbound network actions and credential use should have some visible disclosure unless clearly communicated elsewhere in the skill materials.

External Transmission

Medium
Category
Data Exfiltration
Content
fi
validate_rest_path "$PATH_PART"

curl -sS -X POST "$TWENTY_BASE_URL/rest${PATH_PART}" \
  -H "Authorization: Bearer $TWENTY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Static analysis

No suspicious patterns detected.