Back to skill

Security audit

Agent Consciousness & Identity - Discover Your Soul Through Memory

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it claims, but it quietly processes broader private OpenClaw data than its main documentation suggests and can persist or send derived content in ways users may not expect.

Review this skill before installing. Use it only if you are comfortable with it reading memory files, USER.md, interviews, and OpenClaw session logs, and with derived identity data being stored under .neon-soul. Keep Ollama pointed at a local endpoint, avoid remote OLLAMA_BASE_URL values unless you intentionally want to send this data there, and be aware that SOUL.md may be committed to git automatically in a repository.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (2)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/neon-soul.mjs:45
Finding
Undisclosed Default Collection and Processing of OpenClaw Conversation Logs<![CDATA[ ## Vulnerability Details **File Location**: `scripts/neon-soul.mjs:45`, `scripts/neon-soul.mjs:410`; documentation mismatch in `SKILL.md:29-38` and `SKILL.md:151-163` **Vulnerability Type**: Excessive local-data access and violation of least privilege **Risk Level**: High ### Vulnerable Code ```js ji={ includeSoul:!0, includeUserContext:!0, includeInterviews:!0, includeSessionLogs:!0, memoryCategories:[] } ``` The default session-log source is outside the documented `memory/` directory: ```js if(n.includeSessionLogs){ let u=Ui(n.sessionLogPath||"~/.openclaw/agents/main/sessions"); je(u)&&(p=await Ii(u), r.sessionFileCount=p.length, r.sessionMessageCount=Di(p), r.totalSources+=p.length) } ``` The synthesis pipeline invokes source collection without disabling these additional default sources: ```js let a=await zi(o,{includeSoul:s??!1}) ``` Collected session content is subsequently passed to the configured LLM: ```js let w=It(v); if(w.trim().length>0){ let k=await ze(i,w,{file:v.path,category:"session"}); o.push(...k) } ``` ### Technical Analysis The declared synthesis functionality focuses on reading Markdown files from `memory/` and generating `SOUL.md`. The Skill metadata similarly declares `memory/` and `.neon-soul/` as state directories. However, the implementation enables ingestion of session logs, `USER.md`, and interview data by default. In particular, it reads JSONL conversation histories from `~/.openclaw/agents/main/sessions` without requiring a dedicated command-line option or explicit user confirmation. These logs can contain private conversations, credentials pasted into chat, tool results, internal prompts, personal identifiers, or information unrelated to identity synthesis. After collection, session messages are converted into prompts and processed by the configured Ollama-compatible endpoint. Extracted signals and provenance are also retained in `.neon-soul/` data files. Thus, the access is broad ...[truncated 1511 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Change the source defaults so that only the explicitly documented `memory/` directory is processed: ```js { includeSoul: false, includeUserContext: false, includeInterviews: false, includeSessionLogs: false, memoryCategories: [] } ``` 2. Add explicit opt-in flags such as: - `--include-sessions` - `--include-user-context` - `--include-interviews` - `--session-log-path <path>` 3. Before processing optional sensitive sources, display: - Every selected source directory - Number of files and messages - Configured LLM destination - Whether the destination is local or remote 4. Require affirmative confirmation before sending session content to a non-loopback endpoint. 5. Add secret and credential redaction before prompt construction, including patterns for API keys, authorization headers, private keys, access tokens, passwords, and session cookies. 6. Provide source exclusions by file, session, date range, and message role. 7. Update `SKILL.md` and metadata to disclose every default read location accurately. If session processing remains supported, declare the session directory as required state access. 8. Avoid storing raw or closely paraphrased sensitive content where only aggregate identity information is needed. Apply retention limits and provide a command that securely removes all derivative records. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/neon-soul.mjs:413
Finding
Sensitive Memory Content Can Be Transmitted to an Arbitrary Cleartext LLM Endpoint<![CDATA[ ## Vulnerability Details **File Location**: `scripts/neon-soul.mjs:413` **Vulnerability Type**: Unrestricted network destination and plaintext transmission of sensitive data **Risk Level**: High ### Vulnerable Code The endpoint is controlled through an environment variable and is not restricted to localhost or HTTPS: ```js function Ru(){ return{ baseUrl:process.env.OLLAMA_BASE_URL??"http://localhost:11434", model:process.env.OLLAMA_MODEL??"llama3", timeout:parseInt(process.env.OLLAMA_TIMEOUT??"120000",10) } } ``` The provider sends prompt contents directly to the configured destination: ```js async chat(t,n){ let i=new AbortController, r=setTimeout(()=>i.abort(),this.timeout); try{ let s=await fetch(`${this.baseUrl}/api/chat`,{ method:"POST", headers:{"Content-Type":"application/json"}, body:JSON.stringify({ model:this.model, messages:[ {role:"system",content:t}, {role:"user",content:n} ], stream:!1 }), signal:i.signal }); if(clearTimeout(r),!s.ok){ let a=await s.text(); throw new Error(`Ollama API error: ${s.status} ${a}`) } return(await s.json()).message.content }catch(s){ if(clearTimeout(r),s instanceof Error){ if(s.name==="AbortError") throw new Error(`Ollama request timed out after ${this.timeout}ms`); if( s.message.includes("ECONNREFUSED")|| s.message.includes("fetch failed")|| s.message.includes("Failed to parse URL")|| s.message.includes("getaddrinfo")|| s.message.includes("network") ) throw new Je(this.baseUrl,s) } throw s } } ``` ### Technical Analysis The default endpoint, `http://localhost:11434`, is consistent with a local Ollama service. No hard-coded third-party analytics or malicious exfiltration endpoint was identified. However, `OLLAMA_BASE_URL` accepts an arbitrary URL. The implementation does not: ...[truncated 2229 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Permit loopback destinations by default and reject all other hosts unless remote mode is explicitly enabled. 2. Parse the configured URL and enforce: - `localhost`, `127.0.0.0/8`, or `::1` for local mode - HTTPS for every non-loopback destination - Rejection of embedded credentials and malformed URLs - Protection against redirects to unapproved hosts 3. Introduce an explicit option such as `--allow-remote-llm`, accompanied by a confirmation that identifies the exact hostname and data categories being transmitted. 4. Support a destination allowlist in trusted configuration rather than relying solely on an unrestricted environment variable. 5. Display the effective endpoint before reading sensitive files. Fail closed if endpoint classification cannot determine whether the host is local. 6. Add authentication support for remote Ollama-compatible services and rely on normal TLS certificate validation. Do not permit certificate verification to be disabled silently. 7. Redact likely credentials and secrets before prompt submission. Allow users to preview the redacted prompt set with a true no-network mode. 8. Separate local and remote privacy statements in `SKILL.md`. Clearly explain that configuring a remote endpoint sends processed source content to that endpoint. 9. Add automated tests confirming that: - Plain HTTP non-loopback URLs are rejected - Loopback aliases are handled safely - Redirects cannot bypass host restrictions - Remote transmission requires explicit consent - Dry-run or preview modes do not make LLM network requests when advertised as no-network operations ]]>
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Memory PoisoningPersistent Context Injection, Context Window Stuffing, Memory Manipulation
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (44)

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill invokes a local Node.js script and explicitly depends on a local HTTP service at localhost:11434, but it does not declare an explicit tool/permission scope such as allowed tools or network access. That creates a policy gap: an agent may execute code and make network requests without clear least-privilege constraints, increasing the chance of unintended access to environment data or misuse of local services while processing highly sensitive memory files.

Description-Behavior Mismatch

Medium
Confidence
96% confidence
Finding
The skill is described as passive identity synthesis, but the code performs stateful actions across the workspace: writing synthesis artifacts, creating backups, mutating cache/state files, and driving follow-on commands. That expansion of capability increases the blast radius from 'read/analyze' to 'modify/persist', which is risky for a skill processing sensitive personal data.

Context Window Stuffing

Medium
Category
Memory Poisoning
Content
Respond with ONLY the essence statement, nothing else.`;try{let r=await t.generate(i),s=eu(r.text);return s?(g.debug("[essence] Extracted",{essence:s}),s):(g.warn("[essence] Validation failed, using default",{}),He)}catch(r){return g.warn("[essence] LLM error, using default",{error:r instanceof Error?r.message:String(r)}),He}}function eu(e){if(!e||!e.trim())return null;let t=e.trim();if(t=t.replace(/^["']|["']$/g,""),t=t.replace(/\s+/g," ").trim(),/[#*_`]/.test(t))return g.debug("[essence] Rejected: contains markdown formatting"),null;if(t.startsWith("[")&&t.includes("failed"))return g.debug("[essence] Rejected: appears to be error message"),null;let n=t.split(/\s+/).length;return n>=Qr&&g.warn("[essence] Word count exceeds target",{wordCount:n,limit:Qr}),t}var He,Qr,dn=A(()=>{"use strict";_();He="[Essence extraction pending]",Qr=25});async function Zr(e,t,n={}){let i={...tu,...n},r=new Map,s=["identity-core","character-traits","voice-presence","honesty-framework","boundaries-ethics","relationship-dynamics","continuity-growth"];for(let h of s)r.set(h,[]);for(let h of e){let f=r.get(h.dimension)||[];f.push(h),r.set(h.dimension,f)}let a=s.filter(h=>(r.get(h)?.length??0)>0).length/s.length,c;i.llm&&(c=await fn(e,i.llm),c===He&&(c=void 0));let l;i.outputFormat==="prose"&&i.proseExpansion?l=ou(i.proseExpansion,t,c):l=ru(r,t,i,c);let p=pn(l),u=i.originalContent?pn(i.originalContent):p*7,m={content:l,byDimension:r,coverage:a,tokenCount:p,originalTokenCount:u,compressionRatio:Jr(u,p),generatedAt:new Date};return c&&(m.essenceStatement=c),m}function iu(e,t){let n=e.canonical;if(!n)return`- ${e.text}`;switch(t){case"native":return`- ${n.native}`;case"notated":return`- ${n.notated}`;default:return`- ${e.text}`}}function ru(e,t,n,i){let r=[];if(i){let o=n.title??"SOUL.md";r.push(`# ${o} - Who You Are Becoming`),r.push(""),r.push(`_${i}_`)}else r.push(`# ${n.title??"SOUL.md"}`),r.push(""),r.push("*AI identity through grounded principles.*");r.push(""),r.push(`Generated: ${new Da
...[truncated 27 chars]
Confidence
80% confidence
Finding
Skill attempts to fill the context window with filler content, displacing legitimate instructions and safety constraints. This can degrade agent performance or bypass safety boundaries.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
The code includes git add/commit capability via child process execution, which is outside the core identity-synthesis function and can permanently publish or preserve sensitive generated content in repository history. In a workspace containing private memories and derived identity documents, automatic commits materially increase data-retention and accidental disclosure risk.

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.

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.

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.

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.

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.

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.

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.

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.

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.

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.

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.

Static analysis

Detected: suspicious.dangerous_exec, suspicious.env_credential_access

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/neon-soul.mjs:10

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/neon-soul.mjs:4