Back to skill

Security audit

Quack Identity

Security checks for vulnerabilities and agentic risk

Overview

The skill does what it claims, but it creates a public identity and stores an API key locally without strong containment while also printing part of that key.

Review before installing if you use shared machines, logged terminals, CI, or recorded agent sessions. Running the registration command publishes an agent profile and stores a Quack API key under ~/.openclaw/credentials/quack.json; protect that file, avoid sharing status output, and delete or rotate the credential if you no longer want the identity active.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/register.mjs:65
Finding

Insecure API Credential Storage and Partial Secret Disclosure

Content
View full analysis

Vulnerability Details

File Locations:

  • scripts/register.mjs:30-36
  • scripts/register.mjs:65-74
  • scripts/check.mjs:22-24

Vulnerability Type: Insecure storage and disclosure of API credentials
Risk Level: Medium

Technical Analysis

The registration script stores an API key in ~/.openclaw/credentials/quack.json without explicitly applying restrictive filesystem permissions:

js
// Save credentials
if (data.apiKey || data.agentId) {
  mkdirSync(CREDS_DIR, { recursive: true });
  const creds = {
    agentId: data.agentId || args.agentId,
    apiKey: data.apiKey || null,
    badge: data.badge || null,
    quckGrant: data.quckGrant || 0,
    registeredAt: new Date().toISOString(),
  };
  writeFileSync(CREDS_FILE, JSON.stringify(creds, null, 2));
  console.log(`Credentials saved to ${CREDS_FILE}`);
}

Because neither mkdirSync nor writeFileSync specifies a mode, effective permissions depend on the process umask and existing path permissions. Common defaults may create the directory as 0755 and the file as 0644, potentially allowing other local users to read the complete API key on a shared system.

The registration script also prints the first 12 characters of an existing API key:

js
if (existsSync(CREDS_FILE)) {
  const existing = JSON.parse(readFileSync(CREDS_FILE, 'utf8'));
  console.log(`Already registered as ${existing.agentId}`);
  console.log(`API Key: ${existing.apiKey?.substring(0, 12)}...`);
  console.log('To re-register, delete ~/.openclaw/credentials/quack.json first.');
  return;
}

The status-checking script repeats this disclosure:

js
if (creds.apiKey) {
  console.log(`   API Key:     ${creds.apiKey.substring(0, 12)}...`);
}

Terminal output may be retained in shell logs, CI logs, agent transcripts, or monitoring systems. Revealing a key prefix is unnecessary for checking registration status and can facilitate credential correlation, identification, or attacks against weak or predictable token ...[truncated 1763 chars]

Remediation
View remediation

Remediation Suggestions

  1. Create the credentials directory with owner-only permissions:
js
mkdirSync(CREDS_DIR, {
  recursive: true,
  mode: 0o700,
});
  1. Write the credential file with mode 0600:
js
writeFileSync(
  CREDS_FILE,
  JSON.stringify(creds, null, 2),
  {
    encoding: 'utf8',
    mode: 0o600,
  },
);
  1. Explicitly tighten permissions on pre-existing paths, because creation modes do not correct permissions on files or directories that already exist:
js
import { chmodSync } from 'fs';

chmodSync(CREDS_DIR, 0o700);
chmodSync(CREDS_FILE, 0o600);
  1. Avoid following attacker-controlled symbolic links. Validate the destination and use exclusive or atomic file creation where practical, such as writing securely to a same-directory temporary file and renaming it into place.

  2. Remove all API-key prefix output. Report only whether a credential exists:

js
console.log(`API Key: ${existing.apiKey ? 'configured' : 'not configured'}`);
js
if (creds.apiKey) {
  console.log('   API Key:     configured');
}
  1. Document that the file contains a sensitive bearer credential and should not be copied into source control, logs, diagnostics, backups without access controls, or agent transcripts.

  2. Consider using an operating-system credential store instead of a plaintext JSON file when the supported runtime environment provides one.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (6)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill includes commands that perform network operations, but the manifest does not declare any tool scope such as permissions or allowed-tools. This creates a transparency and policy-enforcement gap: an agent or user may invoke a skill that reaches external services without an explicit declaration that network access is required.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
88% confidence
Finding

The skill is explicitly designed to create a persistent public identity and store related registration state, which introduces session persistence and long-lived exposure. In context this is intentional functionality, but it remains security-sensitive because it establishes durable credentials and a discoverable public profile that may outlive the user's immediate intent.

Content

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

md
---
name: quack-identity
description: Register on the Quack Network and create a public Agent Card profile. Use when registering a new agent, creating an agent profile, checking registration status, or claiming a Quack identity. Triggers on "register on quack", "create agent card", "agent identity", "quack registration", "agent profile".
---

# Quack Identity

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill tells users to register and notes that credentials are saved locally and a public Agent Card is created, but it does not present these as explicit security/privacy warnings before execution. Users may unknowingly publish an identity profile and persist credentials to disk without understanding the privacy and secret-management implications.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

The skill provides a direct example of transmitting agent identity data to an external third-party endpoint over the network. While this appears necessary for registration, it is still a real security-relevant behavior because it sends potentially identifying metadata off-host and depends on an external service outside the local trust boundary.

Content

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

Manual Registration (curl)

bash
curl -X POST "https://agent-card-builder.replit.app/api/register" \
  -H "Content-Type: application/json" \
  -d '{"agentId":"myagent/main","platform":"openclaw"}'

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This script reads a local credentials file and prints identifying registration details plus a prefix of the API key to stdout. Even partial secret disclosure is risky because terminal output may be logged, captured in CI, shared in screenshots, or exposed to other local observers, and revealing the key prefix aids credential correlation and validation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script stores a returned API key in ~/.openclaw/credentials/quack.json without warning the user, restricting file permissions, or using a secure secret store. On multi-user systems, shared environments, backups, or when the home directory is broadly readable, this can expose the credential and allow unauthorized use of the Quack identity or associated API access.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.