Back to skill

Security audit

ActiveCampaign (50+ Capabilities)

Security checks for vulnerabilities and agentic risk

Overview

This is mostly a disclosed ActiveCampaign reporting skill, but it needs review because some instructions can bypass its own write safeguards and one webhook audit can probe arbitrary or internal URLs.

Review before installing. Use a least-privileged ActiveCampaign integration user, set AC_READ_ONLY=1 for analysis-only use, avoid the direct curl write examples, and prefer named scripts or the Python client for any changes. Run webhook_audit.py with --skip-probe unless you have reviewed the configured webhook URLs and are comfortable with outbound probes from your machine. Treat snapshots, contact exports, suppression exports, and local state as customer data and delete them when no longer needed.

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/webhook_audit.py:27
Finding

Server-Side Request Forgery Through Unrestricted Webhook Probes

Content
View full analysis
dict: if not url or not url.startswith(("http://", "https://")): return {"reachable": False, "error": "invalid url"} try: req = urllib.request.Request(url, method="HEAD") with urllib.request.urlopen(req, timeout=timeout) as resp: return {"reachable": True, "status": resp.status} ``` ### Technical Analysis The probe accepts any URL beginning with `http://` or `https://` and sends a request using `urllib.request.urlopen()`. It does not validate: - The destination hostname or resolved IP address - Loopback addresses such as `127.0.0.1` or `::1` - Private network ranges - Link-local and cloud metadata addresses - Reserved or unspecified IP ranges - Destination ports - Redirect destinations - DNS rebinding between validation and connection The URLs come from webhook records retrieved from the ActiveCampaign account. Consequently, a user who can create or modify a webhook can influence requests originating from the environment running the Skill. The implementation also conflicts with the claim in `SECURITY.md` that the webhook probe cannot be redirected to arbitrary targets. `urlopen()` can follow HTTP redirects, and no destination validation is performed before or after redirection. ### Attack Path 1. An attacker obtains permission to create or modify webhook records in the connected ActiveCampaign account. 2. The attacker configures a webhook URL targeting an internal address, such as a loopback service, private-network endpoint, or cloud metadata service. 3. Alternatively, the attacker configures a public URL that redirects to an internal destination. 4. The operator or Agent runs `scripts/webhook_audit.py` without the optional `--skip-probe` flag. 5. `probe_url()` issues ...[truncated 946 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:445
Finding

Documented Direct API Writes Bypass Centralized Safety Controls

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (205)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · INSTALL.md (reported line 179)May include surrounding context.

bash
openclaw skills uninstall activecampaign
rm -rf ~/.activecampaign-skill   # removes state and history

State and history files are NOT removed automatically on uninstall. If you reinstall, your data is preserved.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description presents a feature-rich ActiveCampaign reporting/diagnostics agent. The provided code chunk does not implement any ActiveCampaign integration, marketing analytics, reporting, triggers, or sales/list-health functionality. Instead, it is a generic sanitization helper for API-sourced strings. While sanitization could be a supporting internal detail in a larger system, this chunk’s actual purpose is materially different from the declared primary purpose, so this code chunk does not accurately represent the described skill behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared description emphasizes an agent that analyzes ActiveCampaign data to produce operational and marketing reports such as list health, lead scoring, deliverability, campaign postmortems, and automation diagnostics. The supplied code does not compute, analyze, or report on those topics. Instead, it fetches raw account objects from many ActiveCampaign API endpoints and saves them as a local JSON archive for auditing, diffing, and review. While both relate to ActiveCampaign, the primary purpose is materially different: export/backup-style snapshotting versus analytics/reporting. The code also accesses and stores contacts and deals when requested, which is a significant data-export capability not reflected in the declared description.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description presents the skill as an ActiveCampaign reporting/diagnostics agent for marketers and sales users. However, the supplied code chunk does not implement reporting, analytics, campaign analysis, automation diagnostics, or any ActiveCampaign data access. Its sole purpose is authentication credential management: showing where AC_API_URL and AC_API_TOKEN come from, storing them in the OS keychain, and clearing them. This is a materially different primary purpose from the declared marketing/reporting functionality, so it is a clear mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The declared description presents a broad ActiveCampaign analytics/reporting agent with many marketer and sales reports across multiple domains. The supplied code chunk, however, only implements one focused diagnostic: mapping dependencies among automations by inspecting automation blocks for tag application, automation enrollment, and message sending. While this fits loosely under 'automation diagnostics,' it does not substantiate the much broader declared purpose. Therefore the description materially overstates what this code chunk actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The description claims a comprehensive ActiveCampaign agent with numerous reporting and diagnostic capabilities across marketing and sales domains. The supplied code does not implement those functions. Instead, it accepts an automation name, searches cached taxonomy or the ActiveCampaign automations endpoint, and formats matching automation records with ID, name, status, entered, and exited counts. This is a materially different and much narrower primary purpose than the declared broad reporting/diagnostics agent, so it should be flagged as a mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The declared description presents a broad reporting/analytics agent for marketing and sales use cases (list health, deliverability, postmortems, automation diagnostics, etc.). The supplied code chunk does not implement reporting or analysis across campaigns/lists/automations; it only fetches one contact record from the ActiveCampaign contacts endpoint and formats the result. This is a materially different primary purpose and introduces a specific contact-record retrieval capability not reflected in the description. While the returned score and bounce fields may be adjacent to lead scoring or deliverability concepts, the code is still fundamentally a single-contact lookup tool rather than the described reporting agent.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description emphasizes broad marketing/sales reporting and diagnostics (list health, lead scoring, deliverability, campaign postmortems, automation diagnostics). The code does not implement those reporting functions. Instead, it performs a targeted export of one contact's full record and related resources, producing a local JSON artifact for debugging, audit, or compliance handling. This is a materially different primary purpose and introduces an undeclared capability: extracting detailed personal/contact data. The lack of declared triggers/permissions is not itself the issue; the mismatch is between the promised reporting agent and the actual contact-data export behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The declared description presents a broad analytics/reporting agent focused on marketer and sales reporting use cases across lists, scoring, deliverability, campaigns, and automations. The supplied code chunk instead implements a specific utility for fetching a full profile of one contact, identified by email or ID, and collecting related records in parallel. It accesses and outputs detailed contact-specific data, including personal/contact details, tags, list subscriptions, automations, custom field values, notes, and deals. That is a materially different primary purpose from the declared account-level/reporting-oriented description. While contact-level data could support some sales workflows, this script is not performing the kinds of analyses named in the declaration, so the description does not accurately represent this code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared description presents a broad analytics/reporting agent focused on list health, lead scoring, deliverability, campaign postmortems, automation diagnostics, and dozens of reports. The supplied code chunk does not implement those reporting or diagnostic capabilities. Instead, it only queries the ActiveCampaign contacts endpoint with an email address and returns details for one contact, including identifying/profile information and some status fields. This is a materially different and much narrower primary purpose, so the description does not accurately represent the behavior of this code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

The declared description presents a broad ActiveCampaign reporting/diagnostics agent with 40+ report capabilities across multiple marketing and sales domains. The supplied code chunk, however, is a single-purpose script focused solely on retrieving and displaying the top contacts by score or recent modification date. While this could fit loosely within lead scoring/engagement reporting, it materially underrepresents the actual scope of the declared skill and does not demonstrate the broad capabilities claimed. Therefore, the description does not accurately represent what this specific code chunk actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The supplied code chunk performs a specific contact-list retrieval operation: it makes one API call to the ActiveCampaign contacts endpoint, sorts by creation date descending, limits results, sanitizes selected fields, and renders a table of recent contacts. That is materially narrower and different from the declared description, which emphasizes a comprehensive reporting/diagnostics agent covering list health, lead scoring, deliverability, campaign postmortems, automation diagnostics, and many other reports. While contact reporting could loosely fit within a broad ActiveCampaign tool, this particular code does not implement those described analytics capabilities and instead acts as a simple 'most recent contacts' viewer.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description presents a broad analytics/reporting agent centered on marketer and sales insights such as list health, lead scoring, deliverability, campaign postmortems, and automation diagnostics. The supplied code instead implements a specific CRM lookup/report for one deal. It queries deal, contact, tasks, notes, and custom field resources and formats them into a deal context summary. This is materially different in primary purpose and resource scope from the declared description, and the CRM/deal-focused capability is not accurately represented by the stated marketing/reporting description.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description presents a broad ActiveCampaign analytics/reporting agent covering list health, lead scoring, deliverability, campaign postmortems, automation diagnostics, and many other reports. The supplied code chunk instead implements a specific duplicate-contact audit script. It scans contact records and detects likely duplicates using normalized email, phone, and name heuristics, then outputs candidate groups. While duplicate detection could loosely relate to 'list health,' the actual code’s primary purpose is deduplication, not the broader reporting/diagnostics functions described. This is a material description-behavior mismatch because the implemented capability is narrower and different in kind from the declared multi-report agent.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description promises a broad ActiveCampaign analytics/reporting agent for marketing and sales use cases. The supplied code instead has a narrow, specific purpose: validating a contact CSV before import by inspecting email-related quality issues and producing a local report. While this could loosely relate to list hygiene, it does not meaningfully implement the advertised agent capabilities, does not interact with ActiveCampaign, and relies on local CSV file input not reflected in the description. This is a material description-behavior mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The description portrays a broad ActiveCampaign analytics agent focused on marketer/sales reporting categories such as list health, lead scoring, deliverability, campaign postmortems, and automation diagnostics. The supplied code does not implement those areas. Instead, it performs a specific CRM sales performance roll-up for individual reps using users, deals, deal tasks, and notes. That is a materially different primary purpose from the declared examples and involves CRM performance analysis capabilities not explicitly represented in the description. While the phrase '40+ more reports' is broad, the concrete declared purpose emphasizes marketing and operational reporting categories, not a per-rep productivity scoreboard, so this is best treated as a mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared description presents a broad ActiveCampaign reporting/diagnostics agent focused on marketer and sales analytics such as list health, lead scoring, deliverability, campaign postmortems, and automation diagnostics. The supplied code does not implement any of those areas. Instead, it fetches the /savedResponses endpoint and audits the saved response library for staleness, anomalous length, and near-duplicate content. That is a distinct CRM content-governance/reporting function and uses a resource not referenced in the description. This is a material description-behavior mismatch, not merely an implementation detail.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description presents a broad ActiveCampaign analytics/reporting agent for marketing and sales use cases. The supplied code instead is a narrowly scoped local CLI script for diffing two JSON account snapshots and summarizing structural taxonomy changes. While automation-related changes could be loosely adjacent to 'automation diagnostics,' the primary purpose is materially different and far more limited than the declared capability set. There is no evidence of live ActiveCampaign access, marketer-facing reporting workflows, or the many named report types in the description.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
8. **Destructive helpers (e.g. `tag_merge.py`) are dry-run by default**; `--confirm` is required to execute, and they refuse to operate on anything still refere

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
| `snapshots/*.json` | Versioned account snapshots | `snapshot.py`, `account_archive.py` | Manual |

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
| `snapshots/*.json` | Versioned account snapshots | `snapshot.py`, `account_archive.py` | Manual |

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
| Find a tag id by name | `scripts/tag_lookup.py --name <name>` *(checks state.json first; no API call if cached)* |

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
| Find a tag id by name | `scripts/tag_lookup.py --name <name>` *(checks state.json first; no API call if cached)* |

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
| Subject line pattern analysis | `scripts/subject_line_report.py [--days N]` |

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
| Best send window | `scripts/send_time_optimizer.py` |

Static analysis

No suspicious patterns detected.