Back to skill

Security audit

Lead Scoring

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly lead-scoring related, but it asks for a live HubSpot token and includes operational CRM/data-processing behavior despite presenting itself as instruction-only.

Review this skill before installing. Use it only with a test CRM or least-privilege token, and do not grant a production HubSpot token unless you intend the agent environment to have access to CRM configuration and contact data. Expect the script to create scored contact CSV files, and back up CRM exports before running it.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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)

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
SKILL.md:6
Finding
Unnecessary Exposure of a Privileged HubSpot Access Token<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:6-10` **Vulnerability Type**: Violation of least privilege through an unnecessary credential requirement **Risk Level**: Medium ### Vulnerable Code ```yaml metadata: openclaw: requires: env: - HUBSPOT_ACCESS_TOKEN primaryCredential: HUBSPOT_ACCESS_TOKEN credentialNotes: "Required for HubSpot API access to configure scoring properties and workflows. For Salesforce, set SALESFORCE_ACCESS_TOKEN instead." ``` ### Technical Analysis The skill declares `HUBSPOT_ACCESS_TOKEN` as a required environment variable and its primary credential. However, the audited project does not read this environment variable, invoke the HubSpot API, or perform any network communication. Its executable functionality only processes local CSV and JSON files. Injecting a privileged CRM credential into an execution environment when it is not required violates the principle of least privilege. Although the current script contains no mechanism that transmits or otherwise abuses the token, exposing it to the skill environment unnecessarily expands the credential's attack surface. A future malicious modification, compromised dependency, diagnostic dump, or other process sharing the environment could potentially read it. ### Attack Path 1. An operator activates the skill. 2. The runtime injects `HUBSPOT_ACCESS_TOKEN` because the skill metadata declares it as required. 3. The token becomes available in the skill's process environment despite no current functionality needing it. 4. If the skill, one of its dependencies, or another process with access to that environment is subsequently compromised, the token can be read. 5. The attacker can then use the token against HubSpot APIs within the permissions granted to that token. The audited version does not contain the final token-reading or exfiltration step, so exploitation requires an additional compromise or malicious modification. ### Impact Assessme ...[truncated 433 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `HUBSPOT_ACCESS_TOKEN` from `requires.env` and remove `primaryCredential` from this instruction-only skill. 2. Separate local scoring functionality from any future HubSpot API integration. 3. If API functionality is added later, request credentials only when the API operation is explicitly invoked. 4. Create a dedicated HubSpot private application with only the minimum scopes needed for the requested operation. 5. Avoid exposing tokens to subprocesses, logs, generated reports, exception messages, or unrelated dependencies. 6. Document token rotation and revocation procedures and prefer short-lived credentials where supported. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/score-calculator.py:660
Finding
Unsafe Output Path Derivation Can Overwrite or Truncate CRM Data<![CDATA[ ## Vulnerability Details **File Location**: `scripts/score-calculator.py:660-667` **Vulnerability Type**: Destructive output-path collision and unsafe file overwrite **Risk Level**: Medium ### Vulnerable Code ```python output_path = args.output or args.input.replace('.csv', '_scored.csv') scored_df.to_csv(output_path, index=False) logger.info(f"Scored data saved to {output_path}") # Save top scoring contacts top_contacts = scored_df.nlargest(20, 'total_lead_score') top_path = output_path.replace('.csv', '_top_20.csv') top_contacts.to_csv(top_path, index=False) logger.info(f"Top 20 contacts saved to {top_path}") ``` ### Technical Analysis Output names are derived using case-sensitive string replacement rather than structured path handling. No check ensures that the input, complete output, and top-20 output resolve to distinct files. Two destructive collision cases exist: - If the input filename does not contain lowercase `.csv`, `args.input.replace('.csv', '_scored.csv')` returns the original input path. The complete scored data is then written over the source file. - If an explicitly supplied output filename does not contain lowercase `.csv`, `output_path.replace('.csv', '_top_20.csv')` returns the same output path. The script first writes the complete result and then immediately replaces it with only the top 20 contacts. Examples include extensionless paths and filenames ending in uppercase `.CSV`. `pandas.DataFrame.to_csv()` overwrites existing files by default, and the implementation does not use collision checks, exclusive creation, backups, or atomic replacement. ### Attack Path #### Source-file overwrite 1. A user runs the script with an extensionless or uppercase-extension input, such as: ```bash python scripts/score-calculator.py --input contacts.CSV ``` 2. The default derivation fails to replace lowercase `.csv`. 3. `output_path` remains `contacts.CSV`, identical to the input path. 4. `to_csv()` opens that path for writing ...[truncated 1105 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Use `pathlib.Path` rather than raw string replacement: ```python from pathlib import Path input_path = Path(args.input) output_path = ( Path(args.output) if args.output else input_path.with_name(f"{input_path.stem}_scored.csv") ) top_path = output_path.with_name(f"{output_path.stem}_top_20.csv") ``` 2. Resolve and compare all paths before writing: ```python resolved = { input_path.resolve(), output_path.resolve(), top_path.resolve(), } if len(resolved) != 3: raise ValueError("Input, scored output, and top-20 output must be distinct files") ``` 3. Refuse to overwrite existing files unless the user supplies an explicit `--force` option. 4. Write to a temporary file in the destination directory, flush and synchronize it, and atomically rename it after successful completion. 5. Validate output extensions case-insensitively and explicitly support `.csv` and `.CSV`. 6. Add automated tests for extensionless filenames, uppercase extensions, explicit colliding paths, existing destinations, and symbolic-link aliases. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (10)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The code is related to lead scoring, so the domain overlaps with the description. However, the declared purpose explicitly says this is an instruction-only skill with frameworks and setup guides for HubSpot/CRMs, while the supplied code is an operational scoring engine that processes actual CSV data, computes scores, classifies leads, and saves results. That is a materially different behavior and introduces undeclared file-processing capabilities. It does not implement HubSpot setup guidance or lifecycle-stage configuration; instead it acts as a standalone analytics/scoring utility. Therefore this is a description-behavior mismatch.

Lp3

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding
Without declared permissions the skill's intent is opaque and cannot be validated.

Description-Behavior Mismatch

Medium
Confidence
96% confidence
Finding
The manifest describes the skill as instruction-only, yet it declares required live CRM credentials, which implies the skill may operate against real tenant data or configuration. This mismatch can mislead users and orchestrators into granting sensitive tokens to content they believe is passive guidance, increasing the risk of unintended data access or configuration changes.

Intent-Code Divergence

Medium
Confidence
93% confidence
Finding
The credential notes explicitly mention API access to configure scoring properties and workflows, directly contradicting the instruction-only positioning. That inconsistency is dangerous because it obscures that the skill can make persistent CRM changes, which could affect production sales and marketing operations if invoked with real credentials.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The description references CRM access tokens and API-based configuration but does not disclose that handling CRM records may expose customer and prospect data or alter lead-scoring logic and lifecycle automation. In this context, the omission matters because CRM integrations often touch sensitive business data and production workflows, so users need clear notice before granting access.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The guide instructs users to collect and act on detailed behavioral data such as page views, form submissions, email opens, clicks, and replies to score and route leads, but it provides no guidance on consent, lawful basis, notice, retention, or jurisdictional privacy requirements. In CRM/marketing automation context, this can lead to noncompliant profiling and tracking practices under regulations like GDPR, ePrivacy, and similar laws, especially when automated lifecycle changes and nurturing are triggered from that data.

Session Persistence

Medium
Category
Rogue Agent
Content
3. **Workflow Actions**:
   - Set Lifecycle stage to "Marketing Qualified Lead"
   - Create task for marketing team
   - Send internal notification
   - Add to MQL nurturing sequence
Confidence
80% 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.

Session Persistence

Medium
Category
Rogue Agent
Content
3. **Workflow Actions**:
   - Set Lifecycle stage to "Marketing Qualified Lead"
   - Create task for marketing team
   - Send internal notification
   - Add to MQL nurturing sequence
Confidence
80% 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.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill explicitly instructs collection and scoring of behavioral, demographic, and inferred intent data such as page visits, email engagement, phone number, budget range, and third-party intent signals, but provides no privacy notice, consent guidance, lawful-basis checks, retention limits, or regional compliance considerations. In a lead-scoring skill for CRM automation, this omission is risky because it operationalizes profiling and potentially automated decision-making on personal data, which can create privacy, compliance, and trust harms if deployed as written.

Missing User Warnings

Medium
Confidence
84% confidence
Finding
This code writes a full scored contacts CSV and a separate top-20 contacts CSV derived from CRM exports, which commonly contain personal and business-sensitive data. Although output paths are logged, there is no explicit warning or confirmation to the user that additional files containing processed lead data will be created.