T09 · Insecure Skill Coding Practices
- Location
scripts/saleshandy-import.py:9- Finding
API Keys Exposed Through Command-Line Process Arguments
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill is a coherent cold-outreach automation tool, but it handles prospect personal data, live outreach systems, and API credentials with too little user-facing control and safety guidance.
Install only if you are prepared to supervise it closely. Use least-privileged Apollo and Saleshandy keys, avoid putting real keys on command lines or in workspace config files, keep generated CSVs out of version control, and require manual approval before importing prospects, activating sequences, or sending any campaign. Also verify that your lead sourcing, enrichment, personalization, unsubscribe handling, and cold-email sending comply with applicable privacy and marketing rules.
scripts/saleshandy-import.py:9API Keys Exposed Through Command-Line Process Arguments
references/config-template.json:1Documentation Encourages Plaintext API Key Storage in the Workspace
The skill instructs the agent to use environment variables, shell commands, and write CSV/config files, but it does not declare any explicit tool scope or permissions boundaries. That creates an unsafe mismatch where an agent may execute sensitive operations without clear user-visible authorization or least-privilege constraints.
The skill processes personal data for lead generation and email enrichment, then imports that data into third-party outreach platforms, but it does not clearly warn users that these are privacy-sensitive actions. This can lead to accidental collection, transfer, and processing of personal information without informed consent, policy review, or jurisdiction-specific compliance checks.
The skill is designed for fully automated cold outreach and sequence management, yet it does not prominently warn that activating sequences can send bulk cold email and damage sender reputation, domain health, or account standing. In this context, the lack of warning increases the chance of unintended mass messaging and operational harm to business email infrastructure.
The reference explicitly documents retrieving a person's direct email address via enrichment, but provides no privacy, consent, lawful-basis, or data-handling guidance. In a cold-outreach skill, that omission materially increases the risk that users or downstream agents will collect and process personal data in ways that violate policy, expectations, or applicable regulations.
Unlike the generic search endpoint, this endpoint is specifically documented as returning a full person object including email, which is personal contact data transmitted from a third party. In the context of a cold-outreach skill, documenting this transmission without any privacy, consent, or handling constraints makes misuse more likely and elevates the risk beyond a generic external call.
POST https://api.apollo.io/api/v1/people/match
Body: {"id": "apollo_person_id"}
The bulk enrichment endpoint facilitates larger-scale transmission and retrieval of identifiable prospect data to a third party, increasing privacy and abuse risk through volume. In a cold-outreach workflow, bulk processing amplifies the chance of unauthorized harvesting or mass contact preparation if no safeguards or compliance notes are provided.
POST https://api.apollo.io/api/v1/people/bulk_match
Body: {"details": [{"first_name": "X", "last_name": "Y", "organization_name": "Z"}]}
The documented prospect import, email-account assignment, and sequence activation endpoints can modify external outreach systems and trigger real customer-facing sends, yet the file contains no warning about confirmation, authorization, or operational safeguards. In an agentic context, this can lead to accidental spam campaigns, unauthorized contact of prospects, or unintended changes to production sequences.
The template normalizes collecting, researching, and using prospect and company data for outreach without any guidance on lawful basis, consent, notice, or regional compliance requirements. In a cold-outreach automation skill, that omission increases the risk of privacy-law violations, unlawful profiling, and non-compliant email marketing at scale.
The writing rule instructing operators to use real client names and exact results without any qualifier encourages disclosure of potentially confidential commercial information and testimonials without documented permission. In sales outreach, this can misappropriate client data, breach NDAs or confidentiality obligations, and create deceptive-marketing or endorsement risks if claims are not authorized and substantiated.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
APOLLO_KEY = os.environ.get('APOLLO_API_KEY', '')
def enrich_by_id(person_id):
r = subprocess.run([
'curl', '-s', '-X', 'POST',
'https://api.apollo.io/api/v1/people/match',
'-H', f'X-Api-Key: {APOLLO_KEY}',
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.
APOLLO_KEY = os.environ.get('APOLLO_API_KEY', '')
def enrich_by_id(person_id):
r = subprocess.run([
'curl', '-s', '-X', 'POST',
'https://api.apollo.io/api/v1/people/match',
'-H', f'X-Api-Key: {APOLLO_KEY}',
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
def enrich_by_id(person_id):
r = subprocess.run([
'curl', '-s', '-X', 'POST',
'https://api.apollo.io/api/v1/people/match',
'-H', f'X-Api-Key: {APOLLO_KEY}',
'-H', 'Content-Type: application/json',
'-d', json.dumps({'id': person_id})
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
def enrich_by_id(person_id):
r = subprocess.run([
'curl', '-s', '-X', 'POST',
'https://api.apollo.io/api/v1/people/match',
'-H', f'X-Api-Key: {APOLLO_KEY}',
'-H', 'Content-Type: application/json',
'-d', json.dumps({'id': person_id})
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
def enrich_by_id(person_id):
r = subprocess.run([
'curl', '-s', '-X', 'POST',
'https://api.apollo.io/api/v1/people/match',
'-H', f'X-Api-Key: {APOLLO_KEY}',
'-H', 'Content-Type: application/json',
'-d', json.dumps({'id': person_id})
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
"per_page": per_page,
"page": page
}
r = subprocess.run([
'curl', '-s', '-X', 'POST',
'https://api.apollo.io/api/v1/mixed_people/api_search',
'-H', f'X-Api-Key: {APOLLO_KEY}',
The subprocess call invokes curl to send user-supplied search criteria and the Apollo API key to api.apollo.io. Although external API use is part of the script's purpose, the file lacks a visible disclosure in help text, comments, or runtime output that the command sends this data to a third-party service.
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.
"per_page": per_page,
"page": page
}
r = subprocess.run([
'curl', '-s', '-X', 'POST',
'https://api.apollo.io/api/v1/mixed_people/api_search',
'-H', f'X-Api-Key: {APOLLO_KEY}',
The script writes lead data to a local CSV by default without clear consent, sensitivity labeling, or storage safeguards. In a cold-outreach skill, this can expose personal/business contact data to unintended local users, backups, or downstream automation, creating privacy and compliance risk.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
print("Set SALESHANDY_API_KEY or use --api-key", file=sys.stderr)
sys.exit(1)
r = subprocess.run([
'curl', '-s', '-X', 'POST', f'{BASE}/v1/email-accounts',
'-H', f'x-api-key: {SH_API_KEY}',
'-H', 'Accept: application/json',
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.
print("Set SALESHANDY_API_KEY or use --api-key", file=sys.stderr)
sys.exit(1)
r = subprocess.run([
'curl', '-s', '-X', 'POST', f'{BASE}/v1/email-accounts',
'-H', f'x-api-key: {SH_API_KEY}',
'-H', 'Accept: application/json',
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
'-H', f'x-api-key: {SH_API_KEY}', '-H', 'Accept: application/json']
if data:
cmd += ['-H', 'Content-Type: application/json', '-d', json.dumps(data)]
r = subprocess.run(cmd, capture_output=True, text=True)
return json.loads(r.stdout)
def list_sequences():
Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.
'-H', f'x-api-key: {SH_API_KEY}', '-H', 'Accept: application/json']
if data:
cmd += ['-H', 'Content-Type: application/json', '-d', json.dumps(data)]
r = subprocess.run(cmd, capture_output=True, text=True)
return json.loads(r.stdout)
def list_sequences():
This Python code accesses a sensitive credential via SALESHANDY_API_KEY and sends it as an HTTP header using curl. While the script's purpose implies checking Saleshandy status, there is no explicit user-facing warning, comment, or log noting that a credential will be used and sent to an external service.
No suspicious patterns detected.