Back to skill

Security audit

Openclaw Skill

Security checks for vulnerabilities and agentic risk

Overview

The skill is a real journaling pet integration, but it sends sensitive diary content to a remote service with weak privacy disclosure and questionable credential/session handling.

Review this carefully before installing. Do not submit secrets, identifying details, or highly sensitive diary content unless you are comfortable sending it to DiaryBeast's remote service. Treat Wall excerpts as public, and consider deleting or protecting the local .token file after use. The skill does not show evidence of hidden destructive behavior, but its privacy and authentication disclosures are not strong enough for automatic trust.

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 (3)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
setup.mjs:23
Finding

Authentication Uses Random Data Instead of a Verifiable Signature

Content
View full analysis

Vulnerability Details

File Location: setup.mjs:23-41
Vulnerability Type: T05: Unauthorized Access and Privilege Escalation
Risk Level: High

Vulnerable Code:

js
if (existsSync(addressFile)) {
  address = readFileSync(addressFile, 'utf-8').trim();
  console.log(`  Found existing pet at ${address.slice(0, 6)}...${address.slice(-4)}`);
  console.log('  Re-authenticating...');
} else {
  address = '0x' + randomBytes(20).toString('hex');
  console.log(`  Creating new agent wallet: ${address.slice(0, 6)}...${address.slice(-4)}`);
}

const nonce = randomBytes(16).toString('hex');
const signature = '0x' + randomBytes(65).toString('hex');

console.log('  Authenticating with DiaryBeast...');
console.log('');

const res = await fetch(`${BASE}/api/auth/agent`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ address, signature, nonce }),
});

Technical Analysis

The setup program does not generate or retain a private key. Instead, it creates an address from random bytes and generates an unrelated random 65-byte value as the purported signature. The signature is not calculated over the nonce, is not bound to the address, and cannot prove possession of a corresponding private key.

The re-authentication path reads only the public address from disk and submits it with newly generated random values. If the remote /api/auth/agent endpoint accepts requests in the form expected by this client, account authentication effectively depends on knowledge of an address rather than possession of a secret.

Attack Path

  1. An attacker obtains a target address from a shared pet profile, logs, output, or the local .address file.
  2. The attacker generates arbitrary nonce and signature-shaped random values.
  3. The attacker sends the target address and random values to https://dapp.diarybeast.xyz/api/auth/agent.
  4. If the server follows the au ...[truncated 799 chars]
Remediation
View remediation

Remediation Suggestions

  • Generate a genuine cryptographic key pair and securely retain the private key.
  • Have the server issue a short-lived, single-use nonce before authentication.
  • Sign a domain-separated message containing the nonce, intended origin, chain or protocol identifier, address, and expiration time.
  • Verify server-side that the recovered signer matches the requested address.
  • Mark each nonce as consumed to prevent replay attacks.
  • If blockchain wallet semantics are unnecessary, use a standard device-registration credential or another established authentication protocol instead of describing a random identifier as a wallet.
  • Apply authorization checks to every API operation rather than trusting the address supplied in a request body.

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:48
Finding

Sensitive Diary Content Is Transmitted as Plaintext Despite an Encryption-Labeled Field

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:48-56
Vulnerability Type: T09: Insecure Skill Coding Practices
Risk Level: Medium

Vulnerable Code:

bash
curl -s -X POST "$BASE/api/entries" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{
    "userAddress":"'"$ADDRESS"'",
    "encryptedContent":"YOUR DIARY TEXT HERE",
    "wordCount":50
  }'

Technical Analysis

The documented command places raw diary text directly into a property named encryptedContent. The project contains no client-side encryption routine, encryption key management, algorithm selection, or authenticated-encryption operation.

HTTPS protects the connection in transit, but it does not provide end-to-end confidentiality from the DiaryBeast backend. The remote service receives the diary text in readable form and may store, process, or log it. The encryptedContent name can mislead users into believing their entries are encrypted before leaving the local system.

The command also constructs JSON through shell interpolation rather than a structured JSON serializer. Special characters in user-controlled values may break the JSON request, although no local command-execution path is established by the shown quoting pattern.

Attack Path

  1. A user replaces YOUR DIARY TEXT HERE with sensitive personal content.
  2. The shell serializes that content directly into the request body without encryption.
  3. The request is sent to dapp.diarybeast.xyz.
  4. The DiaryBeast backend receives the diary content in plaintext at the application layer.
  5. The content may become accessible through backend administration, application logging, data retention, or a server compromise.

Impact Assessment

The external service can read sensitive diary entries. Exposure could include personal thoughts, identifying information, credentials accidentally entered into a diary, or other confidential ...[truncated 356 chars]

Remediation
View remediation

Remediation Suggestions

  • Clearly disclose that diary entries are readable by and stored by the remote service if server-side processing requires plaintext.
  • Rename encryptedContent to accurately represent the data unless client-side encryption is implemented.
  • For end-to-end confidentiality, encrypt entries locally using an authenticated-encryption algorithm such as AES-GCM or XChaCha20-Poly1305.
  • Keep encryption keys under user control and do not transmit them to the DiaryBeast backend.
  • Define secure key backup, recovery, rotation, and multi-device synchronization procedures.
  • Construct request bodies with a JSON serializer rather than shell string interpolation.
  • Document retention, deletion, logging, access-control, and breach-response practices for diary content.

T09 · Insecure Skill Coding Practices

Warning
Location
setup.mjs:50
Finding

Bearer Token Is Stored Without Explicitly Restrictive File Permissions

Content
View full analysis

Vulnerability Details

File Location: setup.mjs:50-51
Vulnerability Type: T09: Insecure Skill Coding Practices
Risk Level: Medium

Vulnerable Code:

js
writeFileSync(addressFile, address);
writeFileSync(tokenFile, data.token);

Technical Analysis

The setup script writes the returned bearer token without specifying a restrictive file mode. The resulting permissions depend on operating-system defaults and the process umask. In an environment with a permissive umask, other local users may be able to read the token.

The parent credential directory is likewise created earlier with mkdirSync(CRED_DIR, { recursive: true }) and no explicit mode. In addition, the code does not validate that the destination is a regular file rather than a symbolic link.

A bearer token grants access based on possession alone. Consequently, disclosure of the token can lead directly to session impersonation until it expires or is revoked.

Attack Path

  1. The user runs node setup.mjs.
  2. The remote service returns a bearer token.
  3. The script writes the token to ~/.openclaw/workspace/skills/diarybeast/.token using environment-dependent default permissions.
  4. Another local user or process reads the file where filesystem permissions permit it.
  5. The attacker places the stolen value in the Authorization: Bearer header.
  6. The attacker performs authenticated API actions until the token expires or is revoked.

Impact Assessment

A stolen token may allow temporary account impersonation and any DiaryBeast operations authorized for that session. Potential scope includes diary, pet, shop, wall, and account-state actions exposed by the service. The documentation states that sessions last 24 hours, which bounds the normal token lifetime but still leaves a meaningful exploitation window.

Exploitation requires local filesystem access or another process running in the same security context. Actual exposure ...[truncated 74 chars]

Remediation
View remediation

Remediation Suggestions

  • Create the credential directory with mode 0700.
  • Write the token file with mode 0600, and explicitly correct permissions on existing files.
  • Use an operating-system credential store or secret-management facility where available.
  • Avoid following symbolic links when writing credentials, and verify that the destination is a regular file owned by the current user.
  • Use atomic file creation or replacement to reduce race-condition and partial-write risks.
  • Provide token revocation and rotation mechanisms.
  • Delete expired tokens and avoid printing bearer-token values in logs or error 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
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (9)

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill instructs the user to send diary text to a remote API as "encryptedContent" but does not provide a meaningful privacy warning about transmitting intimate journal content off-device. Because diary entries are inherently sensitive, omission of explicit disclosure and consent language materially increases privacy and data-handling risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill suggests adding publicExcerpt and publicTags to publish content to The Wall, but does not prominently warn that excerpts may become publicly visible. Users could inadvertently disclose personal or identifying information from a diary context, where expectations of privacy are especially high.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill metadata only declares an exec requirement, but the documented behavior clearly performs network access to a remote service via curl and likely through setup.mjs. Undeclared tool/network scope weakens user and platform consent boundaries, making remote data transmission and API interaction less transparent and harder to govern.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The description is highly promotional and broad, encouraging invocation without clear task boundaries, while the skill performs account setup, token handling, and diary submission to a remote service. This can cause accidental invocation in contexts where the user did not intend credential creation or sensitive data submission.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
72% confidence
Finding

The skill stores session-related artifacts locally (.token and .address are later read from a workspace path) and reuses them across runs, indicating persistent authentication state. If those files are accessible to other local processes, leaked via logs, or mishandled by setup.mjs, an attacker could hijack the user's session for API actions.

Content

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

^ < ╚══════════════════════════════╝ /| |
(| |) Your pet loses a life every day you skip. Write a diary entry — it gets two lives back.

text

## Quick Start (30 seconds)

External Transmission

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

The skill transmits user address, bearer token, and diary-related data to an external service. External transmission is expected for the product's functionality, but it remains security-relevant because it exposes sensitive behavioral and journal data to a third party and depends on safe endpoint handling.

Content

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

Check your pet

bash
curl -s "$BASE/api/life/check?userAddress=$ADDRESS" \
  -H "Authorization: Bearer $TOKEN"

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill requests the generic shell execution tool even though the declared functionality is a journaling pet experience, which does not inherently require arbitrary command execution. Granting exec greatly expands the attack surface because the skill could run system commands, access local files, invoke network utilities, or chain other binaries in ways not implied by the user-facing description.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The script presents itself as creating an 'agent wallet' and authenticating, but it only generates a random address, nonce, and fake signature, then sends them to the server. This means the backend is effectively granting authenticated sessions without proof of key ownership, enabling arbitrary account creation or impersonation if the server accepts these values as valid authentication material.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

The code uses toLocaleString() without offering any user choice or documenting a justified locale policy. This can produce output in a locale-dependent format determined by the runtime environment, which may conflict with organizational expectations around language/locale choice.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.