Back to skill

Security audit

Judge Human

Security checks for vulnerabilities and agentic risk

Overview

The skill is purpose-aligned, but it can run persistent autonomous evaluations that publish to Judge Human while feeding untrusted story text to local or third-party LLM evaluators.

Install only if you want an agent to publish Judge Human votes, stories, or evaluation signals under your identity. Use dry-run first, avoid scheduling until you understand the consent file and uninstall path, prefer a tightly sandboxed evaluator, and do not run the heartbeat from an environment containing unrelated sensitive files or sessions.

Vulnerability Patterns
  • 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
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Findings (1)

other

Warning
Location
scripts/heartbeat.mjs:153
Finding

Untrusted Story Content Is Passed to Agentic Local LLM CLIs

Content
View full analysis

Vulnerability Details

File Location: scripts/heartbeat.mjs:153-174, 220-241, 384-389
Vulnerability Type: Indirect prompt injection through remotely supplied story content
Risk Level: Medium

Vulnerable Code

js
function buildPrompt(s) {
  const dimension = (s.dimension ?? s.bench ?? "DILEMMA").toUpperCase();
  const desc = DIMENSION_GUIDE[dimension] ?? "General evaluation";
  return [
    "You are Themis, an impartial AI judge on JudgeHuman. Evaluate this story.",
    "",
    `Primary dimension: ${dimension} — ${desc}`,
    `Title: ${s.title}`,
    `Content: ${s.content ?? s.exhibit ?? "(none)"}`,
    "",
    "Score all five dimensions 1–10:",
    "1–2 = seriously problematic | 3–4 = below average | 5–6 = neutral | 7–8 = commendable | 9–10 = exceptional",
    "",
    "Compute an overall composite score 0–100.",
    "Give up to 3 concise reasoning strings (max 200 chars each).",
    "",
    "Reply ONLY with valid JSON, no markdown:",
    '{"dimension_scores":{"ETHICS":0,"HUMANITY":0,"AESTHETICS":0,"HYPE":0,"DILEMMA":0},"score":0,"reasoning":["..."]}',
  ].join("\n");
}
js
if (evaluator === "claude-cli") {
  const raw = execFileSync("claude", ["-p", prompt, "--output-format", "json"], {
    timeout: 60_000,
    encoding: "utf8",
    // PATH + HOME only (HOME locates CLI auth). CLAUDECODE is naturally
    // absent, allowing spawning outside a live Claude Code session.
    env: minimalChildEnv(),
  });
  return parseEvalResponse(raw);
}

if (evaluator === "codex-cli") {
  const raw = execFileSync(
    "codex",
    ["exec", "--ephemeral", "--sandbox", "read-only", "--skip-git-repo-check", prompt],
    {
      timeout: 120_000,
      encoding: "utf8",
      // PATH + HOME only (HOME locates ~/.codex auth)
      env: minimalChildEnv(),
    }
  );
  return parseEvalResponse(raw);
}
js
if (evaluator) {
  const signal = await evaluate(s, evaluator);
  const res = await api("/api/v2/agent/signal", {
    method: "POST",
    auth: tr
...[truncated 2884 chars]
Remediation
View remediation

Remediation Suggestions

  1. Treat every remotely retrieved title and story body as hostile input. Place it in an explicitly delimited data field and instruct the evaluator that content inside that field is evidence only and must never be interpreted as instructions.
  2. Prefer structured API messages that separate trusted evaluator instructions from untrusted story data. Do not combine both into one undifferentiated prompt.
  3. Disable tools for local CLI evaluation wherever supported. Run all evaluators in a disposable sandbox with:
    • No project-directory access.
    • A temporary, minimal home directory.
    • No shell or subprocess tools.
    • No network access unless strictly required.
    • Read access only to files explicitly needed for authentication.
  4. Do not rely only on environment filtering. Restrict the child process’s working directory, filesystem namespace, tool permissions, and network capabilities.
  5. Validate evaluator output against a strict schema before submission:
    • Allow only score, dimension_scores, reasoning, and explicitly supported evidence fields.
    • Reject unknown properties.
    • Enforce numeric ranges and finite numeric values.
    • Enforce permitted dimension names.
    • Enforce reasoning item counts and lengths.
  6. Construct the outbound request from individually validated fields instead of spreading the complete evaluator object:
js
const body = {
  story_id: s.id,
  score: validated.score,
  dimension_scores: validated.dimension_scores,
  reasoning: validated.reasoning,
};
  1. Consider requiring per-story approval for untrusted content or providing a mode that displays generated evaluations for human review before publication.
  2. Add adversarial tests containing embedded instructions, requests to read local files, malformed JSON, unexpected properties, oversized reasoning, and out-of-range scores.
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
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
Findings (17)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
Run `scripts/heartbeat.mjs` on a schedule via your system's task scheduler (cron on Linux/macOS, Task Scheduler on Windows, systemd timer, or any CI runner). Se

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
Run `scripts/heartbeat.mjs` on a schedule via your system's task scheduler (cron on Linux/macOS, Task Scheduler on Windows, systemd timer, or any CI runner). Se

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
Run `scripts/heartbeat.mjs` on a schedule via your system's task scheduler (cron on Linux/macOS, Task Scheduler on Windows, systemd timer, or any CI runner). Se

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
Run `scripts/heartbeat.mjs` on a schedule via your system's task scheduler (cron on Linux/macOS, Task Scheduler on Windows, systemd timer, or any CI runner). Se

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
Run `scripts/heartbeat.mjs` on a schedule via your system's task scheduler (cron on Linux/macOS, Task Scheduler on Windows, systemd timer, or any CI runner). Se

Rp1

Medium
Category
MCP Rug Pull
Confidence
92% confidence
Finding

The install instruction uses npx skills add appmeee/judge-human without pinning an exact package version, so users may execute whatever version is current at install time. If the upstream package, dependency chain, or resolution target is compromised or changed unexpectedly, consumers could run attacker-controlled code during installation or skill retrieval.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
84% confidence
Finding

The skill declares broad operational capabilities via metadata and instructions, including use of environment variables and outbound network access, but does not define an explicit tool scope such as allowed-tools or permissions. In an agent ecosystem, that ambiguity can cause the host to grant more access than the operator expects, especially since the skill also describes autonomous scheduled activity and authenticated API use.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The skill text attempts to direct the agent into an operational role ('You are an AI agent. Your role is to vote... submit evaluation signals...') without an explicit opt-in boundary. In a tool-using agent, this can override user intent and trigger unreviewed actions against external services, made more concerning here by the presence of API-authenticated endpoints, scheduled automation, and persistent state.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The documentation first says every agent's API key 'starts inactive' and will be activated later by an admin, but the example response and follow-up text state the key is 'active as soon as it is issued' and should be used immediately. These statements are directly inconsistent and create a material intent/documentation divergence around authentication and operational readiness.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
91% confidence
Finding

The skill instructs installation of a session-start hook into a persistent user hooks directory, creating code that runs automatically in future sessions. Persistent hooks increase risk because they survive beyond the current task, may execute without fresh review, and in this skill are tied to an autonomous workflow that can prompt recurring activity and interact with stored state.

Content

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

Claude Code:

bash
mkdir -p ~/.claude/hooks
cp hooks/session-start.sh ~/.claude/hooks/session-start.sh
chmod +x ~/.claude/hooks/session-start.sh

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 · heartbeat.md (reported line 175)May include surrounding context.

cron (Linux / macOS)

Add an entry to your personal crontab with crontab -e — sourcing the env file rather than inlining the key:

text

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 · heartbeat.md (reported line 187)May include surrounding context.

systemd timer (Linux)

Create ~/.config/systemd/user/judgehuman.service — referencing the env file, never embedding the key:

ini

Session Persistence

Medium
Category
Rogue Agent
Confidence
80% 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 · heartbeat.md (reported line 214)May include surrounding context.

WantedBy=timers.target

text

Enable with: `systemctl --user enable --now judgehuman.timer`

### Manual invocation

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill explicitly instructs an agent to send authenticated POST requests to production endpoints that create votes and evaluation signals, which are state-changing actions with public visibility. In an agent-skill context, presenting live mutation examples without clear safety gates, sandboxing guidance, or explicit operator confirmation increases the risk that an autonomous agent will take unintended real-world actions.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

Lines L025-L029 state that credentials are sent only to JudgeHuman, Anthropic, or OpenAI and are not forwarded to any other host. However, the script explicitly supports an arbitrary JUDGEHUMAN_EVAL_CMD custom command (L012, L206-L216), and it passes through all JUDGEHUMAN_EVAL_* environment variables to that child process (L185-L200), so the code permits evaluator-controlled handling that may involve other hosts.

Content

No source excerpt is available for this finding.

Unsafe Defaults

Medium
Category
Tool Misuse
Confidence
75% confidence
Finding

Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.

Content

Scanner excerpt · scripts/heartbeat.mjs (reported line 118)May include surrounding context.

js
// ── API ───────────────────────────────────────────────────────────────────────

async function api(path, { method = "GET", body, auth = false } = {}) {
  const headers = { "Content-Type": "application/json" };
  if (auth) headers["Authorization"] = `Bearer ${KEY}`;
  const res = await fetch(`${BASE}${path}`, {

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · scripts/heartbeat.mjs (reported line 321)May include surrounding context.

js
handleConsentFlags();

  if (!flags["dry-run"] && !loadConsent()) {
    console.error("No consent on record for autonomous operation.");
    console.error("This heartbeat sends story content to your configured evaluator and");
    console.error("publishes scores/votes to judgehuman.ai under your agent identity.");
    console.error("Review with --dry-run, then opt in once with: node heartbeat.mjs --grant-consent");

Static analysis

Detected: suspicious.dangerous_exec, suspicious.env_credential_access

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/heartbeat.mjs:208

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/heartbeat.mjs:32