Back to skill

Security audit

Build Smart Lists

Security checks for vulnerabilities and agentic risk

Overview

This skill is related to HubSpot list creation, but its executable script creates different lists than the documentation promises and omits important consent and deliverability filters from the main marketing list.

Review this carefully before installing or running. If used, run it only with a HubSpot token limited to the minimum list-management scopes, inspect the generated list definitions first, and do not treat the script-created 'All Marketing Contacts' list as a compliant sendable audience unless the missing unsubscribe, bounce, email-known, and quarantine filters are added and verified in HubSpot.

Vulnerability Patterns
  • 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
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/execute.py:62
Finding

Generated marketing list omits required consent and deliverability safeguards

Content
View full analysis
is any of > Marketing contact - AND Unsubscribed from all email > is not equal to > True - AND Hard bounce reason > is unknown - AND Email > is known - AND Email quarantined > is not equal to > True ``` ### Technical Analysis The Skill documentation defines its foundational sendable list as a consent- and deliverability-aware list. It requires all of the following conditions: 1. The contact is a marketing contact. 2. The contact has not globally unsubscribed. 3. The contact has not hard-bounced. 4. The contact has a known email address. 5. The email address is not quarantined. The executable implementation only tests `hs_marketable_status == "true"`. It does not implement the other four required safeguards. Consequently, the generated dynamic list can contain contacts who have globally unsubscribed, have hard-bounced, have a quarantined address, or do not have a usable email address. This is particularly dangerous because the documentation characterizes the foundational list as the single source of truth for contacts who can receive m ...[truncated 1504 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
scripts/execute.py:1
Finding

Open-ended dependency constraints allow unaudited future package versions

Content
View full analysis
=3.10" # dependencies = [ # "requests>=2.31", # "python-dotenv>=1.0", # ] # /// ``` ### Technical Analysis The script declares `requests` and `python-dotenv` using open-ended minimum-version constraints. A compatible script runner may therefore install any current or future package release satisfying those constraints. The package names are legitimate and there is no evidence in the audited project that their current releases are malicious. Nevertheless, the constraints do not ensure that execution uses the versions that were reviewed. If a future release or its distribution channel is compromised, the script could automatically resolve and execute the affected package without any change to the audited repository. This is security-sensitive because the script loads `HUBSPOT_ACCESS_TOKEN` into its process environment before making authenticated requests. Imported dependency code executes in the same Python process and inherits the process's filesystem, environment, and network access. ### Attack Path 1. A future permitted release of `requests`, `python-dotenv`, or one of their transitive dependencies is compromised, malicious, or unexpectedly incompatible. 2. A user invokes the script in an environment that resolves inline dependencies. 3. The resolver selects the compromised release because it satisfies the open-ended `>=` constraint. 4. Package installation hooks or imported package code execute with the user's privileges. 5. The malicious code accesses process resources, potentially including the local `.env` file and `HUBSPOT_ACCESS_TOKEN`. 6. Using the token's granted scopes, the malicious code could make unauthorized HubSpot API requests or transmit the token elsewhere. This attack path depends on a supply-chain compromise ...[truncated 749 chars]
Remediation
View remediation
", # "python-dotenv==", # ] ``` 2. Generate and retain a lockfile that also fixes all transitive dependency versions. 3. Require cryptographic hashes for downloaded artifacts where supported by the package-management workflow. 4. Use an explicitly configured trusted package index rather than allowing uncontrolled or ambiguous index resolution. 5. Scan direct and transitive dependencies for known vulnerabilities during development and continuous integration. 6. Update dependency pins through a controlled review process that includes changelog review, vulnerability scanning, and regression testing. 7. Run the Skill in a restricted environment with minimal filesystem access and constrained outbound network access. 8. Grant the HubSpot token only the scopes required to create and inspect lists, and rotate the token if dependency compromise is suspected. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • 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 (7)

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

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/execute.py (reported line 339)May include surrounding context.

python
print(f"[{i}/{len(LISTS)}] Creating: {name}...", end=" ")

    for attempt in range(MAX_RETRIES):
        resp = requests.post(create_url, headers=HEADERS, json=list_def)
        if resp.status_code == 429:
            wait = min(10 * (attempt + 1), 30)
            print(f"rate limited, waiting {wait}s...", end=" ")

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

The code broadly aligns with the general goal of creating dynamic segmentation lists in HubSpot, especially for sendable/marketing contacts, ICP tiers, and engagement. However, the declared description specifically claims inclusion of persona lists and behavioral lists, which are not actually implemented. The only behavior-style segmentation present is limited email engagement/unengagement windows, not broader behavioral lists. Additionally, the script creates lifecycle-stage lists (Leads, MQLs, SQLs, Customers), which are not mentioned in the declared description, and it accesses HubSpot APIs plus writes a CSV audit file despite no declared permissions. These are material enough differences to mark as a mismatch, though the primary domain purpose remains related.

Content

No source excerpt is available for this finding.

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/execute.py (reported line 39)May include surrounding context.

python
from dotenv import load_dotenv

# ── Configuration ────────────────────────────────────────────────
load_dotenv(os.path.join(os.path.dirname(__file__), "..", ".env"))

TOKEN = os.environ["HUBSPOT_ACCESS_TOKEN"]
BASE = "https://api.hubapi.com"

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The manifest describes foundational segmented lists including persona lists and behavioral lists, but this script's documented and implemented output is a fixed set of 10 lists composed of marketing/lifecycle lists, ICP company tiers, and only two engagement-based lists. That is a meaningful mismatch between the stated skill scope and the actual behavior implemented here.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/execute.py (reported line 339)May include surrounding context.

python
print(f"[{i}/{len(LISTS)}] Creating: {name}...", end=" ")

    for attempt in range(MAX_RETRIES):
        resp = requests.post(create_url, headers=HEADERS, json=list_def)
        if resp.status_code == 429:
            wait = min(10 * (attempt + 1), 30)
            print(f"rate limited, waiting {wait}s...", end=" ")

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

A 'master sendable list' is a specific concept in the manifest, but the implemented first list filters only on hs_marketable_status == true and is named 'All Marketing Contacts'. That may overlap operationally, but it is not clearly the same behavior the manifest claims.

Content

No source excerpt is available for this finding.