Back to skill

Security audit

Zernio CLI

Security checks for vulnerabilities and agentic risk

Overview

The CLI appears aligned with its social-media management purpose, but it needs review because it can publish/delete external content and handles API credentials with weak safeguards.

Install only if you are comfortable giving this CLI authority to read account data, upload selected media files, and create, schedule, retry, or delete social-media posts through your Zernio account. Prefer using a tightly scoped API key, keep ~/.zernio/config.json private, avoid custom API URLs unless they are trusted HTTPS endpoints, confirm post/profile IDs before deletion, and verify local media paths before upload.

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

T09 · Insecure Skill Coding Practices

Warning
Location
src/utils/config.ts:46
Finding

API Key Stored Without Restrictive Filesystem Permissions

Content
View full analysis
): void { const existing = readJsonConfig(CONFIG_FILE); const merged = { ...existing, ...updates }; if (!existsSync(CONFIG_DIR)) { mkdirSync(CONFIG_DIR, { recursive: true }); } writeFileSync(CONFIG_FILE, JSON.stringify(merged, null, 2) + '\n', 'utf-8'); } ``` ### Technical Analysis The `writeConfig` function stores the Zernio API key in `~/.zernio/config.json` without specifying restrictive permissions for either the configuration directory or file. When Node.js creates the file, its effective permissions are derived from the default creation mode and the process umask. On commonly configured Unix-like systems, this can result in a mode such as `0644`, allowing other local users to read the file. The implementation also does not repair an existing configuration file that already has insecure permissions. The API key is a bearer credential. Any local principal able to read it can authenticate without needing the user's password or browser authorization session. ### Attack Path 1. The victim runs `zernio auth:login` or `zernio auth:set`. 2. The CLI calls `writeConfig` and writes the API key to `~/.zernio/config.json`. 3. The operating system creates the directory and file using permissions determined by the current umask. 4. If those permissions permit access by another local user or process, that principal reads the configuration file. 5. The attacker extracts the plaintext `apiKey` value. 6. The attacker submits authenticated requests to the configured Zernio API using the stolen bearer credential. Exploitation requires local filesystem access and permissions suffici ...[truncated 622 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
src/commands/auth.ts:141
Finding

API Credentials Can Be Transmitted to Arbitrary or Plaintext Custom Endpoints

Content
View full analysis
y .option('key', { type: 'string', describe: 'API key', demandOption: true, }) .option('url', { type: 'string', describe: 'Custom API base URL', }), async (argv) => { const updates: Record = { apiKey: argv.key }; if (argv.url) updates.baseUrl = argv.url; writeConfig(updates); output({ success: true, message: 'API key saved to ~/.zernio/config.json' }, argv.pretty as boolean); }, ``` The configured URL is then passed to an authenticated SDK client without scheme or destination validation: ```ts export function createClient(): Late { const apiKey = requireApiKey(); const config = getConfig(); return new Late({ apiKey, baseURL: config.baseUrl || undefined, }); } ``` Environment variables can also supply the unrestricted destination: ```ts export function getConfig(): ZernioConfig { const file = readConfigFile(); return { apiKey: process.env.ZERNIO_API_KEY || process.env.LATE_API_KEY || file.apiKey, // SDK default is https://zernio.com/api (it adds /v1/ prefix to paths internally) baseUrl: process.env.ZERNIO_API_URL || process.env.LATE_API_URL || file.baseUrl, }; } ``` ### Technical Analysis The custom base URL is not parsed or validated before it is stored and passed to the SDK. In particular, the implementation does not: - Require the `https:` scheme. - Reject plaintext `http:` endpoints. - Restrict destinations to trusted Zernio domains. - Reject URLs containing embedded credentials. - Require explicit confirmation before sending a bearer creden ...[truncated 2439 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Rogue AgentSelf-Modification, Session Persistence
Findings (30)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The provided code does not implement scheduling or management of social media posts, nor does it interact with any social media platforms. Its actual function is to load configuration and credentials, then instantiate a Zernio SDK client. That is a materially different primary purpose from the declared description, so this is a mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description says the skill schedules and manages social media posts across 14 platforms from the CLI. However, this code chunk only defines analytics-related CLI commands that query analytics endpoints for post performance, daily metrics, and best posting times. There is no scheduling, publishing, editing, deleting, or management of posts shown here. This is a material purpose mismatch: the implemented behavior is analytics/reporting, not post scheduling/management.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description says the skill schedules and manages social media posts across many platforms, but the supplied code chunk does not implement posting, scheduling, platform integrations, or social media management. Instead, it implements auth-related CLI commands (auth:login, auth:set, auth:check) for obtaining, storing, and validating an API key for the Zernio service. This is a materially different primary purpose and includes undeclared capabilities related to authentication, browser launching, network polling, and local credential storage.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared description says the skill schedules and manages social media posts across many platforms, but the supplied code only implements media upload. It accesses the local filesystem, obtains a presigned URL from an API, and uploads the file to that URL, then returns the media URL/key. Those are materially different capabilities from post scheduling/management, and the advertised multi-platform posting functionality is not represented in this code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description says the skill schedules and manages social media posts across 14 platforms from the CLI. However, the supplied code only defines profile-related CLI commands: profiles:list, profiles:create, profiles:get, profiles:update, and profiles:delete. These interact with a profiles API and manipulate profile fields like name, description, color, and isDefault. There is no evidence of creating, scheduling, publishing, or managing social media posts, nor any platform-specific integrations. This is a material purpose mismatch, not just an implementation detail.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The supplied code does not implement social media post scheduling or multi-platform post management. Instead, it handles CLI configuration and authentication setup by reading and writing config files in the user's home directory, checking environment variables, and requiring an API key. While config handling could be a supporting detail in a larger CLI, this chunk's actual behavior is specifically auth/config management for a Zernio/Late service, not the declared social media scheduling purpose. That is a materially different primary function for this code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description describes a feature-rich CLI for scheduling and managing social media posts across many platforms. The supplied code chunk does not implement any posting, scheduling, platform integrations, or management logic. It only contains helper functions for JSON output and structured error reporting. While output formatting could be a supporting detail within a larger CLI, this chunk by itself does not match the declared purpose and instead serves a different, much narrower utility role.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: picomatch==4.0.3 — 2 advisory(ies): CVE-2026-33672 (Picomatch: Method Injection in POSIX Character Classes causes incorrect Glob Mat); CVE-2026-33671 (Picomatch has a ReDoS vulnerability via extglob quantifiers)

High
Category
Supply Chain
Confidence
80% confidence
Finding

Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Content

No source excerpt is available for this finding.

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · src/commands/auth.ts (reported line 66)May include surrounding context.

ts
const { deviceCode, userCode, browserUrl, expiresAt, interval } =
          await initiateRes!.json();

        // Step 2: Print instructions to stderr (so stdout stays clean for JSON)
        process.stderr.write('\n');
        process.stderr.write(`  Confirmation code: ${userCode}\n\n`);
        process.stderr.write(`  Opening browser to: ${browserUrl}\n`);

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

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

zernio accounts:list --pretty

3. Schedule a post

zernio posts:create --text "Hello from the CLI!" --accounts --scheduledAt "2025-06-01T10:00:00Z"

text

## Authentication

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The README explicitly states that an API key is saved to ~/.zernio/config.json without warning that this file contains sensitive credentials. In an AI-agent and CLI context, local plaintext credential storage can increase the chance of accidental disclosure through backups, logs, shared home directories, or permissive file permissions.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

This markdown file lists profiles:delete and posts:delete commands, but provides no warning that these actions may permanently remove user data or scheduled content. For markdown files, the skill description should disclose behaviors that can affect user data or system integrity, especially destructive operations.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill declares use of an API key and clearly performs networked operations, but it does not declare an explicit tool scope such as allowed tools or permissions. In an agent setting, this weakens containment and can let the skill invoke sensitive capabilities without clear operator review, especially around credential use and outbound requests.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The documentation includes destructive operations such as deleting profiles and posts without any warning, confirmation guidance, or recovery caveats. In an autonomous or semi-autonomous agent workflow, this increases the chance of irreversible data loss or accidental deletion of scheduled content.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

Immediate publish and multi-platform posting commands can trigger real-world external side effects, yet the skill provides no caution about accidental posting, reputational damage, or misuse by an agent. In this context, the absence of warnings is risky because the tool is designed to act on behalf of user-owned public accounts.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The media upload examples instruct users to send local files to an external service without warning that sensitive local content may be transmitted off-host. For agent use, this can lead to unintended exfiltration of private images, videos, or embedded metadata if file selection is automated or inferred incorrectly.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · src/client.ts (reported line 5)May include surrounding context.

ts
import { getConfig, requireApiKey } from './utils/config.js';

/**
 * Create a Zernio SDK client instance using config from ~/.zernio/config.json or env vars.
 * Call this at the start of every command handler.
 */
export function createClient(): Late {

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

This code performs a network upload of the selected file by issuing a PUT request to a presigned URL, which transmits user-supplied file data off the local system. Although the command name suggests upload behavior, there is no explicit confirmation prompt, warning message, or user-facing disclosure near the operation itself describing that the file contents will be sent to a remote service.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The CLI exposes a destructive posts:delete operation that immediately deletes a post based only on the supplied ID, with no interactive confirmation, --force gating, dry-run mode, or other visible safeguard. In a social-media scheduling tool, accidental invocation, shell history reuse, scripting mistakes, or targeting the wrong post ID can cause irreversible loss of scheduled or draft content and operational disruption.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The command performs an irreversible delete operation directly from the CLI without any confirmation prompt, dry-run mode, or force flag gating. In a tool used to manage social media profiles across many platforms, accidental invocation, shell history reuse, scripting mistakes, or typoed profile IDs can cause unintended deletion of configuration or account mappings, leading to operational disruption.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: esbuild==0.27.4 — 1 advisory(ies): GHSA-g7r4-m6w7-qqqr (esbuild allows arbitrary file read when running the development server on Window)

Low
Category
Supply Chain
Confidence
60% confidence
Finding

Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 44)May include surrounding context.

json
"url": "https://github.com/zernio-dev/zernio-cli"
  },
  "dependencies": {
    "@zernio/node": "^0.1.58",
    "open": "^10.1.0",
    "yargs": "^17.7.2"
  },

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 45)May include surrounding context.

json
},
  "dependencies": {
    "@zernio/node": "^0.1.58",
    "open": "^10.1.0",
    "yargs": "^17.7.2"
  },
  "devDependencies": {

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 46)May include surrounding context.

json
"dependencies": {
    "@zernio/node": "^0.1.58",
    "open": "^10.1.0",
    "yargs": "^17.7.2"
  },
  "devDependencies": {
    "@types/node": "^20.11.0",

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 49)May include surrounding context.

json
"yargs": "^17.7.2"
  },
  "devDependencies": {
    "@types/node": "^20.11.0",
    "@types/yargs": "^17.0.32",
    "tsup": "^8.0.1",
    "typescript": "^5.3.3"

Static analysis

No suspicious patterns detected.