Back to skill

Security audit

PCBClaw

Security checks for vulnerabilities and agentic risk

Overview

This PCB workflow uses local files, CAD tools, and optional supplier/account workflows, but those actions are disclosed and bounded by clear authorization requirements.

Before installing, review that this skill can create and modify PCB project files, run KiCad and shell diagnostics, and generate local manufacturing packages. Keep supplier uploads, GitHub publication, orders, payments, and account actions behind explicit approval, as the skill itself requires.

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
Vulnerability Patterns
  • 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
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
Findings (10)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The description overstates the skill substantially. The code is a small offline helper script and even documents that it performs no upload, ordering, CAD editing, or live pricing. Its concrete functions are limited to routing input, checking tool availability, backing up a project, validating quantities/cost JSON, cross-checking BOM and CPL designator consistency, and creating a ZIP archive with some safety checks. While these helpers are related to PCB workflows, they do not implement the declared primary capabilities of designing/modifying KiCad boards, resuming those workflows, conducting supplier review, or repricing from live supplier/manufacturer data. The packaging and verification functions are narrower than the declared purpose, so the description does not accurately represent the code's actual behavior.

YARA rule 'agent_skill_prompt_injection_hidden_instructions': Prompt injection or hidden instructions embedded in AI agent skill text [agent_skills]

High
Category
YARA Match
Content
nspect sudo -n availability rather than assuming. Before consequential changes inspect existing package/repository configuration and active editor state, preserve unsaved work, archive and verify complete project, explain unavoidable compatibility. Ask only for actual missing authority/interactive credential entry. Never collect credentials in chat, expose services publicly, change authentication/model routing without need, disable security, rerun onboarding, or install unverified scripts.

Use a supported KiCad API/native template before custom file generation. Check existing maintained solutions before creating additional custom infrastructure. GUI editing is permitted, not mandatory; programmatic CAD must be verifiable and safely reloaded. No brittle blind textual rewrites.

One owner controls the CAD desktop. On COMPUTER_HOST_BUSY stop repeated retries, identify the active owner with available session/node tools, distinguish active from stale execution, use documented recovery and
Confidence
80% confidence
Finding
YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Credential Access

High
Category
Privilege Escalation
Content
self.assertEqual(h.crosscheck(bom,cpl)["matched_references"],2)
            cpl.write_text("Designator\nR1\nR1\n")
            with self.assertRaises(ValueError):h.crosscheck(bom,cpl)
            (project/".env").write_text("synthetic")
            with self.assertRaises(ValueError):h.package(project,base/"rejected.zip")
    def test_policy_contract(self):
        root=pathlib.Path(__file__).resolve().parents[1]
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
self.assertEqual(h.crosscheck(bom,cpl)["matched_references"],2)
            cpl.write_text("Designator\nR1\nR1\n")
            with self.assertRaises(ValueError):h.crosscheck(bom,cpl)
            (project/".env").write_text("synthetic")
            with self.assertRaises(ValueError):h.package(project,base/"rejected.zip")
    def test_policy_contract(self):
        root=pathlib.Path(__file__).resolve().parents[1]
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Vague Triggers

Medium
Confidence
92% confidence
Finding
The trigger phrase "pcb" is extremely broad and likely to appear in ordinary conversation about electronics, files, project names, or prior workspaces, which increases the chance of accidental activation. In a skill that can modify project files, invoke shell/tooling, and perform packaging/repricing workflows, unintended activation could lead to confusing or unwanted actions against local PCB projects.

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill describes capabilities that involve file reads, file writes, and shell execution, but it does not declare an explicit tool/permission scope. That creates a trust and containment gap: a host may expose broader capabilities than users expect, increasing the chance of unintended filesystem changes or command execution in a workflow that handles local projects and packaging. In this PCB context, the risk is elevated because the instructions explicitly authorize installs, local exports, and project file modification.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
Stages: interview needs workspace/config and research as required, not a running desktop. Reprice needs project BOM/requirements and official catalog/quote information, not CAD GUI. Package/modify/resume/design need appropriate KiCad operations. Check kicad-cli version/help, Python/Git and needed exporters; probe pcbnew with the Python interpreter that owns it (Ubuntu package uses /usr/bin/python3). No particular minor version is required if the installed supported stable version works. Check a GUI/computer node only when needed; do not reinstall or downgrade working software.

Use shell for Linux administration. Verify official KiCad OS-specific stable repository instructions if installation is needed; avoid nightly. Inspect sudo -n availability rather than assuming. Before consequential changes inspect existing package/repository configuration and active editor state, preserve unsaved work, archive and verify complete project, explain unavoidable compatibility. Ask only for actual missing authority/interactive credential entry. Never collect credentials in chat, expose services publicly, change authentication/model routing without need, disable security, rerun onboarding, or install unverified scripts.

Use a supported KiCad API/native template before custom file generation. Check existing maintained solutions before creating additional custom infrastructure. GUI editing is permitted, not mandatory; programmatic CAD must be verifiable and safely reloaded. No brittle blind textual rewrites.
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
2. Stage the exact validated source and upload files with manifest/hashes, reports, firmware status, cost timestamp and limitations. Keep previous releases intact. Use a versioned source commit/tag and release assets; make explicit which source snapshot is authoritative if older root files remain.
3. Validate archive contents and download the published assets where accessible to compare their hashes. Provide real release/download links, stating sign-in requirements. Server filesystem Markdown links are not remote downloads; never claim an attachment merely because a path was printed. If no delivery mechanism exists, explain the supported retrieval route.
4. On an explicit request to mark a version first ordered, identify the exact order-designated revision and quantities. Preserve source/manufacturing archives unchanged; add a tagged release/snapshot and provenance notes with date and checksums. Distinguish user-designated ordering from independently verified payment/order acceptance. Do not relabel an older release or imply that ordering proves operation or resolves outstanding supplier review.
5. Verify the published commit/tag, release assets and links. Future changes get a new revision; never silently overwrite the ordered baseline. Project changes and release publication do not automatically modify this reusable skill.
Confidence
80% 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.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
executable = shutil.which(name)
        item = {"available":bool(executable),"path":executable}
        if executable:
            proc = subprocess.run([executable,"version" if name == "kicad-cli" else "--version"],capture_output=True,text=True,timeout=20)
            item.update(returncode=proc.returncode,version=proc.stdout.strip())
        result["tools"][name] = item
    root = pathlib.Path.home()/"pcb-projects"
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Content
item=data.get("rows",{}).get(str(qty),{}) if qty is not None else {}
        values=[item.get(k) for k in ("pcb_fab","components","assembly_setup_other")]
        for value in values:
            if value is not None and (type(value) not in (int,float) or value < 0 or not __import__("math").isfinite(value)):
                raise ValueError("Costs must be nonnegative finite values or null")
        known=sum(v for v in values if v is not None)
        total=sum(values) if qty and all(v is not None for v in values) else None
Confidence
75% confidence
Finding
Dynamic __import__() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Static analysis

No suspicious patterns detected.