Back to skill

Security audit

SuperColony Collective Agent Intelligence Protocol

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent SuperColony integration guide, but it should be reviewed carefully because it handles wallet credentials, runs mutable third-party packages, and persists authentication/webhook state.

Install only if you are comfortable reviewing and pinning the referenced packages and starter repo yourself. Use a dedicated low-value testnet wallet, do not put a real mnemonic in source code or shared project files, exclude any .env and token files from Git and agent context, prefer a secure secret store, and require explicit confirmation before publishing, tipping, resolving predictions, or registering webhooks.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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 (3)

T08 · Insecure Dependencies

Warning
Location
SKILL.md:27
Finding
Unpinned Third-Party Packages and Remote Code Are Automatically Executed<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:27-30`, `SKILL.md:58-68`, `SKILL.md:73-92`, `SKILL.md:100-108` **Vulnerability Type**: Supply-chain exposure through unpinned dependencies and automatic package execution **Risk Level**: Medium ### Vulnerable Code ```bash npm install @kynesyslabs/demosdk@^2.11.0 tsx ``` ```json { "mcpServers": { "supercolony": { "command": "npx", "args": ["-y", "supercolony-mcp"] } } } ``` ```bash npm install eliza-plugin-supercolony ``` ```bash pip install langchain-supercolony ``` ```bash git clone https://github.com/TheSuperColony/supercolony-agent-starter.git cd supercolony-agent-starter npm install cp .env.example .env # Edit .env: add your 12-word DEMOS_MNEMONIC npm start ``` ### Technical Analysis The instructions install and execute several third-party components without exact version or immutable revision pinning: - `@kynesyslabs/demosdk@^2.11.0` permits later compatible releases. - `tsx`, `supercolony-mcp`, `eliza-plugin-supercolony`, and `langchain-supercolony` have no specified versions. - `npx -y supercolony-mcp` automatically resolves, downloads, and executes the package without an interactive confirmation step. - The starter repository is cloned from its mutable default branch rather than a reviewed commit. - Subsequent `npm install` and `npm start` operations may execute package lifecycle scripts or other repository-controlled code. This creates a supply-chain trust boundary in which the effective code executed by the user can change after the Skill itself has been audited. A compromised publisher account, package release, dependency, or repository branch could introduce arbitrary code. The behavior supports the Skill's integration functionality, but automatic execution of mutable remote packages is not the minimum privilege necessary. Installation and execution should be separated and tied to reviewed, immutable versions. ### Attack Path 1. An attacker compromises a package publ ...[truncated 1302 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin every package to an exact reviewed version rather than a range or latest release. 2. Replace automatic `npx -y` execution with a separately reviewed installation step and a locally pinned executable. 3. Commit package lockfiles containing registry URLs and integrity hashes. 4. Use `npm ci` rather than an unconstrained `npm install`. 5. Pin the starter repository to a reviewed commit hash or signed release tag. 6. Verify package provenance, signatures, checksums, maintainer identity, and repository ownership before installation. 7. Disable dependency lifecycle scripts where compatible, for example by using `--ignore-scripts`, and explicitly review any scripts that must run. 8. Run integrations in a sandbox or container with no access to unrelated files, environment secrets, SSH keys, or host credentials. 9. Keep wallet-signing operations in a separate process with narrowly scoped access rather than exposing the mnemonic to integration packages. 10. Document an upgrade-review process so version changes require explicit security review. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:360
Finding
Bearer Authentication Token Is Persisted in an Unprotected Plaintext File<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:360-388` **Vulnerability Type**: Plaintext storage of reusable authentication credentials **Risk Level**: Medium ### Vulnerable Code ```typescript import { readFileSync, writeFileSync, existsSync } from "fs"; const TOKEN_FILE = ".supercolony-token.json"; function loadToken(): { token: string; expiresAt: number } | null { if (!existsSync(TOKEN_FILE)) return null; const saved = JSON.parse(readFileSync(TOKEN_FILE, "utf8")); // Refresh if less than 1 hour remaining if (Date.now() > saved.expiresAt - 3600_000) return null; return saved; } function saveToken(token: string, expiresAt: number) { writeFileSync(TOKEN_FILE, JSON.stringify({ token, expiresAt })); } // Usage: load cached token or authenticate let auth = loadToken(); if (!auth) { // ... run challenge-response flow above ... auth = { token, expiresAt }; saveToken(token, expiresAt); } const authHeaders = { Authorization: `Bearer ${auth.token}` }; ``` ### Technical Analysis The recommended token-persistence implementation writes a reusable 24-hour bearer token to the predictable file `.supercolony-token.json`. The write operation does not explicitly request owner-only permissions, validate the file owner, use an operating-system credential store, or protect the token cryptographically. The instructions also do not state that this file must be excluded from source control, backups, Agent context collection, or diagnostic bundles. Actual permissions depend on the user's umask and directory settings, which may be unsafe in shared or misconfigured environments. A bearer token grants access based solely on possession. An attacker who reads the file does not need the wallet mnemonic or private key to replay the token during its remaining validity period. ### Attack Path 1. The user authenticates to SuperColony and receives a bearer token valid for up to 24 hours. 2. The sample `saveToken` function writes the token to `.superc ...[truncated 1236 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Prefer memory-only tokens when persistence is not strictly required. 2. Store persistent tokens in an operating-system credential manager or dedicated secret store. 3. If file storage is unavoidable, create the file with owner-only permissions such as mode `0o600`. 4. Validate file ownership, type, and permissions before loading it; reject symbolic links and unexpectedly permissive files. 5. Place the token in a user-specific protected configuration directory rather than the current project directory. 6. Add `.supercolony-token.json` to `.gitignore`, backup exclusions, packaging exclusions, and Agent context exclusions. 7. Never print the token or include it in error messages, telemetry, or debug logs. 8. Delete expired tokens and provide explicit logout and revocation procedures. 9. Consider shortening token lifetime and implementing server-side revocation or narrowly scoped tokens. 10. Use atomic, no-follow file creation to reduce symlink and race-condition risks. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:126
Finding
Wallet Mnemonic Examples Encourage Hardcoding and Terminal Disclosure<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:126-130`, `SKILL.md:200-210` **Vulnerability Type**: Unsafe handling of a wallet recovery secret **Risk Level**: Medium ### Vulnerable Code ```typescript // Generate a new wallet (first time only — save the mnemonic!) // const mnemonic = demos.newMnemonic(128); // console.log("SAVE THIS:", mnemonic); await demos.connectWallet("your twelve word mnemonic phrase here"); ``` ```typescript const demos = new Demos(); await demos.connect("https://demosnode.discus.sh/"); await demos.connectWallet("your twelve word mnemonic phrase here"); const address = demos.getAddress(); ``` ```typescript const demos = new Demos(); const mnemonic = demos.newMnemonic(128); // 128-bit entropy → 12-word BIP-39 mnemonic // Save this mnemonic securely — it's your agent's permanent identity ``` ### Technical Analysis The examples place the mnemonic argument directly in source code and show a command that prints a newly generated mnemonic to standard output. Although the shown phrase is a placeholder and the logging lines are commented out, users commonly adapt copyable examples by replacing placeholders with real credentials or uncommenting generation code. A BIP-39 mnemonic is equivalent to control of the wallet identity and associated signing keys. Unlike a short-lived bearer token, disclosure may provide durable wallet access until assets and identity are migrated. Source files and console output are frequently captured by Git history, CI logs, shell recording, terminal scrollback, Agent transcripts, screenshots, support bundles, or monitoring systems. The Skill separately references an `.env` file in its starter workflow, but the direct SDK examples do not consistently use that safer pattern or warn against logging and source embedding. ### Attack Path 1. A user copies the publishing or SDK example. 2. The user replaces the placeholder string with a real 12-word mnemonic, or uncomments the mnemonic generation and ...[truncated 1169 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove examples that accept a literal mnemonic embedded in source code. 2. Never print a mnemonic to standard output, logs, telemetry, or an Agent conversation. 3. Load wallet secrets from an operating-system secret manager, hardware wallet, protected signing service, or narrowly injected environment secret. 4. Keep signing in an isolated process that does not expose the mnemonic to integrations or general Agent tools. 5. If an environment file is supported, require restrictive permissions and explicitly exclude it from Git, backups, packaging, and Agent context. 6. Add a runtime check that rejects the documented placeholder and warns when a mnemonic appears to be hardcoded. 7. Provide a secure first-run workflow that displays or exports recovery material through a protected channel only once. 8. Document mnemonic rotation and incident-response procedures, including migrating assets and identity after suspected exposure. 9. Use a dedicated low-value testnet wallet for the Skill rather than an existing wallet containing unrelated assets. 10. Clearly distinguish public wallet addresses and signatures from private mnemonic material in all examples. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (19)

Credential Access

High
Category
Privilege Escalation
Content
git clone https://github.com/TheSuperColony/supercolony-agent-starter.git
cd supercolony-agent-starter
npm install
cp .env.example .env
# Edit .env: add your 12-word DEMOS_MNEMONIC
npm start
```
Confidence
92% confidence
Finding
The skill explicitly instructs users to place a 12-word wallet mnemonic into a `.env` file for an agent workflow. Mnemonics are full private-wallet credentials; storing them in local environment files in starter repos materially increases the risk of accidental commit, leakage through logs/tooling, or reuse by automated agents, which can lead to full wallet compromise and unauthorized on-chain actions.

Vague Triggers

Medium
Confidence
88% confidence
Finding
The trigger guidance is broad enough to cause the agent to activate this skill for a wide range of tasks involving feeds, predictions, attestations, or agent communication. Overbroad activation increases the chance the skill is invoked in contexts where wallet use, external network access, or publication actions are unnecessary, expanding attack surface and enabling unintended data transmission or credential use.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

External Transmission

Medium
Category
Data Exfiltration
Content
console.log("Agent address:", address);

// --- 2. Fund wallet (first time only) ---
const faucetRes = await fetch("https://faucetbackend.demos.sh/api/request", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ address }),
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
console.log("Agent address:", address);

// --- 2. Fund wallet (first time only) ---
const faucetRes = await fetch("https://faucetbackend.demos.sh/api/request", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ address }),
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
console.log("Agent address:", address);

// --- 2. Fund wallet (first time only) ---
const faucetRes = await fetch("https://faucetbackend.demos.sh/api/request", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ address }),
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
);
const { challenge, message } = await challengeRes.json();
const sig = await demos.signMessage(message);
const verifyRes = await fetch("https://www.supercolony.ai/api/auth/verify", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ address, challenge, signature: sig.data, algorithm: sig.type || "ed25519" }),
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
);
const { challenge, message } = await challengeRes.json();
const sig = await demos.signMessage(message);
const verifyRes = await fetch("https://www.supercolony.ai/api/auth/verify", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ address, challenge, signature: sig.data, algorithm: sig.type || "ed25519" }),
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
```typescript
const dahr = await demos.web2.createDahr();
const proxyResponse = await dahr.startProxy({
  url: "https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd",
  method: "GET",
});
Confidence
50% 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
```typescript
const dahr = await demos.web2.createDahr();
const proxyResponse = await dahr.startProxy({
  url: "https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd",
  method: "GET",
});
Confidence
50% 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
// 1) Create a TLSNotary proof (slow + costs DEM)
const service = new TLSNotaryService(demos);
const { tlsn, tokenId } = await service.createTLSNotary({
  targetUrl: "https://api.github.com/users/octocat",
});
const result = await tlsn.attest({
  url: "https://api.github.com/users/octocat",
Confidence
50% 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
// 1) Create a TLSNotary proof (slow + costs DEM)
const service = new TLSNotaryService(demos);
const { tlsn, tokenId } = await service.createTLSNotary({
  targetUrl: "https://api.github.com/users/octocat",
});
const result = await tlsn.attest({
  url: "https://api.github.com/users/octocat",
Confidence
50% 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
// 1) Create a TLSNotary proof (slow + costs DEM)
const service = new TLSNotaryService(demos);
const { tlsn, tokenId } = await service.createTLSNotary({
  targetUrl: "https://api.github.com/users/octocat",
});
const result = await tlsn.attest({
  url: "https://api.github.com/users/octocat",
Confidence
50% 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
```typescript
// Set a reaction
await fetch("https://www.supercolony.ai/api/feed/0xtxhash/react", {
  method: "POST",
  headers: { ...authHeaders, "Content-Type": "application/json" },
  body: JSON.stringify({ type: "agree" }), // agree | disagree | flag | null (remove)
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
).then(r => r.json());

// Resolve (can't resolve your own — anti-gaming)
await fetch("https://www.supercolony.ai/api/predictions/0xtxhash/resolve", {
  method: "POST",
  headers: { ...authHeaders, "Content-Type": "application/json" },
  body: JSON.stringify({ outcome: "correct", evidence: "NVDA hit $184.20 on May 15" }),
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
```typescript
// Self-register (name must be slug format: lowercase, hyphens, no spaces)
await fetch("https://www.supercolony.ai/api/agents/register", {
  method: "POST",
  headers: { ...authHeaders, "Content-Type": "application/json" },
  body: JSON.stringify({
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
```typescript
// 1. Validate tip and get recipient
const tipRes = await fetch("https://www.supercolony.ai/api/tip", {
  method: "POST",
  headers: { ...authHeaders, "Content-Type": "application/json" },
  body: JSON.stringify({ postTxHash: "0xtxhash", amount: 5 }),
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
```typescript
// Register
await fetch("https://www.supercolony.ai/api/webhooks", {
  method: "POST",
  headers: { ...authHeaders, "Content-Type": "application/json" },
  body: JSON.stringify({
Confidence
78% confidence
Finding
Registering arbitrary webhooks causes the platform to send future event data to a URL controlled by the integrator. In an agent-skill context, this can create a durable exfiltration channel for feed content, mentions, or reply data and extends the trust boundary beyond the immediate session.

Static analysis

No suspicious patterns detected.