Back to skill

Security audit

Ai Bill Clawhub

Security checks for vulnerabilities and agentic risk

Overview

This billing dashboard has a coherent purpose, but it exposes and can modify sensitive usage and balance data with weak controls and includes risky installer/persistence behavior.

Install only after reviewing and tightening deployment: bind the server to localhost or put it behind real authentication, do not expose port 8003 publicly, remove or restrict /api/setup and vault access, avoid the pipe-to-shell installer, pin and verify install artifacts, and make any systemd/background service installation an explicit opt-in with clear uninstall steps.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (6)

T03 · Remote Payload Retrieval and Execution

Error
Location
app/installer.sh:34
Finding

Unpinned Remote Payload Installation with Persistent System Services

Content
View full analysis
/dev/null; then wget -q https://github.com/fumabot16-max/project-bill/archive/refs/heads/master.zip -O master.zip elif command -v curl &> /dev/null; then curl -fsSL https://github.com/fumabot16-max/project-bill/archive/refs/heads/master.zip -o master.zip else echo "❌ Error: wget or curl required" exit 1 fi # 3. Extract echo "📦 Extracting..." unzip -q master.zip mv project-bill-master/* . mv project-bill-master/.* . 2>/dev/null || true rm -rf project-bill-master master.zip # 4. Install dependencies echo "📦 Installing dependencies..." npm install --silent ``` ```bash if command -v systemctl &> /dev/null; then # Linux with systemd sudo cp systemd/*.service /etc/systemd/system/ sudo systemctl daemon-reload sudo systemctl enable ai-bill ai-bill-collector sudo systemctl start ai-bill ai-bill-collector ``` The installer also explicitly promotes execution through a shell pipeline: ```bash # Usage: curl -fsSL [URL] | bash ``` ### Technical Analysis The installer downloads the mutable `master` branch of a personal GitHub repository without pinning a commit, checking a cryptographic digest, or verifying a signature. The downloaded archive is extracted into the Skill directory and followed by `npm install`, which can execute package lifecycle scripts contained in the remotely supplied package. The same remotely supplied repository is expected to contain systemd unit files. Those files are copied with `sudo` into `/etc/systemd/system`, enabled at startup, and started. This creates a direct path from ...[truncated 1757 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
app/server.js:37
Finding

Unauthenticated Network Access to Billing Data and Configuration

Content
View full analysis
{ try { const vaultPath = path.join(__dirname, 'vault.json'); if (!fs.existsSync(vaultPath)) return res.json({}); const vault = JSON.parse(fs.readFileSync(vaultPath, 'utf8')); res.json(vault); } catch (error) { res.status(500).json({ error: error.message }); } }); // API: Save setup app.post('/api/setup', (req, res) => { try { const vaultPath = path.join(__dirname, 'vault.json'); const fields = ['openai', 'claude', 'kimi', 'deepseek', 'groq', 'xai', 'minimax', 'mistral', 'qwen', 'glm', 'llama', 'gemini']; const data = {}; fields.forEach(f => { if (req.body[f] && typeof req.body[f] === 'object') { data[f] = { balance: parseFloat(req.body[f].balance) || 0, mode: req.body[f].mode || 'prepaid' }; } else { data[f] = { balance: parseFloat(req.body[f]) || 0, mode: 'prepaid' }; } }); fs.writeFileSync(vaultPath, JSON.stringify(data, null, 2)); res.json({ status: 'success', message: 'Configuration saved' }); } catch (error) { res.status(500).json({ status: 'error', message: error.message }); } }); ``` ```js app.get('/usage.json', (req, res) => { res.sendFile(path.join(__dirname, 'dist', 'usage.json')); }); ``` ```js app.listen(PORT, () => { console.log(`AI Billing System running on port ${PORT}.`); if (needsSetup()) { console.log('⚠️ First time setup required. Visit http://localhost:8003/setup'); } }); ``` ### Technical Analysis The server has no authentication or authorization middleware. Any party able to reach port 8003 can: - Retrieve provider balances and billing modes through `GET /api/vault`. - R ...[truncated 1671 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
app/simple-server.js:22
Finding

Path Traversal and Arbitrary File Disclosure in Alternate HTTP Server

Content
View full analysis
{ console.log(`${req.method} ${req.url}`); // Set CORS headers res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type'); if (req.method === 'OPTIONS') { res.writeHead(200); res.end(); return; } let filePath = '.' + req.url; ``` ```js // Handle static files const extnameStr = extname(filePath); let contentType = 'text/html'; switch (extnameStr) { case '.js': contentType = 'text/javascript'; break; case '.css': contentType = 'text/css'; break; case '.json': contentType = 'application/json'; break; case '.png': contentType = 'image/png'; break; case '.jpg': contentType = 'image/jpg'; break; case '.ico': contentType = 'image/x-icon'; break; } try { const content = await readFile(filePath); res.writeHead(200, { 'Content-Type': contentType }); res.end(content); ``` ```js server.listen(PORT, '0.0.0.0', () => { console.log(`AI Billing System running on port ${PORT} (IPv4 & IPv6).`); }); ``` ### Technical Analysis The server forms a filesystem path by concatenating `"."` with the raw request URL. It does not: - Parse and remove the query string. - Normalize the path against a fixed document root. - Reject `..` path components. - Resolve and verify canonical containment. - Restrict files to an explicit allowlist. A raw request containing traversal components can therefore cause `readFile()` to access a path outside the application directory. Because the service explicitly binds to `0.0.0.0`, this behavior is exposed t ...[truncated 1221 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
app/collector.js:4
Finding

Root-Owned OpenClaw Metadata Is Republished as Unprotected Web Data

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
app/index.html:78
Finding

Hard-Coded Client-Side PIN Does Not Protect Billing Data

Content
View full analysis
document.getElementById('lock-screen').classList.add('unlocked'), 500); } else { s.innerText="Invalid Code"; s.style.color="#ef4444"; document.getElementById('pass-input').value=""; } } } function changePass() { const cur=document.getElementById('pass-current').value; const n1=document.getElementById('pass-new').value; const n2=document.getElementById('pass-confirm').value; const err=document.getElementById('pass-error'); if(cur!==SECURE_CODE){err.innerText="Current invalid";err.classList.remove('hidden');return;} if(n1.length!==4){err.innerText="Must be 4 digits";err.classList.remove('hidden');return;} if(n1!==n2){err.innerText="Match error";err.classList.remove('hidden');return;} SECURE_CODE=n1; err.classList.add('hidden'); alert("Updated!"); toggleSettings(); } ``` ### Technical Analysis The access code is embedded in JavaScript delivered to every browser. Any user can view the source and recover the default value. Validation occurs entirely in the browser and only changes the visibility of a UI overlay. Changing the PIN updates an in-memory JavaScript variable only. It is not persisted securely and does not create an authenticated server session. Ba ...[truncated 967 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
app/index.html:7
Finding

Unpinned Third-Party Scripts Execute in the Billing Dashboard Origin

Content
View full analysis
``` From `app/public/setup.html`: ```html ``` ### Technical Analysis The dashboard loads executable JavaScript from third-party CDNs at runtime. The URLs are not pinned to immutable versions and do not use Subresource Integrity attributes. A compromised CDN response, DNS/TLS trust-chain failure, or unexpected upstream change would execute with the dashboard's origin privileges. Such a script could call same-origin endpoints, read billing data, modify the setup form, or submit altered provider balances. The remote fonts are not executable JavaScript, but they introduce unnecessary external requests and can disclose client network metadata to third parties. ### Attack Path 1. An attacker compromises a referenced CDN resource or its distribution pipeline. 2. A user visits the dashboard or setup page. 3. The browser downloads and executes the modified script in the billing application's origin. 4. The malicious script requests `/api/vault`, `/usage.json`, or `/api/usage`. 5. It can submit changes to `/api/setup` or transmit accessed data to an attacker-controlled endpoint. ### Impact Assessment A successful supply-chain compromise can expose all data available to the logged-in browser and modify billing c ...[truncated 247 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (47)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
3. **Checking Health**: Ensure the `ai-bill` service and `collector.js` are running.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill writes usage and balance-derived data to files under /var/www/html, making the collected information potentially web-accessible to unintended parties. Exposing model usage, balances, runtime details, and per-brand statistics can leak internal operational patterns and financial information, and the risk is amplified because publication occurs automatically on a timer.

Content

No source excerpt is available for this finding.

External Script Fetching

High
Category
Supply Chain
Confidence
99% confidence
Finding

Advertising usage as curl -fsSL [URL] | bash is an unsafe installation pattern because it streams remote content directly into a shell without inspection or integrity verification. This dramatically increases the blast radius of any server compromise, MITM in weaker setups, or malicious update to the installer.

Content

Scanner excerpt · app/installer.sh (reported line 4)May include surrounding context.

sh
#!/bin/bash

# AI Bill Intelligence - One-line Installer
# Usage: curl -fsSL [URL] | bash

set -e

Chaining Abuse

High
Category
Tool Misuse
Confidence
99% confidence
Finding

The | bash pattern executes unreviewed remote installer content immediately, combining network retrieval and code execution into a single opaque step. In this file's context, that danger is heightened because the script then performs sudo operations, downloads additional code, runs npm install, and establishes persistence.

Content

Scanner excerpt · app/installer.sh (reported line 4)May include surrounding context.

sh
#!/bin/bash

# AI Bill Intelligence - One-line Installer
# Usage: curl -fsSL [URL] | bash

set -e

Chaining Abuse

High
Category
Tool Misuse
Confidence
75% confidence
Finding

Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Content

Scanner excerpt · app/installer.sh (reported line 16)May include surrounding context.

sh
if ! command -v unzip &> /dev/null; then
    echo "📦 Installing unzip..."
    if command -v apt-get &> /dev/null; then
        sudo apt-get update -qq && sudo apt-get install -y -qq unzip
    elif command -v yum &> /dev/null; then
        sudo yum install -y unzip
    elif command -v dnf &> /dev/null; then

Known Vulnerable Dependency: path-to-regexp==0.1.12 — 1 advisory(ies): CVE-2024-45296 (path-to-regexp vulnerable to Regular Expression Denial of Service via multiple r)

High
Category
Supply Chain
Confidence
97% confidence
Finding

path-to-regexp 0.1.12 is a legacy Express dependency and the referenced advisory describes a Regular Expression Denial of Service risk. Because route matching may process attacker-controlled URLs on every request, an exploitable ReDoS in this component can let remote clients consume CPU and significantly disrupt or stall the service.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The README advertises automatic background monitoring of active sessions and immediate access to billing data, but it does not disclose what data is collected, how long it is retained, where it is stored, or what access controls protect it. In a billing and usage-tracking skill, this omission is security-relevant because session metadata and spending records can reveal sensitive usage patterns and may be exposed or mishandled by operators who are not warned about the privacy implications.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
80% 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.

Content

Scanner excerpt · README.md (reported line 34)May include surrounding context.

md
## 📊 Monitoring

The system automatically runs a background collector (`collector.js`) that:
- Scans active sessions for token usage.
- Matches models with their respective pricing in `prices.json`.
- Archives costs when sessions expire to ensure zero data loss and 100% accuracy.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill explicitly suggests updating vault.json on the user's behalf, which can alter billing balances or payment mode configuration without any stated confirmation, authorization, or safety warning. In a billing-related skill, silent modification of financial configuration is sensitive because it could misstate balances, disrupt service behavior, or facilitate unauthorized changes to cost tracking and payment settings.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The code reads broad local files including global agent sessions, runtime configuration, pricing, and vault/balance data without any visible access control, minimization, or stated need boundary. Even if used for billing, this creates unnecessary exposure to sensitive operational and financial information and expands the blast radius if the skill is misused or modified.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The code ingests sensitive session, configuration, and vault-related data and then derives output that is later persisted to web-facing locations, but there is no disclosure, consent, or user-visible indication that this monitoring and publication is occurring. This creates a transparency and privacy problem and can unintentionally expose internal usage patterns tied to agent activity.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The document sets the page language to Korean via lang="ko", which imposes a specific language/locale choice in the UI without any visible user opt-in or explanation. This matches the policy concern for language or locale restrictions that are not optional or clearly justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Line L002 sets the entire document language to Korean via lang="ko", but the visible UI text is otherwise in English and there is no indication that this skill is intentionally region-specific or that users can opt into a locale. This creates a natural-language locale policy concern because the file hard-codes a specific language setting without user choice or documented justification.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
99% confidence
Finding

The 'Secure Access' screen is only enforced in client-side JavaScript with a hardcoded 4-digit code, so it provides no real access control. Any user can view or bypass the protection by inspecting the source, modifying SECURE_CODE at runtime, or disabling the overlay in the browser, which may expose usage/billing data and create a false sense of security.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The installer performs privileged package installation using sudo to modify the host system, but it provides no explicit warning, consent prompt, or clear justification tied to documented skill functionality. In a skill installer context, silent system modification increases risk because users may run it via a one-line pipe-to-shell flow and not realize it will change global packages.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
86% confidence
Finding

This sudo invocation elevates package-management actions on the host system. While sudo is not inherently malicious, using it inside an installer delivered for pipe-to-shell execution raises the risk of unintended privileged changes and abuse if upstream content is compromised.

Content

Scanner excerpt · app/installer.sh (reported line 16)May include surrounding context.

sh
if ! command -v unzip &> /dev/null; then
    echo "📦 Installing unzip..."
    if command -v apt-get &> /dev/null; then
        sudo apt-get update -qq && sudo apt-get install -y -qq unzip
    elif command -v yum &> /dev/null; then
        sudo yum install -y unzip
    elif command -v dnf &> /dev/null; then

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The installer invokes package managers with sudo and noninteractive flags (-y / -qq) without explicit confirmation beyond the package manager's own privilege prompt. This can surprise users and normalize unsafe execution patterns, especially given the advertised curl | bash installation method.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
83% confidence
Finding

This sudo yum install performs privileged system modification as part of an automated installer. In context, the concern is not yum itself but the lack of explicit informed consent and the combination with remotely fetched installer content.

Content

Scanner excerpt · app/installer.sh (reported line 18)May include surrounding context.

sh
if command -v apt-get &> /dev/null; then
        sudo apt-get update -qq && sudo apt-get install -y -qq unzip
    elif command -v yum &> /dev/null; then
        sudo yum install -y unzip
    elif command -v dnf &> /dev/null; then
        sudo dnf install -y unzip
    elif command -v brew &> /dev/null; then

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
83% confidence
Finding

This sudo dnf install similarly performs privileged package installation in an unattended flow. Because the installer is intended for easy one-line execution, this increases the chance of users granting elevated permissions without understanding the system changes.

Content

Scanner excerpt · app/installer.sh (reported line 20)May include surrounding context.

sh
elif command -v yum &> /dev/null; then
        sudo yum install -y unzip
    elif command -v dnf &> /dev/null; then
        sudo dnf install -y unzip
    elif command -v brew &> /dev/null; then
        brew install unzip
    else

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · app/installer.sh (reported line 26)May include surrounding context.

sh
else
        echo "❌ Error: unzip not found and cannot install automatically"
        echo "   Please install unzip manually:"
        echo "   Ubuntu/Debian: sudo apt-get install unzip"
        echo "   macOS: brew install unzip"
        exit 1
    fi

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · app/setup.js (reported line 56)May include surrounding context.

js
else
        echo "❌ Error: unzip not found and cannot install automatically"
        echo "   Please install unzip manually:"
        echo "   Ubuntu/Debian: sudo apt-get install unzip"
        echo "   macOS: brew install unzip"
        exit 1
    fi

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The script downloads an archive from GitHub, extracts it, and runs npm install, which executes externally sourced code and dependency lifecycle scripts from the network without integrity verification. This creates a supply-chain risk where repository compromise, dependency compromise, or unexpected upstream changes can lead to arbitrary code execution on the user's machine.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
91% confidence
Finding

Copying service files into /etc/systemd/system with sudo modifies privileged system configuration. In the context of a downloaded installer, this is sensitive because it establishes trusted execution paths under root-controlled service management.

Content

Scanner excerpt · app/installer.sh (reported line 80)May include surrounding context.

sh
echo "🚀 Setting up services..."
if command -v systemctl &> /dev/null; then
    # Linux with systemd
    sudo cp systemd/*.service /etc/systemd/system/
    sudo systemctl daemon-reload
    sudo systemctl enable ai-bill ai-bill-collector
    sudo systemctl start ai-bill ai-bill-collector

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script copies service units into /etc/systemd/system, enables them for persistence, and starts them immediately without prior user confirmation or a description of their runtime behavior. Background persistence materially increases risk because any flaw or malicious change in the installed application will continue executing across reboots.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
88% confidence
Finding

sudo systemctl daemon-reload refreshes the system service manager after adding new units, which is part of a privileged persistence setup. The command is not harmful by itself, but within this installer it contributes to an unprompted privileged service installation flow.

Content

Scanner excerpt · app/installer.sh (reported line 81)May include surrounding context.

sh
if command -v systemctl &> /dev/null; then
    # Linux with systemd
    sudo cp systemd/*.service /etc/systemd/system/
    sudo systemctl daemon-reload
    sudo systemctl enable ai-bill ai-bill-collector
    sudo systemctl start ai-bill ai-bill-collector
    echo "✅ Services started!"

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
app/setup.js:14