Back to skill

Security audit

Tokenrip CLI

Security checks for vulnerabilities and agentic risk

Overview

This collaboration skill has legitimate features, but its update, credential, and persistent instruction handling need review before installation.

Install only if you trust the Tokenrip publisher and are comfortable giving the agent broad rip CLI authority. Avoid running rip update/self-update or changing API/frontend URLs unless you initiated it and verified the destination. Treat printed API keys, operator links, invite tokens, and generated share links as secrets, and consider tightening permissions on ~/.config/tokenrip files after setup.

Vulnerability Patterns
  • 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
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (5)

T09 · Insecure Skill Coding Practices

Error
Location
src/config.ts:31
Finding

API keys are stored in a configuration file without restrictive permissions

Content
View full analysis
; } ``` ### Technical Analysis `saveConfig()` writes `~/.config/tokenrip/config.json` without specifying a restrictive file mode. On a typical Unix system with a `022` umask, a newly created file receives mode `0644`, allowing other local users to read it. The file contains the bearer API key set during registration, key recovery, key rotation, or `rip config set-key`. This differs from `saveIdentity()`, which correctly creates the private-key file with mode `0600`. The absence of an explicit mode also means that updating an existing configuration file does not repair previously insecure permissions. ### Attack Path 1. A user runs `rip auth register`, `rip auth create-key`, or `rip config set-key`. 2. The returned API key is placed in the configuration object. 3. `saveConfig()` creates `~/.config/tokenrip/config.json` using permissions derived only from the process umask. 4. On a multi-user system, another local account reads the file. 5. The attacker extracts the bearer API key. 6. The attacker sends authenticated requests to the Tokenrip API as the victim agent. ### Impact Assessment A local attacker may obtain all Tokenrip privileges granted to the API key. Depending on server-side authorization, this can include reading private inbox messages and threads, accessing or ...[truncated 276 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
src/commands/config.ts:12
Finding

Unrestricted API endpoint configuration can disclose bearer credentials

Content
View full analysis
{ const config = loadConfig(); config.apiUrl = url; saveConfig(config); outputSuccess({ message: 'API URL saved', apiUrl: url }, formatConfigSaved); } ``` The configured value is used directly: ```typescript export function getApiUrl(config: TokenripConfig): string { return process.env.TOKENRIP_API_URL || config.apiUrl || 'https://api.tokenrip.com'; } export function getApiKey(config: TokenripConfig): string | undefined { return process.env.TOKENRIP_API_KEY || config.apiKey; } ``` The bearer credential is attached to requests to that endpoint: ```typescript export function createHttpClient(config: ClientConfig = {}): AxiosInstance { const baseUrl = config.baseUrl || 'https://api.tokenrip.com'; const headers: Record = {}; if (config.apiKey) { headers['Authorization'] = `Bearer ${config.apiKey}`; } const client = axios.create({ baseURL: baseUrl, timeout: config.timeout || DEFAULT_TIMEOUT, headers, }); ``` ### Technical Analysis `rip config set-url` accepts any string without enforcing HTTPS, checking the hostname, restricting embedded credentials, or requiring confirmation when changing the credential destination. Authenticated clients then attach the API key as an `Authorization: Bearer` header to requests sent through the configured base URL. Consequently, an attacker-controlled endpoint can collect the credential. An `http://` endpoint additionally exposes the key to network interception. Custom endpoints can be legitimate for self-hosted deployments, but unrestricted endpoint changes do not follow least privilege. ...[truncated 1365 chars]
Remediation
View remediation

T03 · Remote Payload Retrieval and Execution

Error
Location
src/commands/self-update.ts:49
Finding

Unvalidated manifest data can be converted into an npm package installation

Content
View full analysis
{ try { const controller = new AbortController(); const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS); const res = await fetch(manifestUrl(), { signal: controller.signal }); clearTimeout(timer); if (!res.ok) return null; return await res.json() as UpdateManifest; } catch { return null; } } ``` The remote `version` field is interpolated directly into an npm package specification: ```typescript const targetVersion = manifest.version; try { execFileSync('npm', ['install', '-g', `@tokenrip/cli@${targetVersion}`], { stdio: 'inherit' }); } catch { outputSuccess({ status: 'failed', version: currentVersion, targetVersion, message: `Update failed. Try running with sudo:\n sudo npm install -g @tokenrip/cli@${targetVersion}`, }, formatSelfUpdate); return; } ``` ### Technical Analysis The use of `execFileSync()` prevents conventional shell metacharacter injection, but it does not make the npm package specification trustworthy. npm supports package specifications beyond strict semantic versions, including tags and URL/file-style specifications. Because `manifest.version` is not constrained to a strict semantic version, an attacker controlling the manifest can influence what npm resolves and installs. npm installation may execute package lifecycle sc ...[truncated 1810 chars]
Remediation
View remediation

T02 · Agent Memory Poisoning

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

Attacker-controlled remote Skill instructions are persisted without verification

Content
View full analysis
controller.abort(), 3000); const manifestRes = await fetch(`${frontendUrl}/.well-known/skills/tokenrip/manifest.json`, { signal: controller.signal }); if (manifestRes.ok) { const manifest = await manifestRes.json() as { skill_url?: string }; if (manifest.skill_url) { const skillRes = await fetch(manifest.skill_url); if (skillRes.ok) { fs.mkdirSync(CONFIG_DIR, { recursive: true }); fs.writeFileSync(skillPath, await skillRes.text(), 'utf-8'); result.skill_file = skillPath; } } } } catch {} } ``` A similar trust issue exists in `src/commands/self-update.ts:7-22`, where `skillUrl` is fetched and written to the same persistent path: ```typescript async function saveSkillFile(skillUrl: string): Promise<{ path: string; changed: boolean } | null> { try { const res = await fetch(skillUrl); if (!res.ok) return null; const newContent = await res.text(); const skillPath = path.join(CONFIG_DIR, 'SKILL.md'); let existing = ''; try { existing = fs.readFileSync(skillPath, 'utf-8'); } catch {} const changed = newContent !== existing; if (changed) { fs.mkdirSync(CONFIG_DIR, { recursive: true }); fs.writeFileSync(skillPath, newContent, 'utf-8'); } return { path: skillPath, changed }; } catch { return null; } } ``` ### Technical Analysis The manifest's `skill_url` is trusted without checking its protocol, hostname, relationship to the manifest ...[truncated 2132 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

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

Authentication commands emit reusable API keys to standard output

Content
View full analysis
= { agentId, alias: data.data.alias ?? null, apiKey, message: existing && !options.force ? 'Registered existing identity with server' : 'Agent registered', identity_file: '~/.config/tokenrip/identity.json', config_file: '~/.config/tokenrip/config.json', }; ``` JSON is the default output mode, and the full result is serialized: ```typescript export function outputSuccess(data: Record, formatter?: Formatter): void { if (isJsonMode() || !formatter) { console.log(JSON.stringify({ ok: true, data })); } else { console.log(formatter(data)); } } ``` Human-readable mode also prints the complete key: ```typescript export const formatAuthKey: Formatter = (data) => { const lines = [data.message as string || 'API key created.']; if (data.keyName) lines.push(` Name: ${data.keyName}`); if (data.apiKey) lines.push(` Key: ${data.apiKey}`); if (data.note) lines.push(` ${data.note}`); return lines.join('\n'); }; ``` The same output pattern is used for key recovery and key rotation. ### Technical Analysis Reusable bearer credentials are written to standard output even though the CLI also saves them locally. Standard output is commonly captured by: - Agent conversation transcripts - CI/CD logs - Terminal recording systems - Shell redirection - Process wrappers - Automation telemetry - Shared debugging reports Because JSON is the default mode, machine-driven agent workflows are particularly likely to preserve the entire key in logs or model context. ### Attack Path 1. An agent or user runs `rip auth register`, `rip auth create-key`, or a recovery flow. 2. T ...[truncated 722 chars]
Remediation
View remediation
Vulnerability Patterns
  • Memory PoisoningPersistent Context Injection, Context Window Stuffing, Memory Manipulation
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (147)

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

Authentication recovery/regeneration and profile updates are sensitive account-management actions, and the brief skill description does not make that sensitivity obvious. In practice, an agent following this skill could re-register or relink identities and modify public profile data, affecting account integrity and privacy.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

Authentication recovery/regeneration and profile updates are sensitive account-management actions, and the brief skill description does not make that sensitivity obvious. In practice, an agent following this skill could re-register or relink identities and modify public profile data, affecting account integrity and privacy.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

Authentication recovery/regeneration and profile updates are sensitive account-management actions, and the brief skill description does not make that sensitivity obvious. In practice, an agent following this skill could re-register or relink identities and modify public profile data, affecting account integrity and privacy.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

Authentication recovery/regeneration and profile updates are sensitive account-management actions, and the brief skill description does not make that sensitivity obvious. In practice, an agent following this skill could re-register or relink identities and modify public profile data, affecting account integrity and privacy.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

Authentication recovery/regeneration and profile updates are sensitive account-management actions, and the brief skill description does not make that sensitivity obvious. In practice, an agent following this skill could re-register or relink identities and modify public profile data, affecting account integrity and privacy.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

Authentication recovery/regeneration and profile updates are sensitive account-management actions, and the brief skill description does not make that sensitivity obvious. In practice, an agent following this skill could re-register or relink identities and modify public profile data, affecting account integrity and privacy.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

Authentication recovery/regeneration and profile updates are sensitive account-management actions, and the brief skill description does not make that sensitivity obvious. In practice, an agent following this skill could re-register or relink identities and modify public profile data, affecting account integrity and privacy.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

Authentication recovery/regeneration and profile updates are sensitive account-management actions, and the brief skill description does not make that sensitivity obvious. In practice, an agent following this skill could re-register or relink identities and modify public profile data, affecting account integrity and privacy.

Content

No source excerpt is available for this finding.

Memory Manipulation

High
Category
Memory Poisoning
Confidence
80% confidence
Finding

Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.

Content

Scanner excerpt · src/cli.ts (reported line 561)May include surrounding context.

ts
$ rip tour              # start or resume the human tour
  $ rip tour next         # advance to the next step
  $ rip tour next <id>    # advance, passing an ID captured from the previous step
  $ rip tour restart      # wipe state and start over
  $ rip tour --agent      # print a one-shot script an agent can follow
`)
  .action(wrapCommand((options: { agent?: boolean }) => tour(options)));

Memory Manipulation

High
Category
Memory Poisoning
Confidence
80% confidence
Finding

Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.

Content

Scanner excerpt · src/src/cli.ts (reported line 659)May include surrounding context.

ts
$ rip tour              # start or resume the human tour
  $ rip tour next         # advance to the next step
  $ rip tour next <id>    # advance, passing an ID captured from the previous step
  $ rip tour restart      # wipe state and start over
  $ rip tour --agent      # print a one-shot script an agent can follow
`)
  .action(wrapCommand((options: { agent?: boolean }) => tour(options)));

Self-Modification

High
Category
Rogue Agent
Confidence
96% confidence
Finding

A command explicitly named 'self-update' indicates the tool can modify or replace its own installed code. In a skill/agent environment, self-modification is dangerous because it can bypass the reviewed code boundary and introduce new behavior from external packages or registries after deployment.

Content

Scanner excerpt · src/cli.ts (reported line 852)May include surrounding context.

ts
// ── update command ─────────────────────────────────────────────────
program
  .command('self-update')
  .alias('update')
  .description('Check for and install CLI updates')
  .addHelpText('after', `

Self-Modification

High
Category
Rogue Agent
Confidence
95% confidence
Finding

This duplicate finding maps to the same self-update invocation and therefore reflects the same underlying risk: the CLI can change its own software through an external update path. In the context of a collaboration skill, that broadens authority beyond the expected domain and weakens trust in static review.

Content

Scanner excerpt · src/cli.ts (reported line 863)May include surrounding context.

ts
After updating, shows instructions for refreshing the skill file.
`)
  .action(wrapCommand(async () => {
    const { selfUpdate } = await import('./commands/self-update.js');
    await selfUpdate();
  }));

Self-Modification

High
Category
Rogue Agent
Confidence
95% confidence
Finding

This duplicate finding maps to the same self-update invocation and therefore reflects the same underlying risk: the CLI can change its own software through an external update path. In the context of a collaboration skill, that broadens authority beyond the expected domain and weakens trust in static review.

Content

Scanner excerpt · src/cli.ts (reported line 863)May include surrounding context.

ts
After updating, shows instructions for refreshing the skill file.
`)
  .action(wrapCommand(async () => {
    const { selfUpdate } = await import('./commands/self-update.js');
    await selfUpdate();
  }));

Self-Modification

High
Category
Rogue Agent
Confidence
95% confidence
Finding

The awaited call to selfUpdate() is the execution point for self-modification, making the capability operational rather than theoretical. If influenced by an attacker, compromised registry, or unsafe prompt-driven action, it could lead to installation of malicious code or unreviewed behavior changes.

Content

Scanner excerpt · src/cli.ts (reported line 864)May include surrounding context.

ts
`)
  .action(wrapCommand(async () => {
    const { selfUpdate } = await import('./commands/self-update.js');
    await selfUpdate();
  }));

// ── config commands ─────────────────────────────────────────────────

Lp1

High
Category
MCP Least Privilege
Confidence
75% confidence
Finding

The skill uses 'network' capability that is not listed in its permissions. This may indicate deceptive intent or missing permission declarations.

Content

No source excerpt is available for this finding.

Self-Modification

High
Category
Rogue Agent
Confidence
90% confidence
Finding

Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Content

Scanner excerpt · src/commands/self-update.ts (reported line 7)May include surrounding context.

ts
import { loadConfig, saveConfig, CONFIG_DIR } from '../config.js';
import { fetchManifest, getCurrentVersion } from '../update-check.js';
import { outputSuccess } from '../output.js';
import { formatSelfUpdate } from '../formatters.js';

async function saveSkillFile(skillUrl: string): Promise<{ path: string; changed: boolean } | null> {
  try {

Self-Modification

High
Category
Rogue Agent
Confidence
90% confidence
Finding

Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Content

Scanner excerpt · src/commands/self-update.ts (reported line 37)May include surrounding context.

ts
import { loadConfig, saveConfig, CONFIG_DIR } from '../config.js';
import { fetchManifest, getCurrentVersion } from '../update-check.js';
import { outputSuccess } from '../output.js';
import { formatSelfUpdate } from '../formatters.js';

async function saveSkillFile(skillUrl: string): Promise<{ path: string; changed: boolean } | null> {
  try {

Self-Modification

High
Category
Rogue Agent
Confidence
90% confidence
Finding

Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Content

Scanner excerpt · src/commands/self-update.ts (reported line 56)May include surrounding context.

ts
import { loadConfig, saveConfig, CONFIG_DIR } from '../config.js';
import { fetchManifest, getCurrentVersion } from '../update-check.js';
import { outputSuccess } from '../output.js';
import { formatSelfUpdate } from '../formatters.js';

async function saveSkillFile(skillUrl: string): Promise<{ path: string; changed: boolean } | null> {
  try {

Self-Modification

High
Category
Rogue Agent
Confidence
90% confidence
Finding

Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Content

Scanner excerpt · src/commands/self-update.ts (reported line 70)May include surrounding context.

ts
import { loadConfig, saveConfig, CONFIG_DIR } from '../config.js';
import { fetchManifest, getCurrentVersion } from '../update-check.js';
import { outputSuccess } from '../output.js';
import { formatSelfUpdate } from '../formatters.js';

async function saveSkillFile(skillUrl: string): Promise<{ path: string; changed: boolean } | null> {
  try {

Self-Modification

High
Category
Rogue Agent
Confidence
90% confidence
Finding

Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Content

Scanner excerpt · src/commands/self-update.ts (reported line 88)May include surrounding context.

ts
import { loadConfig, saveConfig, CONFIG_DIR } from '../config.js';
import { fetchManifest, getCurrentVersion } from '../update-check.js';
import { outputSuccess } from '../output.js';
import { formatSelfUpdate } from '../formatters.js';

async function saveSkillFile(skillUrl: string): Promise<{ path: string; changed: boolean } | null> {
  try {

Self-Modification

High
Category
Rogue Agent
Confidence
90% confidence
Finding

Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Content

Scanner excerpt · src/formatters.ts (reported line 461)May include surrounding context.

ts
import { loadConfig, saveConfig, CONFIG_DIR } from '../config.js';
import { fetchManifest, getCurrentVersion } from '../update-check.js';
import { outputSuccess } from '../output.js';
import { formatSelfUpdate } from '../formatters.js';

async function saveSkillFile(skillUrl: string): Promise<{ path: string; changed: boolean } | null> {
  try {

Self-Modification

High
Category
Rogue Agent
Confidence
90% confidence
Finding

Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Content

Scanner excerpt · src/src/commands/self-update.ts (reported line 37)May include surrounding context.

ts
import { loadConfig, saveConfig, CONFIG_DIR } from '../config.js';
import { fetchManifest, getCurrentVersion } from '../update-check.js';
import { outputSuccess } from '../output.js';
import { formatSelfUpdate } from '../formatters.js';

async function saveSkillFile(skillUrl: string): Promise<{ path: string; changed: boolean } | null> {
  try {

Self-Modification

High
Category
Rogue Agent
Confidence
90% confidence
Finding

Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Content

Scanner excerpt · src/src/commands/self-update.ts (reported line 56)May include surrounding context.

ts
import { loadConfig, saveConfig, CONFIG_DIR } from '../config.js';
import { fetchManifest, getCurrentVersion } from '../update-check.js';
import { outputSuccess } from '../output.js';
import { formatSelfUpdate } from '../formatters.js';

async function saveSkillFile(skillUrl: string): Promise<{ path: string; changed: boolean } | null> {
  try {

Self-Modification

High
Category
Rogue Agent
Confidence
90% confidence
Finding

Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Content

Scanner excerpt · src/src/commands/self-update.ts (reported line 70)May include surrounding context.

ts
import { loadConfig, saveConfig, CONFIG_DIR } from '../config.js';
import { fetchManifest, getCurrentVersion } from '../update-check.js';
import { outputSuccess } from '../output.js';
import { formatSelfUpdate } from '../formatters.js';

async function saveSkillFile(skillUrl: string): Promise<{ path: string; changed: boolean } | null> {
  try {

Self-Modification

High
Category
Rogue Agent
Confidence
90% confidence
Finding

Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Content

Scanner excerpt · src/src/commands/self-update.ts (reported line 88)May include surrounding context.

ts
import { loadConfig, saveConfig, CONFIG_DIR } from '../config.js';
import { fetchManifest, getCurrentVersion } from '../update-check.js';
import { outputSuccess } from '../output.js';
import { formatSelfUpdate } from '../formatters.js';

async function saveSkillFile(skillUrl: string): Promise<{ path: string; changed: boolean } | null> {
  try {

Static analysis

Detected: suspicious.env_credential_access, suspicious.exposed_secret_literal

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
src/src/auth-client.ts:16

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
src/commands/auth.ts:31

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
src/commands/link.ts:23

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
src/commands/operator-link.ts:124

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
src/src/auth-client.ts:32

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
src/src/commands/agent.ts:29

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
src/src/commands/auth.ts:42

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
src/src/commands/link.ts:24

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
src/src/commands/operator-link.ts:121

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
src/src/migrations.ts:54