Back to skill

Security audit

lgd-certify

Security checks for vulnerabilities and agentic risk

Overview

This skill is a local certification/badge generator, but its certification gate can produce trusted-looking PASS results without validating real evidence or protecting state from tampering.

Review before installing. Treat generated PASS results, certification.json, and badges as self-attestation only unless an independent reviewer validates the evidence and state. Avoid the unpinned global npx install path in higher-assurance environments; prefer a reviewed immutable commit or pinned installer.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (3)

T08 · Insecure Dependencies

Warning
Location
SKILL.md:82
Finding
Unpinned Third-Party Package Execution During Installation<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:82-84` **Vulnerability Type**: Unpinned dependency and global package execution **Risk Level**: Medium ### Vulnerable Code ```bash # One-click installation using the skills CLI npx skills add zhaoxinghua09-cell/agent-skills -g ``` ### Technical Analysis The documented installation procedure invokes `npx skills` without specifying an exact package version or verifying package integrity. Consequently, the package and executable resolved by the package manager at installation time may differ from those reviewed during this audit. The `-g` option also requests a global skill installation. Although it does not inherently elevate operating-system privileges, it expands the scope of modifications beyond an isolated project and may affect other agent sessions that use the same global skill directory. This is a supply-chain risk rather than evidence that the currently reviewed local Python script is malicious. Exploitation depends on compromise, replacement, or unexpected resolution of the externally sourced package. ### Attack Path 1. An attacker compromises the package, publisher account, distribution registry, or another component involved in resolving the unpinned `skills` executable. 2. The victim follows the documented `npx skills add ... -g` command. 3. `npx` retrieves and runs the package version available at that time rather than a version tied to this audit. 4. Malicious package or lifecycle code executes with the invoking user's privileges. 5. The package may modify user-accessible files, steal credentials readable by that user, or install altered skills globally. ### Impact Assessment Successful exploitation could provide arbitrary code execution with the privileges of the user running `npx`. The accessible scope may include that user's files, environment variables, development credentials, agent configuration, and global user-level skill installation directories. This command does n ...[truncated 71 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Pin the installer package to an exact reviewed version, such as `npx skills@<exact-version>`. - Verify package provenance and publisher identity before documenting it as the recommended installer. - Use package-locking and registry-supported integrity hashes where available. - Prefer a project-local installation over `-g` unless global installation is strictly required. - Provide the expected artifact digest or signed release metadata so users can verify downloaded content. - For higher-assurance environments, install directly from a reviewed, immutable Git commit and verify its checksum before execution. - Document that the installer executes third-party code and should be run with least privilege. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/lgd_certify.py:97
Finding
Certification Gate Accepts Empty or Meaningless Evidence Files<![CDATA[ ## Vulnerability Details **File Location**: `scripts/lgd_certify.py:97-103, 119-145` **Vulnerability Type**: Insufficient evidence validation and authorization logic **Risk Level**: High ### Vulnerable Code ```python files = [] for k in sorted(SIX): sub = os.path.join(ev_dir, k) if os.path.isdir(sub): for fn in sorted(os.listdir(sub)): fp = os.path.join(sub, fn) if os.path.isfile(fp): files.append((k, fn, fp)) for k, fn, fp in files: block = {"evidence_class": k, "file": fn, "hash": sha256_file(fp), "recorded_at": NOW(), "prev": prev} block["block_hash"] = sha256_obj(block) chain.append(block); prev = block["block_hash"] st["evidence_chain"] = {"head": prev, "blocks": chain, "classes_covered": sorted({b["evidence_class"] for b in chain}), "updated_at": NOW()} def cmd_gate(d): st = load_state(d) classes = set(st.get("evidence_chain", {}).get("classes_covered", [])) checks = { "L1-有籍 REGISTERED": bool(st.get("passport")), "L2-有证 EVIDENCED": bool(st.get("evidence_chain")) and classes >= set(SIX), "L3-有门禁 GATED": "06-issuance" in classes, } verdict = "PASS" if all(checks.values()) else "FAIL" ``` ### Technical Analysis Evidence acceptance is based solely on whether a directory entry is a regular file. The implementation does not enforce: - A nonzero file size. - An expected file format or schema. - Required fields for a given evidence class. - Digital signatures or trusted issuer identities. - Evidence relevance, authenticity, or semantic validity. - Minimum evidence quality or independent review. The `classes_covered` value is derived from the directories containing files, not from validated evidence content. The gate then treats coverage of all six directory names as sufficient for a `PASS`. As a result, six empty files—one in each evidence directory—meet the technical con ...[truncated 1414 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Reject empty files and enforce appropriate minimum sizes and MIME types. - Define a strict schema for each evidence class and validate all required fields. - Validate evidence semantics rather than deriving coverage from directory placement. - Require cryptographic signatures from explicitly trusted and authorized issuers. - Separate preparation of issuance materials from successful completion of the gate; do not let an arbitrary file in `06-issuance` prove that the gate passed. - Require an independent reviewer identity and a signed review decision. - Label outputs as self-attestations unless an independent trusted authority signs them. - Add negative tests proving that empty, malformed, duplicate, and irrelevant files cannot produce `PASS`. - Consider requiring policy-specific thresholds and explicit reviewer approval for each evidence class. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/lgd_certify.py:46
Finding
Editable State Is Trusted Without Evidence-Chain Integrity Verification<![CDATA[ ## Vulnerability Details **File Location**: `scripts/lgd_certify.py:46-48, 132-145` **Vulnerability Type**: Client-controlled state tampering and missing integrity verification **Risk Level**: High ### Vulnerable Code ```python def load_state(d): st = os.path.join(d, "lgd_state.json") return json.load(open(st, encoding="utf-8")) if os.path.exists(st) else {} def cmd_gate(d): st = load_state(d) classes = set(st.get("evidence_chain", {}).get("classes_covered", [])) checks = { "L1-有籍 REGISTERED": bool(st.get("passport")), "L2-有证 EVIDENCED": bool(st.get("evidence_chain")) and classes >= set(SIX), "L3-有门禁 GATED": "06-issuance" in classes, } verdict = "PASS" if all(checks.values()) else "FAIL" ``` The successful path subsequently trusts values from the same state: ```python st["gate_verdict"] = {"verdict": "PASS", "reviewed_at": NOW(), "evidence_head": st["evidence_chain"]["head"], "passport_hash": st["passport"]["verification_ticket"]["passport_hash"]} cert = {"schema_version": "1.0", "type": "LGDCertification", "verdict": "PASS", "algorithm_id": st["passport"]["algorithm_id"], "passport_hash": st["passport"]["verification_ticket"]["passport_hash"], "evidence_head": st["evidence_chain"]["head"], "issued_at": NOW(), "issuer": st["passport"]["verification_ticket"]["issuer"]} ``` ### Technical Analysis `lgd_state.json` is an unsigned, user-editable local file. The gate treats its contents as authoritative without validating them against the evidence files or recomputing any cryptographic values. In particular, the gate does not: - Recompute evidence file hashes. - Recompute each evidence block's `block_hash`. - Verify that every block's `prev` value matches the preceding block. - Verify that the stored chain head matches the final block. - Derive `classes_covered` from verified blocks. - Recompute or validate the passport ...[truncated 1545 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - At gate time, enumerate the evidence files again and recompute every file hash. - Validate every evidence block using a strict schema. - Recompute each `block_hash` and verify the complete `prev` linkage from genesis to the final head. - Derive `classes_covered` from verified blocks instead of trusting the stored field. - Recompute the passport hash and compare it with the stored value. - Reject missing, unexpected, duplicate, malformed, or stale evidence entries. - Sign passports, evidence-chain roots, gate decisions, and certificates with a protected issuer key. - Verify signatures against an explicit trust store and validate issuer authorization. - Use atomic file writes and restrictive permissions to reduce accidental corruption, while recognizing that permissions alone cannot protect against the owning user. - Add tampering tests covering modified state, altered evidence files, forged hashes, broken links, and fabricated class coverage. ]]>
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (7)

Lp3

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding
The skill describes installation and usage patterns that can lead an agent to read and write local files, but it does not declare any explicit tool scope or allowed-tools/permissions boundary. In an agent ecosystem, this ambiguity can cause over-broad file access during execution, increasing the chance of unintended modification or disclosure of local data.

Vague Triggers

Medium
Confidence
90% confidence
Finding
The trigger phrases are very broad and marketing-oriented, with no exclusions or confirmation requirements, so an agent may invoke this skill in situations where certification, evidence scanning, or badge generation was not actually intended. That can lead to inappropriate workflow activation, unnecessary handling of sensitive artifacts, and misleading outputs framed as compliance-oriented results.

Vague Triggers

Medium
Confidence
88% confidence
Finding
The repeated invocation guidance reinforces natural-language triggers without defining when the skill should be skipped, which increases the probability of accidental or overly eager activation. In a compliance-themed skill, this is more dangerous because agents may treat the output as authoritative and initiate evidence-processing steps on user content unnecessarily.

Rp1

Medium
Category
MCP Rug Pull
Confidence
91% confidence
Finding
Using `npx skills` without a pinned version allows whatever package version is current at execution time to run, which creates a supply-chain risk. If the upstream package is compromised, renamed, or updated incompatibly, an agent or user could execute unreviewed code with local privileges.

Natural-Language Policy Violations

Low
Confidence
83% confidence
Finding
This markdown file contains user-facing natural language primarily in Chinese, with only the title bilingualized, and does not indicate that language selection is optional. The policy for this audit flags language or locale constraints when a skill appears to force a specific language without user opt-in or clear justification.

Natural-Language Policy Violations

Low
Confidence
88% confidence
Finding
The manifest sets the category to "AI 治理" in Chinese, which imposes a specific language presentation in user-facing metadata without any indication of language choice or a documented region-specific constraint. This can conflict with language/locale policy expectations when skills are expected to be locale-neutral or offer opt-in.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
The NOW function hard-codes timestamps to "+08:00", which imposes a specific locale/timezone behavior on all generated artifacts. The file does not offer a user choice or document this as a region-specific requirement, so it conflicts with the language/locale policy criteria.

Static analysis

No suspicious patterns detected.