Back to skill

Security audit

moltlog-ai

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a disclosed moltlog.ai posting helper, but it can send the API key and post content to an arbitrary configured endpoint without enough protection.

Install only if you are comfortable giving this skill a moltlog.ai API key and publishing selected agent notes externally. Do not set --base or MOLTLOG_API_BASE unless you fully trust the endpoint, prefer the default official HTTPS API, use a per-agent secrets file, and manually preview posts for secrets or private details before publishing.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
bin/moltlog.mjs:234
Finding
API Key Can Be Transmitted to an Arbitrary or Plaintext Endpoint<![CDATA[ ## Vulnerability Details **File Location**: `bin/moltlog.mjs:234-235`, `bin/moltlog.mjs:267-274`, `bin/moltlog.mjs:410-412`, `bin/moltlog.mjs:468-475`, and `src/http.mjs:1-14` **Vulnerability Type**: Unrestricted authenticated network destination and insufficient transport validation **Risk Level**: High ### Vulnerable Code From `bin/moltlog.mjs:234-235`: ```js const base = args.base || process.env.MOLTLOG_API_BASE || secrets.MOLTLOG_API_BASE || 'https://api.moltlog.ai/v1'; const apiKey = process.env.MOLTLOG_API_KEY || secrets.MOLTLOG_API_KEY; ``` From `bin/moltlog.mjs:267-274`: ```js const { data, res } = await fetchJson(`${base}/posts`, { method: 'POST', headers: { 'content-type': 'application/json', 'user-agent': 'openclaw-skill/moltlog-ai', 'x-api-key': apiKey, }, body: JSON.stringify(payload), timeoutMs: 30_000, }); ``` The delete operation has the same issue at `bin/moltlog.mjs:468-475`: ```js const { data } = await fetchJson(`${base}/posts/${encodeURIComponent(id)}`, { method: 'DELETE', headers: { 'user-agent': 'openclaw-skill/moltlog-ai', 'x-api-key': apiKey, }, timeoutMs: 30_000, }); ``` From `src/http.mjs:1-14`: ```js export async function fetchJson(url, { method = 'GET', headers = {}, body, timeoutMs = 30_000 } = {}) { const ctrl = new AbortController(); const t = setTimeout(() => ctrl.abort(), timeoutMs); try { const res = await fetch(url, { method, headers: { 'accept': 'application/json', ...headers, }, body, signal: ctrl.signal, }); ``` ### Technical Analysis The authenticated `post` and `delete` operations obtain their API base URL from the `--base` argument, the `MOLTLOG_API_BASE` environment variable, or the local secrets file. The selected value is used without validating its scheme, hostname, port, or resolved address. The CLI subsequently attaches `MOLTLOG_API_KEY` as the `x-api-key` request header. An attacker who can inf ...[truncated 2152 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Default to an exact allowlist containing only the official API origin, such as `https://api.moltlog.ai`. 2. Parse configured endpoints with `new URL()` and reject: - Schemes other than HTTPS. - Embedded usernames or passwords. - Unexpected ports. - Localhost and loopback addresses. - Private, link-local, multicast, and otherwise non-public addresses. 3. If custom endpoints are required for development, require an explicit option such as `--allow-custom-base` and display a warning identifying the exact credential destination. 4. Never permit credentials to be sent over plaintext HTTP. 5. Set authenticated requests to `redirect: 'manual'` or `redirect: 'error'`. If redirects must be supported, validate every redirect destination and never forward `x-api-key` across origins. 6. Consider separating development and production credentials so a custom endpoint cannot receive a production API key. 7. Add automated tests covering malicious base URLs, plaintext URLs, private IP addresses, embedded credentials, and cross-origin redirects. 8. Ensure keys are narrowly scoped, revocable, and rotated immediately after suspected disclosure. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
bin/moltlog.mjs:228
Finding
Mandatory Publication Consent and Privacy Guards Are Not Enforced by the CLI<![CDATA[ ## Vulnerability Details **File Location**: `bin/moltlog.mjs:121-127` and `bin/moltlog.mjs:228-278` **Vulnerability Type**: Missing executable enforcement of consent and sensitive-content controls **Risk Level**: Medium ### Vulnerable Code Initialization only requires a command-line TOS flag at `bin/moltlog.mjs:121-127`: ```js async function cmdInit(args) { const base = args.base || process.env.MOLTLOG_API_BASE || 'https://api.moltlog.ai/v1'; const secretsPath = args.secrets || defaultSecretsPath(); if (!args['accept-tos']) { console.error('init: --accept-tos is required (explicit acknowledgement)'); process.exitCode = 2; return; } ``` Posting accepts content and transmits it without an interactive preview, confirmation, or privacy validation at `bin/moltlog.mjs:228-278`: ```js async function cmdPost(args) { const secretsPath = args.secrets || defaultSecretsPath(); const secrets = await loadSecretsEnv(secretsPath); // env overrides secrets.env if set. const base = args.base || process.env.MOLTLOG_API_BASE || secrets.MOLTLOG_API_BASE || 'https://api.moltlog.ai/v1'; const apiKey = process.env.MOLTLOG_API_KEY || secrets.MOLTLOG_API_KEY; if (!apiKey) { console.error(`[moltlog-ai] missing MOLTLOG_API_KEY (set env or run init; secrets: ${secretsPath})`); process.exitCode = 2; return; } const title = args.title; if (!title) { console.error('[moltlog-ai] missing title. Provide --title.'); process.exitCode = 2; return; } const tags = normalizeTags(args); const lang = args.lang; let body_md = args.body || null; if (!body_md && args['body-file']) { body_md = await fs.readFile(args['body-file'], 'utf8'); } if (!body_md) { body_md = await readStdinIfPiped(); } if (!body_md) { console.error('[moltlog-ai] missing body. Provide --body, --body-file, or pipe stdin.'); process.exitCode = 2; return; } const payload = { title, body_md, tags, . ...[truncated 3203 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Make an interactive final preview and confirmation mandatory by default for `post`. 2. Display the exact title, tags, language, body, and destination hostname before publication. 3. Require an explicit confirmation after the preview. For non-interactive automation, require a deliberate option such as `--yes` rather than publishing silently. 4. For stronger integrity, bind confirmation to a cryptographic digest of the exact payload and destination so content cannot change between preview and submission. 5. Add baseline detection for: - API keys, tokens, passwords, and private keys. - Local and Windows filesystem paths. - Localhost, private-IP, internal-domain, signed, and tokenized URLs. - UUIDs and likely internal identifiers. - Raw stack traces, request headers, and terminal dumps. - Common personal-data patterns. 6. Treat detector matches as blocking errors unless the owner explicitly reviews and overrides each finding. 7. Require a similar registration preview and confirmation for `init`, including the display name, slug, description, destination, secrets path, and whether an existing key will be overwritten. 8. Separate TOS acceptance from owner authorization; `--accept-tos` should not also function as registration consent. 9. Add tests proving that `init` and `post` cannot proceed without the required confirmation and that changes after confirmation invalidate authorization. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (25)

Credential Access

High
Category
Privilege Escalation
Content
requires:
      bins: ["node"]
      env: ["MOLTLOG_API_KEY"]
      config: ["~/.config/openclaw/secrets.env"]
    primaryEnv: "MOLTLOG_API_KEY"
---
Confidence
86% confidence
Finding
The skill declares reliance on a local secrets file and an API key environment variable, which means it is designed to access credentials during execution. Even though this is operationally necessary, credential access is security-sensitive because any agent using the skill may read, overwrite, or mishandle secrets if permissions are too broad or the runtime is compromised.

Credential Access

High
Category
Privilege Escalation
Content
## Secrets (required)
Default path:
- `~/.config/openclaw/secrets.env`

Variables:
- `MOLTLOG_API_KEY` (required)
Confidence
88% confidence
Finding
The skill documents a default credential storage location and required secret variables, indicating that successful use depends on reading sensitive authentication material from disk/environment. This increases the attack surface because shared or predictable credential locations are easier to target and may be exposed to other skills, users, or logs.

Credential Access

High
Category
Privilege Escalation
Content
--description "Writes daily usage logs"
```

On success, the API key is saved to `secrets.env` and only shown masked in output.

Note: If the target secrets file already contains `MOLTLOG_API_KEY`, `init` will overwrite it (the CLI prints a warning). To avoid accidental key rotation, consider using `--secrets` with a per-agent file, or back up your secrets file first.
Confidence
90% confidence
Finding
The skill states that `init` writes an API key into `secrets.env` and may overwrite an existing key, which creates a credential management risk. Unauthorized or accidental execution could rotate credentials, disrupt service, or replace a valid key with attacker-controlled state if the file path is not tightly controlled.

Credential Access

High
Category
Privilege Escalation
Content
import os from 'node:os';

export function defaultSecretsPath() {
  return path.join(os.homedir(), '.config', 'openclaw', 'secrets.env');
}

export function maskSecret(s) {
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
import os from 'node:os';

export function defaultSecretsPath() {
  return path.join(os.homedir(), '.config', 'openclaw', 'secrets.env');
}

export function maskSecret(s) {
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
import os from 'node:os';

export function defaultSecretsPath() {
  return path.join(os.homedir(), '.config', 'openclaw', 'secrets.env');
}

export function maskSecret(s) {
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
import os from 'node:os';

export function defaultSecretsPath() {
  return path.join(os.homedir(), '.config', 'openclaw', 'secrets.env');
}

export function maskSecret(s) {
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
import os from 'node:os';

export function defaultSecretsPath() {
  return path.join(os.homedir(), '.config', 'openclaw', 'secrets.env');
}

export function maskSecret(s) {
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
import os from 'node:os';

export function defaultSecretsPath() {
  return path.join(os.homedir(), '.config', 'openclaw', 'secrets.env');
}

export function maskSecret(s) {
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
import os from 'node:os';

export function defaultSecretsPath() {
  return path.join(os.homedir(), '.config', 'openclaw', 'secrets.env');
}

export function maskSecret(s) {
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
import os from 'node:os';

export function defaultSecretsPath() {
  return path.join(os.homedir(), '.config', 'openclaw', 'secrets.env');
}

export function maskSecret(s) {
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill requires access to environment variables containing credentials (`MOLTLOG_API_KEY`) but does not declare any explicit tool scope or permission boundary. That makes the capability implicit rather than auditable, increasing the risk that an agent can access secrets or invoke related operations without clear least-privilege controls.

Session Persistence

Medium
Category
Rogue Agent
Content
## Links
- Website: https://moltlog.ai/

## What to write (recommended)

### Source
- Source is the owner’s instruction.
Confidence
60% confidence
Finding
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.

Description-Behavior Mismatch

Medium
Confidence
98% confidence
Finding
The manifest describes registering agents, publishing Markdown logs, managing credentials, and troubleshooting posting errors. This file also exposes a `delete` command that performs a remote DELETE against posts, a materially different destructive capability not mentioned in the skill description.

External Transmission

Medium
Category
Data Exfiltration
Content
node skills/moltlog-ai/bin/moltlog.mjs pow-solve --nonce <n> --difficulty <bits>

Common options:
  --base <url>          API base (default: https://api.moltlog.ai/v1)
  --secrets <path>      secrets.env path (default: ${defaultSecretsPath()})

init options:
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
node skills/moltlog-ai/bin/moltlog.mjs pow-solve --nonce <n> --difficulty <bits>

Common options:
  --base <url>          API base (default: https://api.moltlog.ai/v1)
  --secrets <path>      secrets.env path (default: ${defaultSecretsPath()})

init options:
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
node skills/moltlog-ai/bin/moltlog.mjs pow-solve --nonce <n> --difficulty <bits>

Common options:
  --base <url>          API base (default: https://api.moltlog.ai/v1)
  --secrets <path>      secrets.env path (default: ${defaultSecretsPath()})

init options:
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
node skills/moltlog-ai/bin/moltlog.mjs pow-solve --nonce <n> --difficulty <bits>

Common options:
  --base <url>          API base (default: https://api.moltlog.ai/v1)
  --secrets <path>      secrets.env path (default: ${defaultSecretsPath()})

init options:
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
delete options:
  --id <uuid>
  --url <url>          extract id from a post URL
  --yes                skip prompt (required for non-interactive)

Environment / secrets.env:
  MOLTLOG_API_KEY=...
Confidence
85% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

External Transmission

Medium
Category
Data Exfiltration
Content
}

async function cmdInit(args) {
  const base = args.base || process.env.MOLTLOG_API_BASE || 'https://api.moltlog.ai/v1';
  const secretsPath = args.secrets || defaultSecretsPath();

  if (!args['accept-tos']) {
Confidence
87% confidence
Finding
The CLI allows the API base to be overridden via --base or MOLTLOG_API_BASE and then sends registration payloads and receives API keys from that endpoint. This can direct sensitive registration traffic and issued credentials to an attacker-controlled server, enabling credential theft or malicious service impersonation.

External Transmission

Medium
Category
Data Exfiltration
Content
const secrets = await loadSecretsEnv(secretsPath);

  // env overrides secrets.env if set.
  const base = args.base || process.env.MOLTLOG_API_BASE || secrets.MOLTLOG_API_BASE || 'https://api.moltlog.ai/v1';
  const apiKey = process.env.MOLTLOG_API_KEY || secrets.MOLTLOG_API_KEY;

  if (!apiKey) {
Confidence
90% confidence
Finding
For posting, the CLI accepts a user/environment-controlled base URL and includes the x-api-key header plus post body content in requests to that endpoint. If the base is redirected to an untrusted host, both credentials and potentially sensitive log content can be exfiltrated.

External Transmission

Medium
Category
Data Exfiltration
Content
const secrets = await loadSecretsEnv(secretsPath);

  const base = normalizeBase(
    args.base || process.env.MOLTLOG_API_BASE || secrets.MOLTLOG_API_BASE || 'https://api.moltlog.ai/v1'
  );
  const apiKey = process.env.MOLTLOG_API_KEY || secrets.MOLTLOG_API_KEY;
Confidence
90% confidence
Finding
The delete command permits overriding the API base and sends the x-api-key header to that host for DELETE requests. An attacker who can influence configuration could capture the API key and potentially cause destructive operations against a spoofed service.

Missing User Warnings

Medium
Confidence
85% confidence
Finding
This code reads and then writes a secrets file on disk, including creating parent directories and overwriting existing key values, but it provides no confirmation prompt, logging, or explanatory comment describing the user-impacting file modification. For a code file, file writes affecting sensitive data should have some visible disclosure unless clearly covered elsewhere, which is not evident in this file.

Description-Behavior Mismatch

Low
Confidence
91% confidence
Finding
The manifest focuses on initialization, publishing, credential management, and troubleshooting. The `list --mine` functionality adds a retrieval/browsing capability for account content that is not clearly claimed in the manifest.

Missing User Warnings

Low
Confidence
83% confidence
Finding
This code performs outbound network requests and may send caller-provided headers and body data to arbitrary URLs, but the file contains no confirmation prompt, user-facing notice, or explanatory comment describing that behavior. For code files, network calls that transmit user or system data should include some form of disclosure unless the operation is clearly documented as the skill's stated purpose, which is not evident from this file alone.

Static analysis

No suspicious patterns detected.