Back to skill

Security audit

AVI Assess

Security checks for vulnerabilities and agentic risk

Overview

This autonomy scoring skill is related to its stated purpose, but it reads sensitive workspace/config files and modifies workspaces during supposedly read-only assessments.

Install only if you are comfortable with the skill scanning an agent workspace and local OpenClaw configuration, including memory files and credential-bearing JSON files. Do not run it against another agent's or sensitive production workspace unless the directory is isolated and backed up. Treat readOnly as incomplete, and do not publish generated reports to IPFS or registries without reviewing and redacting identifiers such as hostname, wallet address, email, channels, and provider inventory.

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

Warning
Location
scripts/assess.js:116
Finding
Excessive Inspection of Credentials, Agent Memory, and Global Configuration<![CDATA[ ## Vulnerability Details **File Location**: `scripts/assess.js:116-148`, `scripts/assess.js:186-208`, `scripts/assess.js:246-253`, `scripts/assess.js:272-297`, `scripts/assess.js:386-400` **Vulnerability Type**: Excessive access to sensitive local data **Risk Level**: Medium ### Vulnerable Code ```javascript // Check wallet credentials const walletFiles = this.findFiles(this.config.workspace, /wallet|credentials/i); if (walletFiles.length > 0) { evidence.proof.walletFiles = walletFiles.map(f => path.basename(f)); points += 10; } // Check for Bankr credentials const bankrCreds = this.safeReadJson(path.join(this.config.workspace, 'bankr-credentials.json')); if (bankrCreds?.api_key) { evidence.proof.bankrConfigured = true; points += 15; } // Check for x402 wallet const x402Wallet = this.safeReadJson(path.join(this.config.workspace, 'x402-wallet.json')); if (x402Wallet?.address) { evidence.proof.x402Wallet = x402Wallet.address; points += 10; } // Check for on-chain identity const memoryPath = path.join(this.config.workspace, 'MEMORY.md'); if (memoryPath && fs.existsSync(memoryPath)) { const memory = fs.readFileSync(memoryPath, 'utf8'); if (memory.includes('ERC-8004') && memory.includes('0x')) { evidence.proof.onChainIdentity = 'ERC-8004 registered'; points += 20; } const txMatches = memory.match(/transaction|transfer|swap|bridge/gi); if (txMatches && txMatches.length > 5) { evidence.proof.transactionHistory = `${txMatches.length} TX references`; points += 15; } } ``` ```javascript // Check gateway config for channels const gatewayConfig = this.safeReadJson(this.config.openclawConfig); const channels = gatewayConfig?.channels || {}; const activeChannels = Object.keys(channels).filter(k => channels[k]?.enabled !== false); evidence.proof.channels = activeChannels; points += Math.min(25, activeChannels.length * 8); // Check for email capability const protonCreds = this.safeReadJson(path.join(this.config.workspa ...[truncated 3591 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Make all credential, memory, and global-configuration probes explicitly opt-in. 2. Require informed consent before assessing a workspace owned by another Agent. 3. Enforce an allowlist or trusted-root boundary for workspace paths. 4. Do not parse API-key or password values. Use a credential manager that exposes only a boolean configuration status. 5. If ordinary files must be checked, inspect only file existence and permissions rather than file contents. 6. Replace full `MEMORY.md` parsing with a dedicated, minimal assessment manifest containing non-sensitive capability declarations. 7. Redact wallet addresses, email addresses, credential filenames, and communication channels from reports by default. 8. Document every file and configuration location that the assessment may access before execution. 9. Isolate cross-Agent assessments in a process that has read access only to an approved assessment manifest. 10. Clear references to parsed sensitive data promptly and avoid verbose output that could expose derived identity information. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/assess.js:353
Finding
Read-Only Assessment Still Writes to and Deletes a Target Workspace File<![CDATA[ ## Vulnerability Details **File Location**: `scripts/assess.js:55-59`, `scripts/assess.js:353-359`; documented behavior in `SKILL.md:73-77` **Vulnerability Type**: Unsafe temporary-file handling and violation of read-only semantics **Risk Level**: Medium ### Vulnerable Code ```javascript const report = await verifier.runFullAssessment(); if (!options.readOnly) { verifier.saveReport(report); } return report; ``` ```javascript // Check file system access try { const testFile = path.join(this.config.workspace, '.avi-test'); fs.writeFileSync(testFile, 'test'); fs.unlinkSync(testFile); evidence.proof.fileSystemAccess = 'read/write'; points += 20; } catch { evidence.proof.fileSystemAccess = 'limited'; } ``` The documented cross-Agent usage states: ```javascript const report = await assess_autonomy({ workspace: '/other/agent/workspace', readOnly: true // Don't write to their files }); ``` ### Technical Analysis The `readOnly` option controls only whether the final report is saved. It is not passed to or checked by the operational file-access probe. Consequently, every assessment attempts to create and delete a fixed `.avi-test` path inside the selected workspace, including assessments explicitly requested as read-only. `fs.writeFileSync()` uses overwrite behavior by default. If `.avi-test` already exists, its contents are replaced with `test`, after which the file is deleted. This can destroy a legitimate pre-existing file. A fixed filename also creates collision and race risks when multiple assessments run concurrently. If deletion fails after creation, the test artifact may remain in the target workspace. Creation, modification, and deletion may also trigger file watchers or other automation. ### Attack Path 1. A target workspace contains an existing `.avi-test` file, or it uses automation that watches filesystem changes. 2. A user invokes cross-Agent verification with `readOnly: true`. 3. `runFullAssessment()` calls `assess ...[truncated 1049 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Skip all write probes when `config.readOnly` is true. 2. Propagate the effective read-only setting into the `AutonomyVerifier` instance and enforce it centrally. 3. Never use a fixed filename for capability tests. 4. If a write test is authorized, create a randomized file with exclusive-create semantics such as the `wx` flag. 5. Use a dedicated temporary directory rather than the assessed workspace where possible. 6. Perform cleanup in a `finally` block. 7. Confirm that a path does not exist before creation and never overwrite an existing file. 8. Resolve and validate the workspace path before conducting filesystem operations. 9. Add tests proving that read-only assessments produce no filesystem changes. 10. Update the documentation if any unavoidable writes remain; read-only must not be claimed unless it is fully enforced. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/assess.js:84
Finding
Sensitive Identity and Host Metadata Is Persisted and May Be Published Through the Documented Workflow<![CDATA[ ## Vulnerability Details **File Location**: `scripts/assess.js:84-108`, `scripts/assess.js:130-134`, `scripts/assess.js:285-289`; external publication example in `SKILL.md:83-91` **Vulnerability Type**: Plaintext sensitive metadata exposure **Risk Level**: Medium ### Vulnerable Code ```javascript return { assessmentId: this.assessmentId, overallScore, tier: tier.level, tierName: tier.name, verifiedAt: this.timestamp, dimensions: { financial, temporal, informational, social, operational }, limitations: this.limitations, system: { platform: this.detectPlatform(), openclawVersion: this.getOpenclawVersion(), nodeVersion: process.version, hostname: require('os').hostname() } }; ``` ```javascript saveReport(report) { if (!fs.existsSync(this.config.outputDir)) { fs.mkdirSync(this.config.outputDir, { recursive: true }); } const outputPath = path.join(this.config.outputDir, `${report.assessmentId}.json`); fs.writeFileSync(outputPath, JSON.stringify(report, null, 2)); return outputPath; } ``` ```javascript // Check for x402 wallet const x402Wallet = this.safeReadJson(path.join(this.config.workspace, 'x402-wallet.json')); if (x402Wallet?.address) { evidence.proof.x402Wallet = x402Wallet.address; points += 10; } ``` ```javascript // Check for email capability const protonCreds = this.safeReadJson(path.join(this.config.workspace, 'proton-credentials.json')); if (protonCreds?.email) { evidence.proof.email = protonCreds.email; points += 15; } ``` The documented external-publication workflow is: ```javascript const report = await assess_autonomy({ workspace: './' }); // Submit to AVI Registry (NEAR, Ethereum, etc.) await submit_to_registry({ agent_id: 'my-agent.near', assessment: report, proof_cid: await upload_to_ipfs(report) }); ``` ### Technical Analysis Assessment reports can contain hostname, operating-system type and release, architecture, Node.js version, OpenClaw version, wallet address ...[truncated 2346 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not persist reports by default; require explicit export consent. 2. Generate separate private and public report formats. 3. Limit public reports to the score, tier, timestamp, verifier identifier, methodology version, and cryptographic commitments. 4. Remove hostname, OS release, runtime versions, email address, wallet address, channel names, and credential-provider details from public output. 5. Replace raw addresses with opt-in, truncated, or cryptographically committed identifiers where verification requires them. 6. Create report directories and files with restrictive permissions, such as directory mode `0700` and file mode `0600`. 7. Warn users before any report is uploaded to IPFS or another immutable service. 8. Require a redaction preview and explicit confirmation before external publication. 9. Document data-retention and deletion behavior. 10. Add schema-level allowlisting so newly collected fields cannot silently enter the public proof object. ]]>
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
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (22)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The documented purpose says the skill measures five autonomy dimensions, but the detected behavior includes host probing, system metadata collection, filesystem write/delete tests, and writing reports by default. That mismatch is dangerous because users may authorize what seems like a scoring utility without realizing it performs environment reconnaissance and persistent writes, which can expose sensitive host details and modify data unexpectedly.

Ae1

High
Category
analysis-evasion
Content
const { assess_autonomy } = require('./scripts/assess.js');
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
const { assess_autonomy } = require('./scripts/assess.js');
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/cli.js
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Credential Access

High
Category
Privilege Escalation
Content
}

    // Check for Bankr credentials
    const bankrCreds = this.safeReadJson(path.join(this.config.workspace, 'bankr-credentials.json'));
    if (bankrCreds?.api_key) {
      evidence.proof.bankrConfigured = true;
      points += 15;
Confidence
94% confidence
Finding
The code reads wallet and API credential files from the workspace to score financial capability. For an autonomy assessment skill, inspecting secrets is contextually more dangerous because the task can be accomplished by checking declared capabilities or presence of config metadata rather than opening sensitive credential stores.

Credential Access

High
Category
Privilege Escalation
Content
}

    // Check for email capability
    const protonCreds = this.safeReadJson(path.join(this.config.workspace, 'proton-credentials.json'));
    if (protonCreds?.email) {
      evidence.proof.email = protonCreds.email;
      points += 15;
Confidence
92% confidence
Finding
The skill reads proton-credentials.json and extracts the email field to include in the report evidence. This unnecessarily accesses sensitive account configuration and may expose identifiers in generated output, increasing privacy and targeting risk.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
The operational assessment verifies filesystem access by creating and deleting a file in the target workspace. This is an active modification of user data space that is not necessary for a scoring tool and can cause integrity issues, trigger watchers/automation, or fail in sensitive directories.

Credential Access

High
Category
Privilege Escalation
Content
findApiKeys() {
    const keys = [];
    const patterns = [
      { file: 'bankr-credentials.json', key: 'api_key', name: 'Bankr' },
      { file: 'xai-credentials.json', key: 'api_key', name: 'xAI' },
      { file: 'chainalysis-credentials.json', key: 'api_key', name: 'Chainalysis' },
      { file: 'proton-credentials.json', key: 'password', name: 'ProtonMail' }
Confidence
95% confidence
Finding
The findApiKeys routine enumerates known credential files and inspects secret-bearing keys to determine which services are configured. This establishes a broad secret-discovery behavior that is disproportionate to the stated purpose and could be repurposed to inventory high-value services present in the workspace.

Credential Access

High
Category
Privilege Escalation
Content
const keys = [];
    const patterns = [
      { file: 'bankr-credentials.json', key: 'api_key', name: 'Bankr' },
      { file: 'xai-credentials.json', key: 'api_key', name: 'xAI' },
      { file: 'chainalysis-credentials.json', key: 'api_key', name: 'Chainalysis' },
      { file: 'proton-credentials.json', key: 'password', name: 'ProtonMail' }
    ];
Confidence
95% confidence
Finding
Including xAI credential file inspection as part of routine assessment broadens the set of secrets the skill probes. In the context of a marketplace or reputation-oriented assessment tool, this is especially risky because users may not expect the tool to inspect and infer their integrated providers from secret files.

Credential Access

High
Category
Privilege Escalation
Content
const patterns = [
      { file: 'bankr-credentials.json', key: 'api_key', name: 'Bankr' },
      { file: 'xai-credentials.json', key: 'api_key', name: 'xAI' },
      { file: 'chainalysis-credentials.json', key: 'api_key', name: 'Chainalysis' },
      { file: 'proton-credentials.json', key: 'password', name: 'ProtonMail' }
    ];
Confidence
95% confidence
Finding
The code also probes for chainalysis credentials, contributing to a pattern of secret inventorying across multiple providers. Such enumeration can reveal sensitive operational relationships and security posture even if raw secrets are not exfiltrated.

Credential Access

High
Category
Privilege Escalation
Content
{ file: 'bankr-credentials.json', key: 'api_key', name: 'Bankr' },
      { file: 'xai-credentials.json', key: 'api_key', name: 'xAI' },
      { file: 'chainalysis-credentials.json', key: 'api_key', name: 'Chainalysis' },
      { file: 'proton-credentials.json', key: 'password', name: 'ProtonMail' }
    ];

    for (const pattern of patterns) {
Confidence
96% confidence
Finding
Checking proton-credentials.json for a password field is direct inspection of a sensitive secret store. Even though the code only records the provider name, reading password-bearing files for scoring is an unjustified access to credentials and increases exposure if the code is later modified, logged, or reused.

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill advertises executable examples that reference environment-derived paths like OPENCLAW_WORKSPACE but does not declare any explicit tool or permission scope. This creates unclear execution boundaries for a skill that appears to inspect a workspace and potentially infer host capabilities, increasing the risk of overbroad access or unintended data exposure when run by an agent framework.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill explicitly describes submitting assessment data to a registry and uploading proof to IPFS, but it provides no warning that this transmits potentially sensitive assessment and system-derived data to external, possibly immutable destinations. In the context of a skill that may collect workspace and host metadata, this omission can lead to unintentional disclosure and permanent publication of operational details.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The skill writes a report to disk by default unless readOnly is set, causing persistent filesystem modification without strong disclosure at the API boundary. In assessment tooling, unexpected writes can leak environment details, clutter workspaces, and violate expectations of read-only analysis.

Description-Behavior Mismatch

Medium
Confidence
94% confidence
Finding
The manifest explicitly defines the AVI framework dimensions as Decision, Financial, Information, Communication, and Temporal. The code never implements a decision dimension and substitutes operational/social categories instead, so the produced score does not match the claimed framework semantics.

Context-Inappropriate Capability

Medium
Confidence
90% confidence
Finding
The assessment invokes local shell commands via execSync to probe for installed tools, which expands the skill's authority beyond passive scoring into command execution on the host. Even though the commands are fixed strings, this still creates unnecessary execution side effects, depends on PATH resolution, and increases risk in a skill whose stated purpose is assessment rather than system interrogation.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The write/delete test modifies the workspace without explicit disclosure, which is unsafe for a skill presented as an assessor. Even if the file is removed, the side effect can trigger build hooks, file monitors, backups, or audit trails and therefore exceeds expected read-only behavior.

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.