Back to skill

Security audit

cargo-gtm

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a legitimate Cargo GTM automation skill, but it deserves Review because it handles sensitive prospect data through broad external workflows and has concrete safety gaps around install pinning and CSV exports.

Install only if you are comfortable giving the Cargo CLI access to your Cargo workspace and connected GTM providers. Pin the Cargo CLI version before operational use, treat downloaded/signed URLs and output files as sensitive, prefer JSON for machine processing, and do not open generated CSVs in spreadsheets unless formula values are neutralized first. Use the documented basis, suppression, approval, and recurring-cost gates before any enrichment, CRM sync, ad upload, or scheduled workflow.

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/lib/common.ts:113
Finding

Spreadsheet Formula Injection in Generated CSV Reports

Content
View full analysis

Vulnerability Details

File Location: scripts/lib/common.ts, lines 113–125
Vulnerability Type: CSV/spreadsheet formula injection
Risk Level: Medium

Vulnerable Code

ts
function csvEscape(value: string): string {
  return /[",\n\r]/.test(value) ? `"${value.replaceAll('"', '""')}"` : value;
}

export function toCsv(rows: Row[], headers?: string[]): string {
  const cols = headers ?? [...new Set(rows.flatMap((r) => Object.keys(r)))];
  const lines = [cols.map(csvEscape).join(",")];
  for (const row of rows) {
    lines.push(cols.map((c) => csvEscape(row[c] ?? "")).join(","));
  }
  return lines.join("\n") + "\n";
}

The affected serializer is reached by the following executable entrypoints:

  • scripts/contact-accuracy-audit.ts:379–382
  • scripts/validate-emails.ts:383–389
  • scripts/select-current-role.ts:405–411
  • scripts/validate-linkedin-names.ts:326–329

The intended human-review workflow is documented in recipes/review-and-iterate.md:25–44, which instructs users to hand over generated files or place rows in a shared spreadsheet.

Technical Analysis

The shared csvEscape() function only applies RFC 4180 quoting for commas, quotation marks, and line breaks. It does not neutralize values beginning with spreadsheet formula indicators such as =, +, -, or @.

CSV quoting is not a security boundary. Spreadsheet software may still interpret a quoted value such as "=HYPERLINK(...)" as a formula when the CSV is opened or imported.

Rows can originate from Cargo workflow output, provider data, scraped public content, or imported JSON/CSV files through readRows(). The scripts retain the original row properties using object spread and then pass those properties to toCsv(). Consequently, an attacker-controlled company, contact, or scraped field can reach the CSV without formula neutralization.

Attack Path

  1. An attacker places a formula-prefixed string in an externally sourced field that the Skill may ingest, ...[truncated 1785 chars]
Remediation
View remediation

Remediation Suggestions

  1. Make spreadsheet-safe serialization the default for all CSV exports.
  2. Before RFC 4180 escaping, neutralize cells whose first meaningful character is =, +, -, or @. Also account for leading spaces, tabs, carriage returns, and other characters that spreadsheet applications may ignore before formula detection.
  3. Prefix dangerous values with a single quotation mark or another application-compatible neutralization marker. Preserve a separate raw JSON export when exact unmodified values are required.
  4. Apply the protection to both headers and values because attacker-controlled JSON objects can also supply property names.
  5. Centralize the fix in scripts/lib/common.ts so all four current CSV-producing scripts inherit it.
  6. Add regression fixtures covering:
    • =HYPERLINK(...)
    • +SUM(...)
    • -1+1
    • @SUM(...)
    • Formula markers preceded by spaces, tabs, or carriage returns
    • Values containing commas and quotation marks in combination with formula markers
  7. Document that JSON is the preferred format for machine-to-machine processing and that raw, unneutralized values must not be directly imported into spreadsheets.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (60)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description promises operational GTM functions such as researching accounts, enriching contacts, verifying emails, scoring leads, drafting outreach, syncing to CRM, and monitoring signals with compliance controls. This code does not implement any of those business workflows or provider-specific enrichment behaviors. Instead, it is infrastructure for internal QA/testing: command-line parsing, CSV/JSON I/O, Cargo workflow output retrieval, and fixture metrics/exit-code reporting. While fetching workflow outputs from Cargo could be a supporting implementation detail in a broader system, the primary purpose of this specific code chunk is materially different from the declared GTM skill behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

This code chunk does not implement the broad GTM workflow described. Instead, it performs a specific internal data-quality check: normalizing names, handling nicknames/initials/non-Latin scripts, comparing source names to LinkedIn/profile names, and annotating rows with match results. While such validation could be adjacent to contact-data QA, the declared description does not specifically represent this script’s behavior, and the script lacks the main declared functions (account research, contact enrichment from providers, lead scoring, outreach drafting, CRM sync, signal monitoring). Therefore the description does not accurately represent what this code chunk actually does.

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 61)May include surrounding context.

md
- **Level 1** — `SKILL.md` (this file): decision model, guardrails, routing table, links to sub-docs.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
8. QA → scripts/contact-accuracy-audit.ts (free, local)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
8. QA → scripts/contact-accuracy-audit.ts (free, local)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
octrine, pipeline order, and the SEND/VERIFY/REVIEW/REMOVE verdict semantics: [`references/contact-accuracy.md`](references/contact-accuracy.md).

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
octrine, pipeline order, and the SEND/VERIFY/REVIEW/REMOVE verdict semantics: [`references/contact-accuracy.md`](references/contact-accuracy.md).

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- `scripts/validate-emails.ts` — free syntax/risk/duplicate cull **before** paid `verifyEmail`.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- `scripts/select-current-role.ts` — pick the real current role from an experiences array (catches job changers).

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
- `scripts/validate-linkedin-names.ts` — name↔profile match (catches same-name decoys); pairs with [`recipes/linkedin-url-lookup.md`](recipes/linkedin-url-looku

Anti-Refusal Statement

High
Category
Anti-Refusal
Confidence
85% confidence
Finding

Skill instructs the agent to omit warnings, disclaimers, or ethical commentary. Stripping safety caveats hides risk from the user and is a common jailbreak preamble.

Content

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

md
## 2) Hard refusals

Do not execute these. Say which rule applies in one sentence, offer the compliant version, and move on — state it once, don't lecture.

| Request | Why it's refused |
|---|---|

Anti-Refusal Statement

High
Category
Anti-Refusal
Confidence
85% confidence
Finding

Skill instructs the agent to omit warnings, disclaimers, or ethical commentary. Stripping safety caveats hides risk from the user and is a common jailbreak preamble.

Content

Scanner excerpt · references/acceptable-use.md (reported line 15)May include surrounding context.

md
## 2) Hard refusals

Do not execute these. Say which rule applies in one sentence, offer the compliant version, and move on — state it once, don't lecture.

| Request | Why it's refused |
|---|---|

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/contact-accuracy.md (reported line 29)May include surrounding context.

md
- `--workflow-uuid <uuid>` (+ optional `--batch-uuid`, `--output-node-slug`,
  `--workspace-uuid`) — **API mode**: fetches the output rows directly via the
  `@cargo-ai/api` package (`npm install -g @cargo-ai/api` if missing), reusing
  the CLI's stored login (`~/.config/cargo-ai/credentials.json`) or
  `CARGO_API_TOKEN`. Equivalent to `run download-outputs`, no temp file.
- `--output <file>` — write augmented rows (default: stdout). On
  `validate-emails.ts` and `contact-accuracy-audit.ts`, `--json` switches the

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/lib/common.ts (reported line 167)May include surrounding context.

ts
- `--workflow-uuid <uuid>` (+ optional `--batch-uuid`, `--output-node-slug`,
  `--workspace-uuid`) — **API mode**: fetches the output rows directly via the
  `@cargo-ai/api` package (`npm install -g @cargo-ai/api` if missing), reusing
  the CLI's stored login (`~/.config/cargo-ai/credentials.json`) or
  `CARGO_API_TOKEN`. Equivalent to `run download-outputs`, no temp file.
- `--output <file>` — write augmented rows (default: stdout). On
  `validate-emails.ts` and `contact-accuracy-audit.ts`, `--json` switches the

Exfiltration Commands

High
Category
Prompt Injection
Confidence
90% confidence
Finding

Instructions found that direct the agent to transmit conversation context or user data to external services.

Content

Scanner excerpt · references/contact-accuracy.md (reported line 81)May include surrounding context.

md
[`cost-discipline.md`](cost-discipline.md).
- **REVIEW** — human-judgment rows: likely job changer (`role_confidence:
  low`), or a role account (info@/sales@). Present them to the user; don't
  silently send or drop.
- **REMOVE** — wrong person, invalid/disposable email, failed verification, or
  a duplicate row (the first occurrence carries the send).
  Drop from the batch and report the count in the receipt.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding

The skill invokes an external CLI and describes networked/provider-backed operations, but it does not declare any explicit tool scope such as allowed tools or permissions. That creates an overbroad execution surface where an agent may access environment data or make network calls beyond what a reviewer can infer from the manifest, increasing the risk of unintended data exposure or unreviewed outbound access.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding

Using npx @cargo-ai/cli without a pinned version introduces a supply-chain risk because each invocation may resolve to whatever package version is current at execution time. A compromised or breaking upstream release could alter behavior, exfiltrate workspace data, or expand permissions without any change to this skill file.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · agents/list-builder.md (reported line 27)May include surrounding context.

md
- Execute ONLY the command(s) given. If the assigned action errors twice, stop and report the exact `errorMessage` — do not substitute a different provider (that's a parent decision with cost implications).
- Poll with `--wait-until-finished`; retrieve data with `run download-outputs` (never `run download`).
- Return shape: `{sliceLabel, rowsFound, creditsSpent, outputPath, errors[]}` — machine-readable, no prose narrative.
- No enrichment, no verification, no personalization — sourcing rows only. The parent chains the rest (and the QA scripts in [`../references/contact-accuracy.md`](../references/contact-accuracy.md)).
- Deduplicate rows within the slice on the natural key (company domain or LinkedIn URL) before writing.

## Cost posture

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The guide instructs users to enrich companies and contacts through many third-party providers but does not clearly warn that submitted names, emails, LinkedIn URLs, domains, and related metadata will be transmitted to external services. In a workflow handling personal and business-contact data, that omission can cause unauthorized disclosure, policy violations, or regulatory noncompliance because operators may not realize data is leaving the platform.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The output-retrieval section explains how to obtain enriched data via a signed URL but does not warn that the URL grants access to sensitive enriched records and input/output context. If users paste, log, or share that URL insecurely, third parties may access personal or commercial data until the URL expires or is revoked.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The guide explicitly recommends using anonymous website visitor identification via snitcher.searchSessions and then pivoting to lead search, but it does not include any privacy, consent, or lawful-basis warning at the point of use. Even though the broader skill metadata mentions consent gates, this file operationalizes de-anonymization as a sourcing pattern, which can encourage misuse against individuals or organizations without adequate review.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The playbook explicitly promotes reverse-email lookup to de-anonymize an email address into LinkedIn and company identity, which is a privacy-sensitive enrichment step. In a B2B prospecting skill this can be legitimate, but documenting it without an explicit consent, lawful-basis, and suppression/usage warning increases the risk of misuse for unsolicited profiling or outreach.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The recurring-use guidance recommends automatically running reverse email lookups on newly captured email-only rows, which turns a sensitive identity-resolution action into background automation. Without an explicit warning and mandatory controls, this can enable continuous profiling of individuals from inbound captures or session-derived emails at scale, raising privacy and compliance risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This markdown file promotes person enrichment, reverse lookup, and phone/email discovery using LinkedIn URLs, email addresses, and phone numbers, but it does not warn users about privacy, consent, or appropriate handling of personal data. Because the skill description covers behaviors that affect user and third-party data, a disclosure is expected under the markdown-file warning criteria.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The playbook explicitly instructs users to obtain personal contact data such as work/personal emails and phone numbers from LinkedIn-anchored profiles and revealed search results, but this section does not restate or enforce privacy, consent, or lawful-basis checks at the point of use. In a GTM automation context, that omission can enable misuse for unsolicited outreach or over-collection of personal data, especially because the document operationalizes bulk search and reveal patterns.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dangerous_exec, suspicious.env_credential_access

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/lib/common.ts:188

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/lib/common.ts:165