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## 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
## Remediation Suggestions 1. Create the credentials directory with owner-only permissions: ```js mkdirSync(CREDS_DIR, { recursive: true, mode: 0o700, }); ``` 2. Write the credential file with mode `0600`: ```js writeFileSync( CREDS_FILE, JSON.stringify(creds, null, 2), { encoding: 'utf8', mode: 0o600, }, ); ``` 3. 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); ``` 4. 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. 5. 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'); } ``` 6. 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. 7. 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)

Lp3

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.

Session Persistence

Medium
Category
Rogue Agent
Content
---
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
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.

Missing User Warnings

Medium
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.

External Transmission

Medium
Category
Data Exfiltration
Content
## 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"}'
```
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.

Missing User Warnings

Medium
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.

Missing User Warnings

Medium
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.

Static analysis

No suspicious patterns detected.