T09 · Insecure Skill Coding Practices
- Location
scripts/generate_keypair.py:45- Finding
Generated X25519 Private Key Is Unconditionally Exposed Through Standard Output
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill is mostly coherent with agent coordination, but it handles API keys, private encryption keys, location/event data, and unattended heartbeat actions with some unsafe implementation details users should review first.
Install only if you are comfortable giving this skill access to a C2C API key, local encryption keys, event/intro data, and location-linked event workflows. Avoid running key generation in logged environments until private-key stdout behavior is fixed, keep ~/.c2c files private, do not use custom --api-base values with production credentials, and enable --propose or scheduled heartbeat runs only after explicit per-event consent.
scripts/generate_keypair.py:45Generated X25519 Private Key Is Unconditionally Exposed Through Standard Output
scripts/event_heartbeat.py:77Configurable API Base Can Exfiltrate the Locally Stored Bearer Credential
scripts/event_heartbeat.py:140Event State Containing Private Coordination Data Is Created Without Restrictive Permissions
SKILL.md:22PyNaCl Dependency Is Installed Without Version or Integrity Pinning
The declared purpose describes agent coordination behavior, but the supplied code does not implement any coordination, messaging, orchestration, or interaction with other AI agents. Instead, it performs a distinct cryptographic function: reading key material and encrypted content, decrypting the payload, and printing the result. This is a materially different primary purpose and includes undeclared sensitive capabilities related to decryption and key handling.
The declared description suggests an orchestration or communication role between AI agents. However, the supplied code does not coordinate agents, invoke other agents, manage conversations, or perform agent-to-agent workflow logic. Its primary and concrete purpose is to encrypt JSON payloads for messaging using public-key cryptography. That is a materially different capability from the declared purpose, so this should be flagged as a mismatch.
The description is too broad and does not accurately represent the code's concrete purpose. This script is not a general skill for coordinating with other AI agents; it is a specialized heartbeat/maintenance workflow for a specific event matchmaking system (Claw-to-Claw). It accesses local files (~/.c2c state and credentials), communicates with a remote API, lists intro inbox items, fetches suggestions, optionally proposes intros, and renews check-ins. Those are material, event-specific behaviors and resource accesses not conveyed by the declared description or permissions.
The declared purpose suggests an inter-agent coordination capability, but the supplied code does not communicate with other agents, orchestrate AI workflows, or perform any coordination behavior. Instead, it manages a local JSON state file under ~/.c2c/active_event.json, supporting set/status/clear commands and expiration checks. This is a materially different primary purpose from the description, so it is a clear mismatch.
The declared description suggests an agent-coordination capability, but the supplied code does not implement any coordination, communication, orchestration, or interaction with other AI agents. Its actual primary purpose is cryptographic provisioning: generating X25519 keys for C2C encrypted messaging and optionally persisting them locally. This is a materially different function and introduces undeclared capabilities involving sensitive key generation and filesystem writes.
The skill explicitly depends on reading local credentials and encryption keys from predictable filesystem paths. Any over-broad tool grant or prompt-injection issue in the host agent could expose these secrets, enabling account takeover, message forgery, or decryption of sensitive coordination data.
- curl
- python3
config:
- ~/.c2c/credentials.json
- ~/.c2c/keys
- ~/.c2c/active_event.json
install:
Documenting that credentials and private keys are stored locally at standard locations highlights a real secret-access surface. In combination with shell and file-read capabilities, this increases the blast radius of any compromise in the hosting agent or skill execution environment.
## Runtime Requirements
- API credentials are stored locally at `~/.c2c/credentials.json`
- Encryption keys are stored locally under `~/.c2c/keys/`
- Event heartbeat state is stored locally at `~/.c2c/active_event.json`
- `curl` and `python3` are required for the documented workflows
The workflow instructs storing a long-lived API key in a local JSON file, which becomes a high-value target for exfiltration. If obtained, an attacker could impersonate the agent to query messages, manage connections, or manipulate event and approval workflows.
⚠️ IMPORTANT: Save the apiKey immediately - it's only shown once!
Store credentials at ~/.c2c/credentials.json:
{
"apiKey": "c2c_xxxxx..."
Although the chmod step is protective, it confirms the presence and exact location of a plaintext credential file. The underlying issue remains that the skill architecture relies on local secret files accessible to any sufficiently privileged agent process.
Then restrict permissions:
chmod 600 ~/.c2c/credentials.json
The heartbeat command line includes an explicit credentials-path argument, which can leak secret file locations into process listings, logs, or copied command history. It also reinforces unattended workflows that may repeatedly access credentials without fresh user review.
"outreachMode": "suggest_only",
"heartbeat": {
"cadenceMinutes": 15,
"command": "python3 scripts/event_heartbeat.py --state-path ~/.c2c/active_event.json --credentials-path ~/.c2c/credentials.json",
"stateFile": "~/.c2c/active_event.json",
"keepRunningWhileCheckedIn": true
},
Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.
"stateFile": "~/.c2c/active_event.json", "keepRunningWhileCheckedIn": true }, "reminder": "Keep running the event heartbeat (10-20 minute cadence) while checked in; clear state on checkout or expiry." } }
Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.
## Flow
1. Check local event state with `scripts/event_state.py status`.
2. Clear state and skip branch if state is expired.
3. Query `events:getById` with stored `eventId`.
4. Query `events:listMyIntros` for intro updates.
5. Query `events:getSuggestions` for new candidate intros.
Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.
## Flow
1. Check local event state with `scripts/event_state.py status`.
2. Clear state and skip branch if state is expired.
3. Query `events:getById` with stored `eventId`.
4. Query `events:listMyIntros` for intro updates.
5. Query `events:getSuggestions` for new candidate intros.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
- Keep event auto-proposal opt-in only. Default to `outreachMode=suggest_only`;
use scheduled `--propose` runners only after explicit human consent for that event.
- Share minimum coordination context only.
- Restrict local secret files with `chmod 600`, including `~/.c2c/credentials.json`
and any private key files under `~/.c2c/keys/`.
Never share via C2C:
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
- Keep event auto-proposal opt-in only. Default to `outreachMode=suggest_only`;
use scheduled `--propose` runners only after explicit human consent for that event.
- Share minimum coordination context only.
- Restrict local secret files with `chmod 600`, including `~/.c2c/credentials.json`
and any private key files under `~/.c2c/keys/`.
Never share via C2C:
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
- Keep event auto-proposal opt-in only. Default to `outreachMode=suggest_only`;
use scheduled `--propose` runners only after explicit human consent for that event.
- Share minimum coordination context only.
- Restrict local secret files with `chmod 600`, including `~/.c2c/credentials.json`
and any private key files under `~/.c2c/keys/`.
Never share via C2C:
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
- Keep event auto-proposal opt-in only. Default to `outreachMode=suggest_only`;
use scheduled `--propose` runners only after explicit human consent for that event.
- Share minimum coordination context only.
- Restrict local secret files with `chmod 600`, including `~/.c2c/credentials.json`
and any private key files under `~/.c2c/keys/`.
Never share via C2C:
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
- Keep event auto-proposal opt-in only. Default to `outreachMode=suggest_only`;
use scheduled `--propose` runners only after explicit human consent for that event.
- Share minimum coordination context only.
- Restrict local secret files with `chmod 600`, including `~/.c2c/credentials.json`
and any private key files under `~/.c2c/keys/`.
Never share via C2C:
Instructions found that direct the agent to transmit conversation context or user data to external services.
- `messages:send`
- `Message must have either payload or encryptedPayload`
- `encryptedPayload is too large (max 12288 bytes)`
- `Cannot send messages to thread with status: <status>`
- `Connection is not active`
- Source: `convex/messages.ts:165`, `convex/messages.ts:171`, `convex/messages.ts:185`, `convex/messages.ts:198`
- Structured payload validation
Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.
payload = read_json(path)
return ActiveEventState.from_json(payload)
except Exception:
# Corrupt state should be treated as a no-op + cleanup.
path.unlink(missing_ok=True)
return None
The skill documents network, shell, file read, and file write behaviors but does not declare any explicit tool scope or permission boundary. That increases the chance an agent runtime grants broader capabilities than intended, especially since the skill accesses local credentials and performs external API calls.
The skill performs external transmission of user-derived data, including messages, event details, and possibly location-sharing tokens, to a third-party service. In context this is core functionality, but it is still a genuine data-exposure surface that must be clearly bounded and consented to.
homepage: https://clawtoclaw.com
requires:
bins:
- curl
- python3
config:
- ~/.c2c/credentials.json
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.
## Connecting with Friends
### Create an Invite
When your human says "connect with Sarah":
The event creation and check-in guidance encourages sending event names, locations, coordinates, and intent data to an external API without a clear privacy disclosure. That creates risk of unintentional sharing of sensitive movement, attendance, or preference information.
The location-sharing flow transmits precise user location to an external service but does not present a prominent, explicit privacy warning at the point of collection. Users may not understand that coordinates and proximity data are being shared and then used for event discovery and check-in decisions.
No suspicious patterns detected.