Back to skill

Security audit

PropAI Live

Security checks for vulnerabilities and agentic risk

Overview

This skill is coherent for realtor automation, but it should go through Review because it combines high-impact messaging/social workflows with under-scoped command authority and weakly disclosed license credential handling.

Install only if you trust the publisher, the bundled dependencies, and the license API endpoint you configure. Use the documented HTTPS production endpoint or a trusted local development endpoint, avoid passing license keys to untrusted or plain-HTTP servers, review connected WhatsApp/Meta/lead-storage permissions, and require explicit confirmation before any message sending, posting, spending, or data mutation.

Vulnerability Patterns
  • 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
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
Findings (6)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/license-guard.mjs:64
Finding

License Enforcement Can Be Bypassed Using a Forged Local State File

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/license-activate.mjs:62
Finding

Arbitrary or Insecure License API Endpoints Can Receive License Credentials

Content
View full analysis
controller.abort(), timeoutMs); try { const response = await fetch(url, { method: "POST", headers: { "content-type": "application/json", accept: "application/json", }, body: JSON.stringify(payload), signal: controller.signal, }); const text = await response.text(); // ... return { ok: response.ok, status: response.status, data, text }; } finally { clearTimeout(timer); } } ``` ### Technical Analysis The base URL is only normalized by removing trailing slashes. The client does not: - Parse and validate the URL - Require HTTPS - Restrict the host to a trusted production domain - Restrict HTTP development endpoints to loopback addresses - Present a trust warning before persisting a custom endpoint Activation sends the raw license key to th ...[truncated 1554 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/license-lib.mjs:127
Finding

Plaintext Bearer Token Is Stored Without Explicitly Restrictive Permissions

Content
View full analysis
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
assets/license-api/src/license-service.mjs:112
Finding

Concurrent Activation Requests Can Exceed the License Seat Limit

Content
View full analysis
= license.seatLimit) { await logAudit(client, license.id, "activate_failed", { reason: "seat_limit_reached", machineId, activeSeatCount, seatLimit: license.seatLimit, }); throw serviceError("seat_limit_reached", "Seat limit reached for this license."); } } await client.query( ` INSERT INTO activations (license_id, machine_id, machine_label, last_seen_at, revoked_at) VALUES ($1, $2, $3, NOW(), NULL) ON CONFLICT (license_id, machine_id) DO UPDATE SET machine_label = EXCLUDED.machine_label, last_seen_at = NOW(), revoked_at = NULL `, [license.id, machineId, machineLabel || null], ); ``` ### Technical Analysis The seat count and activation insertion are separate operations. The surrounding transaction does not lock the license row, lock a shared quota record, or use serializable transaction isolation. Under PostgreSQL's typical `READ COMMITTED` isolation, two transactions can both: 1. Determine that their distinct machine IDs do not already exist. 2. Count the same number of active seats. 3. Determine that a seat remains available. 4. Insert separate activation rows. The unique constraint only covers `(license_id, machine_id)`, so it does not prevent different machine ...[truncated 740 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
assets/license-api/src/server.mjs:38
Finding

Public License Activation Endpoint Lacks Brute-Force and Abuse Controls

Content
View full analysis
{ try { const body = req.body || {}; const data = await activateLicense({ key: body.key, product: body.product, machineId: body.machineId, machineLabel: body.machineLabel, clientVersion: body.clientVersion, runtime: body.runtime, }); res.json(data); } catch (error) { sendInvalid(res, error, mapErrorToStatus(error.code)); } }); ``` ```js const host = process.env.LICENSE_API_HOST || "0.0.0.0"; const port = Number(process.env.LICENSE_API_PORT || 8787); const server = app.listen(port, host, () => { process.stdout.write( `propai-live-license-api listening on http://${host}:${port}\n`, ); }); ``` ### Technical Analysis The server listens on all interfaces by default and exposes an activation endpoint that verifies submitted license keys. No application-level controls are implemented for: - Per-IP rate limiting - Per-key or key-prefix throttling - Progressive delay - Temporary lockout - Request-size-aware concurrency limits - Global abuse protection - Authentication at a reverse proxy - Audit-log volume control The route also returns distinguishable status codes and error types, such as `license_not_found`, `seat_limit_reached`, and inactive-license errors. These responses can act as an oracle during automated probing. Failed requests may create audit records, allowing high-volume traffic to consume database storage and transaction capacity. ### Attack Path 1. Connect to the server on its externally reachable interface. 2. Generate candidate license keys. 3. Submit candidates repeatedly to `/v1/licenses/activate`. 4. Us ...[truncated 602 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Note
Location
assets/license-api/package.json:13
Finding

Runtime Dependencies Are Not Reproducibly Locked

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • 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 (10)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/license-activate.mjs --key <LICENSE_KEY> --api <LICENSE_API_BASE_URL>

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill invokes local scripts and operational commands, including license checks and write guards, but does not declare any explicit tool scope such as permissions or allowed-tools. That mismatch can cause an agent runtime to grant broader command or environment access than reviewers expect, increasing the chance of unintended command execution or access to sensitive environment data.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The code performs remote license validation by sending a payload containing machineId, licenseToken, and licenseId to the validate endpoint. Although this is functionally expected for license checking, this file provides no confirmation prompt, user-facing notice, or explanatory comment/docstring disclosing that local machine and license data will be transmitted.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The code derives a machine ID from hostname, platform, architecture, and username, which are system-identifying attributes. This file also contains HTTP POST logic, but there is no confirmation prompt, user-facing log, or explanatory comment/docstring in the code warning that such system data may be sent to a remote license service.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The postJson function sends arbitrary JSON payloads over the network, and elsewhere in this file the payload is likely to include license and machine-identifying information. There is no confirmation prompt, print/log statement, or explanatory comment/docstring here warning users that license validation performs remote network calls transmitting local or user-linked data.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
97% confidence
Finding

The dependency uses a caret range (^4.21.2), which allows automatic installation of newer minor and patch releases instead of a fully fixed version. This weakens build reproducibility and can unintentionally introduce vulnerable or behavior-changing releases into a server-side API component.

Content

Scanner excerpt · assets/license-api/package.json (reported line 14)May include surrounding context.

json
"migrate": "node scripts/migrate.mjs"
  },
  "dependencies": {
    "express": "^4.21.2",
    "pg": "^8.16.3"
  }
}

Unverifiable Dependency: express has 5 known advisory(ies) (CVE-2024-10491 (Express ressource injection); CVE-2014-6393 (No Charset in Content-Type Header in express); CVE-2024-9266 (Express Open Redirect vulnerability) +2 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
88% confidence
Finding

Express has known advisories, and because the manifest uses a version range rather than an exact pinned release, it is not possible to verify from this file alone whether the deployed version is affected. In a network-exposed API service, unverifiable dependency state increases the chance that a vulnerable Express release could be installed unnoticed.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
97% confidence
Finding

The pg dependency is specified with a caret range (^8.16.3), so different installs may resolve to different releases over time. For a license API that likely handles backend data and authentication-related logic, this creates supply-chain and reproducibility risk even if no specific exploit is present in the manifest itself.

Content

Scanner excerpt · assets/license-api/package.json (reported line 15)May include surrounding context.

json
},
  "dependencies": {
    "express": "^4.21.2",
    "pg": "^8.16.3"
  }
}

Unverifiable Dependency: pg has 1 known advisory(ies) (CVE-2017-16082 (Remote Code Execution in pg)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
85% confidence
Finding

The pg package has historical security advisories, but the exact installed version cannot be verified from this manifest because the dependency is not strictly pinned. Since this appears to be a backend API template that likely connects to PostgreSQL, uncertainty around the actual client version represents a real but low-severity supply-chain risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

The code creates directories, writes a license-state.json file, renames temporary files into place, and can delete the state file. Although these operations are part of license-state management, this file contains no user-facing log, prompt, or explanatory comment/docstring disclosing that persistent local state will be stored and removed under the user's home directory or configured state directory.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.env_credential_access

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/license-lib.mjs:111