Back to skill

Security audit

agent-output-registry

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a coherent local output registry, but its mutable global install instructions and weak registry/export safeguards deserve manual review before use.

Install only from a pinned, reviewed commit or release rather than the unpinned global command. Use the tool in a dedicated directory, avoid registering sensitive outputs, treat CSV exports as untrusted when opening them in spreadsheets, and do not rely on the short LGD-REG identifier alone for high-stakes provenance checks.

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

Error
Location
SKILL.md:87
Finding
Unpinned Package Execution in Installation Instructions## Vulnerability Details **File Location**: `SKILL.md:87-90` **Vulnerability Type**: Supply-chain exposure through unpinned external packages and mutable repositories **Risk Level**: High ```bash npx skills add zhaoxinghua09-cell/agent-skills -g git clone https://github.com/zhaoxinghua09-cell/agent-skills.git ``` ### Technical Analysis The documented one-line installation uses `npx` without specifying an exact package version, integrity digest, lockfile, or verified publisher identity. Depending on the local npm configuration and cache state, `npx` can retrieve and execute the currently resolved version of the `skills` package. The alternative installation method clones a mutable branch rather than a reviewed commit. Consequently, the content installed by either command may differ from the content that was audited. The global installation option also increases the scope of any compromised package or repository content. This issue affects the documented installation path rather than the audited Python runtime, which itself has no third-party dependencies. ### Attack Path 1. An attacker compromises, replaces, or otherwise influences the npm package resolved as `skills`, or compromises the referenced repository. 2. The remote package or repository is modified after this Skill package has been reviewed. 3. A user follows the installation command from `SKILL.md`. 4. `npx` retrieves and executes the mutable package, or Git clones mutable repository content. 5. Attacker-controlled installation logic or Skill files run with the invoking user's permissions and may be installed globally. ### Impact Assessment Successful exploitation can execute code with the privileges of the user running the installation command. The global installation option may modify shared user-level Skill directories and affect multiple future agent sessions. No privilege escalation beyond the invoking user's existing permissions is demonstrated by th ...[truncated 16 chars]
Remediation
## Remediation Suggestions - Pin the installer package to an exact reviewed version, such as `npx package-name@x.y.z`. - Verify the package publisher and publish expected package integrity hashes. - Pin Git installations to a reviewed commit hash or signed release tag. - Verify downloaded content against a published SHA-256 digest or signed release. - Avoid global installation by default and document the exact files and permissions modified. - Clarify that “zero dependencies” applies to runtime code and not necessarily to the installation mechanism.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/output_registry.py:53
Finding
Spreadsheet Formula Injection Through CSV Registry Fields## Vulnerability Details **File Location**: `scripts/output_registry.py:53-55` **Related Input Location**: `scripts/output_registry.py:123-126` **Vulnerability Type**: CSV formula injection **Risk Level**: Medium ```python for r in rows: w.writerow([r["id"], r["ts"], r["model"], r["version"], r["out_hash"][:19], r["prompt_hash"][:19], r.get("issuer", ""), r.get("license", ""), r.get("summary", "")]) ``` The exported values originate in part from command-line arguments: ```python pa = sub.add_parser("add"); pa.add_argument("--out", required=True); pa.add_argument("--model") pa.add_argument("--version"); pa.add_argument("--prompt", default=""); pa.add_argument("--issuer") pa.add_argument("--license") ``` ### Technical Analysis User-controlled values from `--model`, `--version`, `--issuer`, `--license`, and the output summary are written directly into CSV cells. Python's CSV quoting protects the CSV structure, but it does not prevent spreadsheet applications from interpreting cells beginning with characters such as `=`, `+`, `-`, or `@` as formulas. An attacker able to influence registration metadata or output text can therefore place a spreadsheet formula in `registry/registry.csv`. The payload is activated when an operator opens the generated CSV in a spreadsheet application that evaluates formulas. ### Attack Path 1. An attacker supplies crafted registration metadata or output text whose value begins with a spreadsheet formula marker. 2. The `add` command stores the untrusted value in the JSONL registry. 3. `save()` writes the value unchanged into `registry/registry.csv`. 4. An auditor or operator opens the CSV file in a spreadsheet application. 5. The application evaluates the cell as a formula. 6. Depending on the spreadsheet application and its security settings, the formula may initiate external requests, disclose spreadsheet data, alter displayed audit information, or invoke app ...[truncated 455 chars]
Remediation
## Remediation Suggestions - Sanitize every untrusted CSV field before export. - Prefix values beginning with `=`, `+`, `-`, `@`, tab, or carriage return with a single quote or another application-compatible neutralization character. - Apply sanitization to model, version, issuer, license, summary, and any future user-controlled columns. - Keep the JSONL file as the canonical data source and treat CSV as an escaped presentation format. - Add regression tests using representative formula payloads. - Warn users not to bypass spreadsheet protected-view or external-content controls when opening registry exports.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/output_registry.py:73
Finding
Collision-Prone Registry IDs Cause Ambiguous Verification and Lookup## Vulnerability Details **File Location**: `scripts/output_registry.py:73` **Related Locations**: `scripts/output_registry.py:89-90`, `scripts/output_registry.py:102-103` **Vulnerability Type**: Truncated security identifier and duplicate-record ambiguity **Risk Level**: Medium ```python rid = "LGD-REG-" + out_hash[7:15] ``` Lookup and verification select the first matching record: ```python hit = next((r for r in rows if r["id"] == a.id), None) ``` ### Technical Analysis Registry IDs contain only eight hexadecimal characters from the SHA-256 output hash, providing a 32-bit identifier space. The complete output digest remains in each record, but the public identifier used by `lookup` and `verify` is substantially truncated. The `add` operation does not reject duplicate IDs. Both `lookup` and `verify` use `next(...)`, so only the first matching record is considered. Multiple outputs sharing the same 32-bit prefix can therefore produce the same public ID while retaining different full hashes and ownership metadata. A targeted match against an existing 32-bit prefix requires approximately \(2^{32}\) hash attempts on average, while collisions somewhere in a growing collection become likely much earlier due to the birthday bound. ### Attack Path 1. An attacker identifies a registry ID whose provenance they want to confuse. 2. The attacker varies controlled output content and computes SHA-256 hashes until one has the same first eight hexadecimal characters. 3. The colliding output is registered and receives the same `LGD-REG-xxxxxxxx` identifier. 4. The registry accepts both records without detecting the duplicate identifier. 5. A user invokes `lookup` or `verify` using the ambiguous ID. 6. The program silently selects the first matching record, potentially returning unexpected ownership metadata or comparing the supplied file against the wrong full digest. ### Impact Assessment The flaw undermines the uniq ...[truncated 267 chars]
Remediation
## Remediation Suggestions - Use the complete SHA-256 digest as the registry identifier, or retain at least 128 bits of the digest. - Reject duplicate identifiers during `add`. - Require `lookup` and `verify` to detect multiple matches and fail safely instead of selecting the first record. - Bind verification directly to the complete digest stored in an unambiguous record. - Consider using a separately generated UUID while preserving the complete SHA-256 digest as the immutable content identity. - Add tests covering duplicate IDs, deliberately truncated-prefix collisions, and malformed registry records.
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (10)

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill explicitly instructs users to run local Python commands that create and update a local registry, but it does not declare any tool scope such as file-write permissions or allowed tools. In agent environments, this mismatch can cause the agent to perform filesystem modifications without transparent capability boundaries, increasing the risk of unintended writes or abuse if the skill is triggered in the wrong context.

Vague Triggers

Medium
Confidence
84% confidence
Finding
The description includes trigger phrases such as "有籍" and "审计留痕", which are short and broad enough to overlap with ordinary discussion rather than a narrowly scoped invocation. The file does not provide negative examples or explicit activation boundaries to clarify when the skill should not activate.

Natural-Language Policy Violations

Medium
Confidence
89% confidence
Finding
The manifest description presents the skill behavior and trigger guidance only in Chinese, which can impose a language-specific interaction model without documented user opt-in. There is no statement that users may choose another language or that the locale restriction is intentional and justified.

Rp1

Medium
Category
MCP Rug Pull
Confidence
89% confidence
Finding
The installation instructions use `npx skills add ...` without pinning a specific version of the `skills` package or equivalent trusted source. This creates a supply-chain risk because users may execute whatever version is current at install time, including a compromised or behaviorally different release.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
This file contains natural-language content in Chinese for the summary fields on both lines, but provides no indication that language choice is optional or that the registry is intentionally restricted to Chinese users. Per the policy, forcing a specific language without user opt-in or documented justification is a locale-policy violation.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The natural-language interface, command descriptions, and output messaging are presented entirely in Chinese, with no indication that other languages are supported or that the user can opt into this locale. This can violate language/locale policy when a skill implicitly constrains users to a specific language without documented justification or choice.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The tool persistently stores prompt-derived metadata and output summaries to local registry files without any consent prompt, sensitivity warning, redaction option, or access controls. Even though it stores a prompt hash rather than raw prompt text, the saved summary may contain sensitive generated content, and users may not realize that provenance records are being written to disk in multiple formats.

Natural-Language Policy Violations

Low
Confidence
77% confidence
Finding
This file contains natural-language content and leads with Chinese in the title and body labels, which can be interpreted as a language preference decision. The policy says to flag language or locale constraints when they are imposed without user choice or clear justification.

Natural-Language Policy Violations

Low
Confidence
87% confidence
Finding
The file uses Chinese-only headers and summary text throughout, which constitutes a language-specific constraint in natural-language content. There is no indication that users can opt into this locale or that the file is intentionally limited to a Chinese-language or region-specific context.

Description-Behavior Mismatch

Low
Confidence
92% confidence
Finding
The module docstring and manifest position the tool as recording not only hashes, model/version, timestamp, and ownership, but also '血缘' or provenance lineage. In the actual stored record, only id, timestamp, model, version, output hash, prompt hash, issuer, license, and summary are written; there is no lineage field or related logic.

Static analysis

No suspicious patterns detected.