Back to skill

Security audit

Lead Enricher - Explorium AgentSource

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a legitimate Explorium prospecting integration, but it handles API keys and contact/prospect data in ways that need review before installation.

Review before installing. Use only on a private machine/account, avoid entering the API key in recorded or shared terminals, consider rotating the key if it was exposed in scrollback, and avoid processing regulated or sensitive contact lists until result files are stored in a private 0600 directory instead of predictable /tmp paths.

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
bin/agentsource.py:115
Finding
Predictable and Insecure Temporary Files Expose Sensitive Prospect Data<![CDATA[ ## Vulnerability Details **File Location**: `bin/agentsource.py:37, 115-123` **Vulnerability Type**: Predictable temporary files, unsafe file creation, and insufficient access controls **Risk Level**: High ### Vulnerable Code ```python TEMP_DIR = pathlib.Path("/tmp") ``` ```python def make_temp_path(command: str) -> pathlib.Path: ts = int(time.time()) return TEMP_DIR / f"agentsource_{ts}_{command}.json" def write_result(command: str, data: dict) -> pathlib.Path: path = make_temp_path(command) path.write_text(json.dumps(data, indent=2, default=str)) print(str(path)) return path ``` ### Technical Analysis The CLI stores imported CSV records and API results directly under the shared `/tmp` directory. Filenames contain only the current timestamp with one-second resolution and the command name, making them predictable. `Path.write_text()` does not provide exclusive file creation and follows an existing symbolic link. The code also does not explicitly set result files to mode `0600`; their permissions depend on the process umask and may commonly become `0644`. These files can contain sensitive B2B and personal information, including: - Names and employer information - Professional or personal email addresses - Phone numbers - LinkedIn profiles - Imported user CSV records - Enrichment and event results The implementation does not create a private per-user temporary directory, use cryptographically random filenames, prevent symbolic-link traversal, enforce restrictive permissions, or implement explicit cleanup. ### Attack Path 1. A local attacker monitors or predicts when the victim will run a CLI command. 2. The attacker derives a likely filename such as `/tmp/agentsource_<timestamp>_fetch.json`. 3. The attacker either: - Waits for the result to be created and reads it if its permissions allow access; or - Pre-creates that path as a symbolic link to another file writable by the victim. 4. The victim executes the Agen ...[truncated 971 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace timestamp-based paths with secure, exclusive temporary-file creation: ```python import os import tempfile fd, path_str = tempfile.mkstemp( prefix=f"agentsource_{command}_", suffix=".json", dir=private_temp_dir, text=True, ) try: os.fchmod(fd, 0o600) with os.fdopen(fd, "w", encoding="utf-8") as output: json.dump(data, output, indent=2, default=str) except Exception: os.close(fd) raise ``` 2. Create a per-user temporary directory with mode `0700` instead of writing directly into shared `/tmp`. 3. Ensure all result files are explicitly mode `0600`, independent of the process umask. 4. Use exclusive creation and never reopen a predictable path in a way that follows pre-existing symbolic links. 5. Add an explicit retention policy and cleanup command. Do not rely solely on unspecified operating-system cleanup. 6. Consider allowing users to select a protected output directory when processing regulated or highly sensitive contact information. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
setup.sh:81
Finding
API Key Is Echoed and Exposed Through Terminal and Command-Line Handling<![CDATA[ ## Vulnerability Details **File Location**: `setup.sh:81-89` **Vulnerability Type**: Insecure credential input and disclosure **Risk Level**: Medium ### Vulnerable Code ```bash read -r -p "Enter your Explorium API key (or press Enter to skip): " api_key if [ -n "${api_key:-}" ]; then printf '{\n "api_key": "%s"\n}\n' \ "$api_key" > "$CONFIG_FILE" chmod 600 "$CONFIG_FILE" echo "[OK] API key saved to $CONFIG_FILE (mode 600, owner read-only)" echo "" echo "To also set it as an environment variable, add this to ~/.zshrc or ~/.bashrc:" echo " export EXPLORIUM_API_KEY='$api_key'" ``` Related documentation also recommends passing the secret as a command-line argument: ```bash python3 ~/.agentsource/bin/agentsource.py config --api-key your_api_key_here ``` ### Technical Analysis The setup prompt uses `read -r` without the `-s` option, so the API key remains visible while the user types it. After saving the key, the script prints the complete secret back to the terminal as part of an example environment-variable command. The documented `config --api-key` mechanism also places the secret in process arguments. Depending on the operating system and shell configuration, command-line secrets may be exposed through: - Shell history - Process inspection tools - Terminal scrollback - Session recordings - CI logs - Support transcripts or copied terminal output Although the resulting configuration file is changed to mode `0600`, those file permissions do not mitigate disclosure before or during credential entry. ### Attack Path 1. A user runs `setup.sh` and chooses to enter an API key. 2. The key is visibly echoed while being typed because silent input is not enabled. 3. The script subsequently prints the entire key in an `export EXPLORIUM_API_KEY='...'` command. 4. A nearby observer, terminal recorder, log collector, or person with access to terminal scrollback obtains the key. Alternatively: 1. The user follows the documen ...[truncated 728 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Read interactive secrets without terminal echo: ```bash read -r -s -p "Enter your Explorium API key (or press Enter to skip): " api_key echo ``` 2. Never print the API key back to the terminal. Replace the generated command with a generic placeholder. 3. Avoid accepting secrets through command-line arguments. Support protected standard input instead, for example: ```bash read -r -s EXPLORIUM_API_KEY printf '%s' "$EXPLORIUM_API_KEY" | agentsource config --api-key-stdin ``` 4. Preserve mode `0600` for the configuration file and create it atomically with restrictive permissions from the outset, rather than changing permissions only after writing. 5. Update `README.md` and `SKILL.md` to recommend non-echoing, history-safe credential setup. 6. Advise users who followed the existing setup flow in logged or shared terminals to rotate their API keys. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (19)

Session Persistence

Medium
Category
Rogue Agent
Content
**Option A — Environment variable** (recommended for persistent shell setups):
```bash
export EXPLORIUM_API_KEY=your_api_key_here
# Add to ~/.zshrc or ~/.bashrc to persist across sessions
```

**Option B — CLI config command** (saves to `~/.agentsource/config.json`, mode 600):
Confidence
90% 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
**Option A — Environment variable** (recommended for persistent shell setups):
```bash
export EXPLORIUM_API_KEY=your_api_key_here
# Add to ~/.zshrc or ~/.bashrc to persist across sessions
```

**Option B — CLI config command** (saves to `~/.agentsource/config.json`, mode 600):
Confidence
90% 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
## CLI Reference

All commands write results to `/tmp/agentsource_<timestamp>_<command>.json` and print only the file path to stdout.

### API Key Config
```bash
Confidence
83% confidence
Finding
The README states that all command results are written to predictable files under /tmp, which commonly stores data in a shared, globally accessible location on multi-user systems. Because the tool handles prospect, company, enrichment, and matching data, this can expose sensitive business or personal data to other local users, backup agents, or malicious processes if file creation and permissions are not tightly controlled.

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill performs shell execution, reads environment variables, writes files, and sends data over the network, but it does not declare any explicit tool scope or permission boundaries. This increases the blast radius because a host agent may grant broader capabilities than users expect, including access to local files and secrets such as API keys.

Intent-Code Divergence

Medium
Confidence
97% confidence
Finding
The top-level docstring states that all results are written to temporary files in /tmp and only the temp-file path is printed, but the code later provides a command that writes directly to an arbitrary output path. This is a security-relevant documentation integrity issue because operators or higher-level agents may rely on the stated storage model when handling prospect and company data.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
Result and error payloads are written to predictable filenames in /tmp based only on timestamp and command name, with no secure temporary-file creation or permission hardening. In multi-user or hostile local environments, other users or processes may guess, pre-create, read, or race these files, exposing API responses, errors, and potentially sensitive lead or company data.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The module-level documentation promises that results are written only to temporary files under /tmp, but the to-csv command writes fetched or enriched data to an arbitrary caller-specified path. In a B2B prospecting skill, outputs can contain sensitive business and contact data, so this mismatch can cause unanticipated persistent local storage outside the temporary area and weaken data-handling expectations for downstream agents or users.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The to-csv command exports fetched or enriched API data to any output path specified by the caller without an explicit warning that the data will be persistently stored locally. Because this skill is designed for prospecting and contact enrichment, exported CSVs may contain sensitive personal and commercial intelligence that can remain on disk, be backed up, or be read by other local processes or users depending on path and permissions.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The skill explicitly documents enrichment options that return professional email, personal email, direct phone, and mobile phone for prospects, but provides no privacy, consent, or permissible-use guardrails. In a B2B lead-generation skill, this materially increases the risk of misuse for unsolicited outreach, privacy violations, or collection of personal contact data without an appropriate legal basis.

External Transmission

Medium
Category
Data Exfiltration
Content
#   ~/.agentsource/config.json          — API key storage (mode 600, only if you choose to save it)
#
# Nothing is sent to any network during setup. The API key is only used when
# you run CLI commands that call https://api.explorium.ai/v1/.

PLUGIN_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
INSTALL_DIR="$HOME/.agentsource"
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
#   ~/.agentsource/config.json          — API key storage (mode 600, only if you choose to save it)
#
# Nothing is sent to any network during setup. The API key is only used when
# you run CLI commands that call https://api.explorium.ai/v1/.

PLUGIN_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
INSTALL_DIR="$HOME/.agentsource"
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
#   ~/.agentsource/config.json          — API key storage (mode 600, only if you choose to save it)
#
# Nothing is sent to any network during setup. The API key is only used when
# you run CLI commands that call https://api.explorium.ai/v1/.

PLUGIN_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
INSTALL_DIR="$HOME/.agentsource"
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
#   ~/.agentsource/config.json          — API key storage (mode 600, only if you choose to save it)
#
# Nothing is sent to any network during setup. The API key is only used when
# you run CLI commands that call https://api.explorium.ai/v1/.

PLUGIN_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
INSTALL_DIR="$HOME/.agentsource"
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
#   ~/.agentsource/config.json          — API key storage (mode 600, only if you choose to save it)
#
# Nothing is sent to any network during setup. The API key is only used when
# you run CLI commands that call https://api.explorium.ai/v1/.

PLUGIN_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
INSTALL_DIR="$HOME/.agentsource"
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
#   ~/.agentsource/config.json          — API key storage (mode 600, only if you choose to save it)
#
# Nothing is sent to any network during setup. The API key is only used when
# you run CLI commands that call https://api.explorium.ai/v1/.

PLUGIN_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
INSTALL_DIR="$HOME/.agentsource"
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Session Persistence

Medium
Category
Rogue Agent
Content
echo "[OK] Python $PYTHON_VERSION"

# ---------------------------------------------------------------------------
# 2. Create directory structure
# ---------------------------------------------------------------------------
mkdir -p "$BIN_DIR"
echo "[OK] Created $BIN_DIR"
Confidence
60% 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.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
if [[ "${save_key:-}" =~ ^[Yy]$ ]]; then
        printf '{\n  "api_key": "%s"\n}\n' \
            "$EXPLORIUM_API_KEY" > "$CONFIG_FILE"
        chmod 600 "$CONFIG_FILE"
        echo "[OK] API key saved to $CONFIG_FILE (mode 600, owner read-only)"
    fi
else
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
if [[ "${save_key:-}" =~ ^[Yy]$ ]]; then
        printf '{\n  "api_key": "%s"\n}\n' \
            "$EXPLORIUM_API_KEY" > "$CONFIG_FILE"
        chmod 600 "$CONFIG_FILE"
        echo "[OK] API key saved to $CONFIG_FILE (mode 600, owner read-only)"
    fi
else
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The script prints a ready-to-paste export command that embeds the user's API key in cleartext. This exposes the secret on screen, in terminal scrollback, screen recordings, and potentially shell history if copied and executed, increasing the chance of credential leakage.

Static analysis

No suspicious patterns detected.