skill-creator: eval-viewer sends SIGTERM to any process on the target port
generate_review.py terminates every process listening on its target port before starting the viewer, with no check that the process is a previous eval-viewer instance, no prompt, and no output.
File: plugins/skill-creator/skills/skill-creator/eval-viewer/generate_review.py, L288–L305, called at L440. Confirmed against main at da64a66.
def _kill_port(port: int) -> None:
"""Kill any process listening on the given port."""
try:
result = subprocess.run(
["lsof", "-ti", f":{port}"],
capture_output=True, text=True, timeout=5,
)
for pid_str in result.stdout.strip().split("\n"):
if pid_str.strip():
try:
os.kill(int(pid_str.strip()), signal.SIGTERM)
except (ProcessLookupError, ValueError):
passThe only print in this function fires when lsof itself is missing, so the user is never told that a process was killed.
The default port is 3117 (L390), which makes an accidental hit unlikely. But --port is user-settable and gets passed by whoever is driving the script, so --port 3000, --port 8080 or --port 5432 silently kills a dev server, an app, or a local Postgres. Since the script is typically invoked by an agent on the user's behalf, the port isn't always a value the user chose themselves.
The kill is also redundant
L444 already handles a busy port:
except OSError:
# Port still in use after kill attempt — find a free one
server = HTTPServer(("127.0.0.1", 0), handler)
port = server.server_address[1]Binding fails, the fallback picks a free port, and the viewer starts anyway. So the SIGTERM buys nothing that the existing error path doesn't already cover.
Suggested fix
Delete _kill_port and its call at L440, and let the OSError fallback do the work. If reclaiming a stale viewer's port is genuinely wanted, gate it on the process actually being an earlier eval-viewer (match the cmdline) and print what is being terminated.
How this was found
Scanning my locally installed skills with NVIDIA SkillSpector v2.11.2:
uv tool install git+https://github.com/NVIDIA/skillspector.git
skillspector scan <path>/plugins/skill-creator/skills/skill-creatorFor calibration: this was one of only two substantive findings across 31 scanned skills — the scanner's static stage is very noisy on documentation skills, and its LLM stage suppressed none of that noise. I verified every finding by hand; the rest were false positives.
Source: anthropics/claude-plugins-official