Back to skill

Security audit

claude-session-warmer

Security checks for vulnerabilities and agentic risk

Overview

The skill is transparent about its goal, but it creates recurring authenticated Claude CLI jobs and generates cron entries from weakly validated configuration, so it belongs in Review.

Install only if you are comfortable with a recurring job on your VPS using your logged-in Claude CLI. Review the exact crontab lines before adding them, avoid piping directly into crontab, keep config.json trusted and simple, and know how you will remove the cron entries later.

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

T09 · Insecure Skill Coding Practices

Warning
Location
bin/session-warmer.mjs:124
Finding

Unvalidated configuration permits persistent cron command injection and denial of service

Content
View full analysis

Vulnerability Details

File Location: bin/session-warmer.mjs:50-61, 89-94, 124-142
Vulnerability Type: Cron injection through unvalidated configuration and paths
Risk Level: Medium

The application merges arbitrary values from config.json into its configuration without validating their types, ranges, or characters:

js
function loadConfig() {
  const path = join(ROOT, "config.json");
  if (!existsSync(path)) return { ...DEFAULTS, _usingDefaults: true };
  try {
    const user = JSON.parse(readFileSync(path, "utf8"));
    return { ...DEFAULTS, ...user };
  } catch (e) {
    console.error(`! Could not parse config.json: ${e.message}\n  Falling back to defaults.`);
    return { ...DEFAULTS, _usingDefaults: true };
  }
}

Schedule arithmetic also uses these values without checking that they are finite, positive, or within reasonable bounds:

js
function computeSchedule(cfg) {
  const start = hhmmToMinutes(cfg.anchor);
  const end = hhmmToMinutes(cfg.day_end);
  const step = cfg.window_minutes + cfg.buffer_minutes;
  const times = [];
  for (let t = start; t <= end; t += step) times.push(t);
  return times; // minutes-of-day, in cfg.timezone
}

The installation command then places the unvalidated timezone and unquoted project paths directly into shell-interpreted crontab output:

js
function cmdInstall(cfg, cronOnly) {
  const times = computeSchedule(cfg);
  const self = join(ROOT, "bin", "session-warmer.mjs");
  const cronLines = times.map((t) => {
    const hh = Math.floor(t / 60), mm = t % 60;
    return `${mm} ${hh} * * *  node ${self} warm >> ${join(ROOT, "warmer.log")} 2>&1`;
  });
  if (cronOnly) {
    // pipeable: just the crontab lines (plus CRON_TZ), nothing else
    console.log(`CRON_TZ=${cfg.timezone}`);
    cronLines.forEach((l) => console.log(l));
    return;
  }
  console.log("# --- Option A: cron on this VPS (recommended) ---")
...[truncated 3584 chars]
Remediation
View remediation

Remediation Suggestions

  1. Introduce a strict configuration schema before any command is executed:

    • Require enabled and dry_run to be booleans.
    • Require anchor and day_end to match a strict HH:MM format and verify hour/minute ranges.
    • Require window_minutes and buffer_minutes to be finite integers within conservative positive bounds.
    • Explicitly require window_minutes + buffer_minutes > 0.
    • Require claude_args to be an array containing only strings.
  2. Validate timezone using Intl.DateTimeFormat and reject all control characters, especially carriage returns and newlines. Only emit the value after confirming that it is a recognized IANA timezone.

  3. Do not concatenate filesystem paths directly into cron shell commands. Use a robust POSIX shell-quoting function for the Node executable, script path, and log path, or generate a fixed wrapper script whose location is itself safely quoted.

  4. Resolve and emit an explicit trusted Node binary path instead of relying on cron’s restricted or attacker-influenced PATH.

  5. Add a hard upper bound to the number of generated schedule entries so malformed arithmetic cannot consume unbounded memory:

    js
    if (!Number.isInteger(step) || step <= 0 || step > 1440) {
      throw new Error("Invalid scheduling interval");
    }
    
  6. Avoid recommending direct piping into crontab until all output fields are validated and escaped. Prefer writing the proposed crontab to a temporary preview file and requiring explicit review before installation.

  7. Add regression tests covering newline-bearing timezone values, shell metacharacters in installation paths, malformed times, non-numeric values, zero/negative intervals, and excessively large schedule configurations.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (11)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node bin/session-warmer.mjs check # confirms claude is installed + logged in here

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node bin/session-warmer.mjs check # confirms claude is installed + logged in here

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node bin/session-warmer.mjs check # confirms claude is installed + logged in here

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node bin/session-warmer.mjs check # confirms claude is installed + logged in here

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node bin/session-warmer.mjs check # confirms claude is installed + logged in here

Session Persistence

Medium
Category
Rogue Agent
Confidence
85% 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 63)May include surrounding context.

3. Schedule it

node bin/session-warmer.mjs install # prints a ready-to-paste cron block crontab -e # paste it, save — done

text

## Commands

Session Persistence

Medium
Category
Rogue Agent
Confidence
85% 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 · bin/session-warmer.mjs (reported line 136)May include surrounding context.

js
# 3. Schedule it
node bin/session-warmer.mjs install     # prints a ready-to-paste cron block
crontab -e                              # paste it, save — done
```

## Commands

Session Persistence

Medium
Category
Rogue Agent
Confidence
85% 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 · docs/index.html (reported line 170)May include surrounding context.

html
# 3. Schedule it
node bin/session-warmer.mjs install     # prints a ready-to-paste cron block
crontab -e                              # paste it, save — done
```

## Commands

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill advertises activation on broad phrases like usage windows, resets, warming up, and maximizing plan use, which can cause it to trigger during ordinary discussion rather than an explicit request to configure this automation. Because the skill sets up scheduled background behavior tied to an authenticated CLI on a VPS, over-broad activation increases the chance of unsolicited guidance for persistent actions and quota-consuming automation.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
85% confidence
Finding

The skill instructs the user to install a cron entry, creating persistent scheduled execution on an always-on VPS using an authenticated Claude CLI session. Persistence itself is not inherently malicious here, but it is security-relevant because it establishes unattended recurring actions that may consume account resources, outlive user awareness, and be difficult to notice or revoke if misconfigured.

Content

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

3. Schedule it.

bash
node bin/session-warmer.mjs install    # prints a ready-to-paste cron block
crontab -e                             # paste the block; save

Done — the VPS now warms your Claude window every day so your windows align to your hours. (Prefer OpenClaw/Cowork scheduled tasks? install also prints that recipe — one task per

Session Persistence

Medium
Category
Rogue Agent
Confidence
85% 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 · bin/session-warmer.mjs (reported line 142)May include surrounding context.

js
cronLines.forEach((l) => console.log(l));
  console.log("");
  console.log("# One-liner to append it automatically (review first!):");
  console.log(`#   ( crontab -l 2>/dev/null; node ${self} install --cron-only ) | crontab -`);
  console.log("");
  console.log("# --- Option B: OpenClaw / Cowork scheduled task ---");
  console.log("# Create one scheduled task per primer time above, each running:");

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
bin/session-warmer.mjs:154