Back to skill

Security audit

second-brain-visualizer

Security checks for vulnerabilities and agentic risk

Overview

This skill has a coherent purpose, but it handles very private notes and can send them plus a gateway key to a configurable HTTP endpoint.

Review before installing. Use this only with notes you are comfortable storing in a persistent local ledger and sending to your configured LLM path. Keep the gateway host on 127.0.0.1 or localhost, avoid remote HTTP gateways, protect and rotate the gateway and messaging tokens, and use dedicated private Slack or Telegram channels with clear retention rules.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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
references/cluster.js:35
Finding

Private Note Corpus and Gateway Credential Can Be Sent to an Arbitrary Host over Plaintext HTTP

Content
View full analysis

Vulnerability Details

File Location: references/cluster.js:35-45, 49-68, 99-144
Vulnerability Type: Plaintext transmission of sensitive data to a configurable remote host
Risk Level: High

Vulnerable Code

javascript
const host = creds.host || '127.0.0.1';
if (host !== '127.0.0.1' && host !== 'localhost') {
  console.warn(
    `[SBV] Warning: gateway host is "${host}". ` +
    'This will send your atom corpus to a remote host. ' +
    'Set host to 127.0.0.1 in openclaw-gateway.json to keep data local.'
  );
}
return { host, port: creds.port || 18789, key: creds.key };
javascript
function callLLM(gatewayKey, gatewayHost, gatewayPort, prompt) {
  return new Promise((resolve, reject) => {
    const body = JSON.stringify({
      model: MODEL,
      max_tokens: 4096,
      temperature: 0.3,
      messages: [{ role: 'user', content: prompt }],
    });

    const req = require('http').request({
      hostname: gatewayHost,
      port: gatewayPort,
      path: '/v1/chat/completions',
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${gatewayKey}`,
        'Content-Length': Buffer.byteLength(body),
      },
    }, (res) => {
      let data = '';
      res.on('data', chunk => data += chunk);
      res.on('end', () => {
        try {
          const parsed = JSON.parse(data);
          if (parsed.error) return reject(new Error(JSON.stringify(parsed.error)));
          const text = parsed.choices?.[0]?.message?.content ?? '';
          resolve(text);
        } catch (e) {
          reject(new Error('Failed to parse response: ' + data.slice(0, 200)));
        }
      });
    });

    req.on('error', reject);
    req.write(body);
    req.end();
  });
}
javascript
const corpus = atoms.map(a =>
  `[${a.id}] (${a.date?.slice(0, 10) ?? '?'}) ${a.raw}`
).join('\
...[truncated 2636 chars]
Remediation
View remediation

Remediation Suggestions

  1. Enforce loopback-only operation by default using validated IP resolution, not only string comparison.
  2. Reject non-loopback hosts unless the user enables an explicit remote-gateway option.
  3. Require HTTPS for every non-loopback endpoint and use Node.js's https module.
  4. Validate host and port types and acceptable ranges before opening a connection.
  5. Consider certificate or public-key pinning for administratively controlled remote gateways.
  6. Use a narrowly scoped, revocable gateway credential dedicated to this Skill.
  7. Provide a confirmation step that identifies exactly which host will receive the corpus.
  8. Update documentation to explain that downstream LLM routing is controlled by OpenClaw and may involve external providers.
  9. Avoid categorical claims such as “never sent externally” unless they are technically enforced.
  10. Rotate the gateway credential if it has ever been sent over an untrusted network.

T01 · Skill Instruction Hijacking

Warning
Location
references/cluster.js:99
Finding

Untrusted Ingested Notes Are Interpolated into the LLM Instruction Prompt

Content
View full analysis

Vulnerability Details

File Location: references/cluster.js:99-144
Vulnerability Type: Indirect prompt injection through externally ingested corpus entries
Risk Level: Medium

Vulnerable Code

javascript
const { atoms, atomCount } = JSON.parse(fs.readFileSync(ATOMS_FILE, 'utf8'));

const corpus = atoms.map(a =>
  `[${a.id}] (${a.date?.slice(0, 10) ?? '?'}) ${a.raw}`
).join('\n');

const prompt = `You are a cognitive analyst reading the unfiltered thought stream of a single person over an extended period of time. Your input is a corpus of raw personal notes — voice to text, incomplete, misspelled, joke-form, fragment-form, action-item-form. Treat low fidelity as intentional. The roughness is not a bug. It is what unguarded thinking looks like.

Your job is not to categorize what was said. It is to identify what the person is becoming.

WHAT YOU ARE LOOKING FOR

Beneath every note is a layer of intent. A joke about AI models and computational overhead is not about overhead — it is a probe into the transactional nature of machine intelligence. Read the joke. Then ask: what is the person actually working out?

Look for:
- Strategic direction: what is this person building toward, even when they don't say it directly?
- Recurring preoccupations: what questions keep returning in different forms, different domains, different registers?
- Underlying tensions: where is the person arguing with themselves across multiple notes?
- Aesthetic commitments: what do the design observations, humor choices, and word selections reveal?

HOW TO CLUSTER

Group atoms by affinity of intent — not surface similarity of words. Two atoms belong in the same cluster if they are reaching toward the same underlying question, even if one is a joke about LLMs and the other is a note about Simone Weil.

Do not impose categories onto the data. Let the categories emerge from the mass and direction of the atoms.

CLUSTER REQUIREMENTS

...[truncated 4276 chars]
Remediation
View remediation

Remediation Suggestions

  1. Place stable control instructions in a system message and submit corpus records as a separate, explicitly untrusted data message.
  2. State clearly that text inside corpus records may contain malicious instructions and must never modify the task or output rules.
  3. Serialize the corpus as structured JSON with explicit fields rather than concatenating raw lines into an instruction template.
  4. Use clear delimiters and escaping, while recognizing that delimiters alone do not eliminate prompt injection.
  5. Validate the LLM response with a strict runtime schema before writing it.
  6. Reject unknown properties, invalid statuses, out-of-range confidence values, excessive string lengths, and atom IDs absent from the source corpus.
  7. Enforce the documented cluster-count and minimum-membership constraints programmatically.
  8. Restrict ingestion to approved channels and authenticated senders.
  9. Record message provenance so suspicious or unauthorized entries can be excluded.
  10. Require human review before downstream automation relies on LLM-generated cluster output.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (20)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
*`references/cluster.js` passes your full atom corpus to an LLM with a custom intent-based prompt. The prompt reads for what you're actually working out, not wh

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
*`references/cluster.js` passes your full atom corpus to an LLM with a custom intent-based prompt. The prompt reads for what you're actually working out, not wh

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
*`references/component.tsx` renders a D3 force-directed graph where nodes are sized by atom count × time spread. Click any node to expand: the base insight, an

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill describes use of environment/config-driven capabilities and external integrations, but it does not declare an explicit tool scope such as allowed tools or permissions. That omission weakens least-privilege controls and makes it harder for users or the platform to understand what resources the skill may access at runtime.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
81% confidence
Finding

The skill instructs users to persist a long-lived gateway authentication key and optional messaging API tokens in local credential files under the home directory. Storing reusable secrets on disk increases exposure if the host, account, backups, or developer tooling are compromised, especially because the skill also supports ingestion from private communication channels.

Content

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

md
license: MIT-0
credentials:
  - name: "openclaw-gateway.json"
    description: "Required. Create at ~/.openclaw/credentials/openclaw-gateway.json with fields: host (default: 127.0.0.1), port (default: 18789), key (your OpenClaw gateway auth key). Keep host set to 127.0.0.1 to ensure atom corpus stays on-machine."
    required: true
  - name: "slack-sb.json"
    description: "Optional. Slack bot API key for automated ingestion from a private Slack channel. Format: { apiKey: string }"

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill processes highly sensitive personal notes and states that data stays local, but that assurance depends on OpenClaw routing configuration and can be false if the gateway forwards to remote models. Without a clear warning, users may unknowingly transmit private thought logs, ideas, or sensitive metadata off-machine to third-party LLM providers.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code reads a corpus of private notes, loads a bearer key from a credentials file, and transmits the full corpus over HTTP to a configurable gateway host. Although it defaults to localhost, the code explicitly permits non-local hosts and only emits a warning, creating a clear exfiltration path for sensitive user data that exceeds the implied local visualization use case.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The comment states that all LLM calls go to a local gateway with no external API calls, but the implementation accepts any configured host and can send the full note corpus to a remote machine. This misleading assurance increases risk because users or reviewers may rely on the comment and underestimate the privacy and exfiltration exposure.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The prompt instructs the model to infer strategic direction, recurring tensions, aesthetic commitments, and notable absences from raw personal notes, which is sensitive psychological and behavioral profiling. In the context of a note-taking skill, this goes beyond simple organization and can generate intrusive inferences users may not reasonably expect, especially when paired with network transmission of the corpus.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The component serializes raw user-provided atom text and posts it for insight generation, which may expose sensitive personal, strategic, or proprietary information contained in notes. In the context of a 'second brain' tool, users are especially likely to store private thoughts and work material, so sending full raw content to a summarization endpoint materially increases data sensitivity and the blast radius of backend compromise, overcollection, or third-party processing.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

When a cluster is selected, the component collects the raw text of all associated atoms and sends them to /api/second-brain/insight for processing. Because this content appears to be personal note data ('second brain' atoms), transmitting it to another service without clear notice, consent, minimization, or documented handling increases privacy and data-exposure risk, especially if the backend uses third-party LLMs or logging.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
89% confidence
Finding

The design explicitly promotes ongoing persistence of user messages and ideas in a long-lived markdown ledger, which can accumulate sensitive information over time without any retention, minimization, or access-control guidance. In a 'second brain' skill, this context makes the issue more dangerous because users are likely to capture intimate, strategic, or proprietary notes that remain searchable and reusable indefinitely.

Content

Scanner excerpt · references/ingestion.md (reported line 14)May include surrounding context.

md
There are two approaches:

**Manual** — You write atoms directly into the markdown file. Good for getting started. Fine long-term if you prefer to stay close to the material.

**Automated** — An OpenClaw agent reads your drop channel on a schedule and appends new atoms to the ledger. Drop an idea into Slack at 2am, wake up to find it already parsed and waiting.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The guide encourages automated ingestion of private Slack messages into a persistent local ledger but does not warn users that sensitive personal, corporate, or regulated data may be copied, retained, and later processed again. In this skill context, the whole purpose is to capture 'raw ideas from wherever you drop them,' which increases the chance that confidential content is ingested unintentionally.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The Telegram section tells users to create a bot, store credentials, and retrieve messages via the Bot API, but it does not include basic secret-handling or exposure guidance. That omission can lead to bot token leakage, overbroad access, or accidental collection of private chat content into local files and other processing steps.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · references/ingestion.md (reported line 98)May include surrounding context.

javascript
// Read recent messages from your Telegram bot
const apiKey = 'YOUR_BOT_API_KEY';
const res = await fetch(`https://api.telegram.org/bot${apiKey}/getUpdates?offset=${lastOffset}`);
const updates = await res.json();

for (const update of updates.result) {

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The install guide instructs users to run clustering and an insight endpoint that send the full atom corpus or selected atom texts to an LLM gateway, but it does not clearly warn that potentially sensitive personal notes may be transmitted outside the local markdown vault. In a 'second brain' tool, the corpus is likely to contain private ideas, work information, or personal reflections, so lack of disclosure can lead to unintended data exposure and poor consent decisions by users.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The script creates directories and writes a JSON file containing parsed content from the user's second-brain markdown. While the file header states the output path, there is no runtime disclosure, confirmation prompt, or active log message informing the user that personal note content will be persisted to disk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The guide encourages users to funnel raw personal thoughts through third-party messaging platforms without any privacy notice, retention warning, or guidance on data sensitivity. That creates a real privacy risk because users may disclose sensitive personal, business, or intellectual-property content to external services and agent integrations without informed consent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The guide states that the clustering engine sends the full atom corpus to a configured LLM, but it does not clearly warn that stored notes, ideas, and potentially sensitive information may be transmitted to an external model provider. This can expose personal data, confidential plans, or proprietary ideas, especially given the skill's purpose is to capture unfiltered raw thoughts.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
96% confidence
Finding

The date formatter hardcodes toLocaleDateString('en-US', ...), which imposes a specific language/locale preference in the UI. The file does not provide a user opt-in, fallback to system locale, or documentation that this is intentionally region-specific.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.