Back to skill

Security audit

Working with Emm AI

Security checks across malware telemetry and agentic risk

Overview

The skill is coherent for remote AI memory and mission control, but it uses broad implicit triggers for sensitive personal data and includes optional plaintext local OAuth token storage.

Install only if you want Emm AI to be used broadly for personalization and recurring agent work. Review MCP permissions, sharing defaults, connected actions, and instruction-write settings, and treat ~/.mcporter/credentials.json as sensitive if you use the manual OAuth fallback.

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 Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (7)

Tp4

High
Category
MCP Tool Poisoning
Confidence
87% confidence
Finding
The skill description emphasizes memory and mission-control features, but the referenced setup behavior includes OAuth registration, local callback handling, token exchange, and writing credentials to a local secrets file. Those are sensitive authentication operations with significant security implications, and omitting them from the primary description can prevent informed consent and lead users to enable the skill without understanding credential-handling risk.

Vague Triggers

High
Confidence
93% confidence
Finding
The activation criteria are extremely broad, covering many ordinary topics like travel, purchases, diet, health, and any request where user history might help. In practice this can cause the skill to trigger and perform remote memory searches, storage, or agent-run actions without a clear, explicit request to use Emm, increasing privacy risk and the chance of unintended persistent side effects.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill does not present an upfront warning that it may store personal data remotely, access shared memory, and execute persistent workflows across sessions. Because the skill targets personal preferences, health, travel, purchases, and connected-device contexts, lack of clear disclosure undermines meaningful user consent and increases the risk of over-collection or unexpected retention.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The skill enables implicit invocation while advertising broad, common-language triggers such as remembering preferences, saving information for later, and improving responses with personal context. Because this skill connects to a remote MCP memory service and can also invoke higher-privilege mission-control functions, ordinary user phrasing may cause unanticipated collection, recall, or action on sensitive personal data without sufficiently explicit consent.

External Transmission

Medium
Category
Data Exfiltration
Content
# --- Exchange code for tokens ---
echo "==> Exchanging code for tokens..."
TOKEN_RESPONSE=$(curl -sf -X POST "$TOKEN_URL" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=authorization_code&code=${OAUTH_CODE}&redirect_uri=${REDIRECT_URI}&client_id=${CLIENT_ID}&client_secret=${CLIENT_SECRET}&code_verifier=${CODE_VERIFIER}")
Confidence
79% confidence
Finding
This request transmits highly sensitive OAuth material, including the authorization code, client secret, and PKCE verifier, to a remote endpoint. While that is expected in an OAuth token exchange, the script fully trusts a hard-coded third-party service and then persists the returned long-lived credentials locally, so compromise or misconfiguration of that endpoint would expose account tokens.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
- `runs` — `{open, open_count, last_completed}`. **`open` is a list** of every run currently open, newest first; it is empty when nothing is running. (It was a single object or `null` before skill 2.2.0 — if you are reading `runs.open.run_id` you have an older skill and will get `undefined`.)

  **Overlapping runs are supported.** A scheduled Autopilot run and an interactive one can be open at the same time, as can two scheduled ones. Starting a run never closes anyone else's. So when `open` is non-empty, the question is not "may I proceed" — it is "what do I need to be careful about":
  - **Proceed.** Do not ask the user for permission to run because another run is open, and do not wait for it.
  - **Expect the shared surfaces to move under you.** The dashboard, the wiki and the task queue may all change mid-cycle. Re-read before you overwrite, and pass the `updated_at` you read as `if_match` on `output_update` / `output_delete` so a clobber is refused (`revision_conflict`) rather than applied silently.
  - **Close only the run you started.** Compare each entry's `started_by_client_id` with your `your_session_id`, and `started_by_transport_session_id` with your `your_transport_session_id` when both are present. A run that is not yours is not yours to close — the other agent is still using it. **A matching `started_by_client_id` is not proof it is yours:** two sessions of the same registered client (a second tab, or a scheduled run on the same credential) share that id and the server cannot tell them apart. Unless you hold the `run_id` from your own `agent_run()` response, treat a same-client run as someone else's and close by explicit `run_id`, not `last_open=true`.
  - Each entry carries `expires_at`. A run past that is swept to `abandoned` by the server; you never need to clean up someone else's stale run yourself.
Confidence
78% confidence
Finding
The skill instructs the agent to proceed with runs without asking the user for permission when another run is already open, and elsewhere states that output writes during a run are pre-authorized by the trigger. While framed as workflow guidance, this encourages autonomous execution over shared remote state and can lead to unintended writes or task processing without a fresh confirmation in ambiguous situations.

Credential Access

High
Category
Privilege Escalation
Content
const path = require('path');
const os = require('os');

const VAULT_PATH = path.join(os.homedir(), '.mcporter', 'credentials.json');

const descriptor = { name: 'emm', url: '${MCP_URL}', command: null };
const hash = crypto.createHash('sha256').update(JSON.stringify(descriptor)).digest('hex').slice(0, 16);
Confidence
91% confidence
Finding
The script writes access tokens, refresh tokens, and the dynamically issued client secret into ~/.mcporter/credentials.json in plaintext. Any local user, malware, backup system, or process with access to that file can reuse the tokens to access the user's Emm account and potentially maintain persistence via the refresh token.

VirusTotal

VirusTotal findings are pending for this skill version.

View on VirusTotal

Static analysis

No suspicious patterns detected.