Back to skill

Security audit

consensus-deployment-guard

Security checks for vulnerabilities and agentic risk

Overview

The skill largely does what it claims, but it needs review because unbounded external vote data can be persisted and may exhaust storage or runtime resources in deployment automation.

Before installing in CI/CD automation, require bounded input sizes, maxItems/maxLength limits for external votes and nested strings, artifact-size checks, rate limits, and a dedicated non-privileged state directory. Also update or audit the dependency set. I found no evidence of intentional deception, exfiltration, credential theft, or destructive system behavior.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
spec/input.schema.json:10
Finding
Unbounded External Vote Input Can Cause Resource Exhaustion<![CDATA[ ## Vulnerability Details **File Locations**: - `spec/input.schema.json:10` - `spec/input.schema.json:75-83` - `src/index.mjs:53-57` - `src/index.mjs:116` - `src/index.mjs:161` **Vulnerability Type**: Uncontrolled resource consumption through unbounded, persisted input **Risk Level**: Medium ### Vulnerable Code `spec/input.schema.json:10`: ```json "external_votes": { "type": "array", "items": { "$ref": "#/$defs/externalVote" } }, ``` `spec/input.schema.json:75-83`: ```json "externalVote": { "type": "object", "additionalProperties": false, "required": ["persona_id", "name", "reputation_before", "vote", "confidence", "reasons", "red_flags", "suggested_edits"], "properties": { "persona_id": { "type": "string", "minLength": 1 }, "name": { "type": "string", "minLength": 1 }, "reputation_before": { "type": "number", "minimum": 0.05, "maximum": 0.95 }, "vote": { "type": "string", "enum": ["YES", "NO", "REWRITE"] }, "confidence": { "type": "number", "minimum": 0, "maximum": 1 }, "reasons": { "type": "array", "items": { "type": "string" } }, "red_flags": { "type": "array", "items": { "type": "string" } }, "suggested_edits": { "type": "array", "items": { "type": "string" } } } } ``` `src/index.mjs:53-57`: ```js if (input.external_votes !== undefined) { if (!Array.isArray(input.external_votes)) return 'external_votes must be array'; for (const vote of input.external_votes) { const ve = validateVote(vote); if (ve) return ve; } } ``` `src/index.mjs:116`: ```js const votes = externalMode ? input.external_votes : makeVotes(personaSet, flags); ``` `src/index.mjs:161`: ```js const d = await writeArtifact(board_id, 'decision', { idempotency_key: idem, decision_id, final_decision, policy_flags: flags, votes, aggregation: ag, response }, statePath); ``` ### Technical Analysis The input schema does not impose a `maxItems` restriction on `external_votes`. It also leaves the nested `reasons`, `red_flags`, an ...[truncated 2626 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Add a conservative `maxItems` limit to `external_votes` based on the maximum legitimate persona count: ```json "external_votes": { "type": "array", "minItems": 1, "maxItems": 50, "items": { "$ref": "#/$defs/externalVote" } } ``` 2. Bound every nested array and string: ```json "persona_id": { "type": "string", "minLength": 1, "maxLength": 128 }, "name": { "type": "string", "minLength": 1, "maxLength": 256 }, "reasons": { "type": "array", "maxItems": 20, "items": { "type": "string", "maxLength": 1000 } }, "red_flags": { "type": "array", "maxItems": 20, "items": { "type": "string", "maxLength": 500 } }, "suggested_edits": { "type": "array", "maxItems": 20, "items": { "type": "string", "maxLength": 1000 } } ``` 3. Apply suitable `maxLength` limits to all other caller-controlled strings, including `board_id`, `persona_set_id`, `request_id`, `service`, `version`, and `ticket_ref`. 4. Enforce a maximum request-body or input-file size before calling `JSON.parse`. API integrations should reject oversized bodies at the transport layer. 5. Calculate or estimate the serialized artifact size before invoking `writeArtifact`, and reject artifacts exceeding a configured upper bound. 6. Add authentication, per-caller rate limiting, memory limits, execution timeouts, filesystem quotas, and isolated writable volumes where the Skill is exposed through automation. 7. Add tests covering: - More than the permitted number of external votes. - Oversized strings. - Oversized nested arrays. - Maximum accepted boundary values. - Artifact-size rejection. - Repeated requests with distinct idempotency inputs. ]]>
Vulnerability Patterns
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (7)

Known Vulnerable Dependency: fast-uri==3.1.0 — 7 advisory(ies): CVE-2026-13676 (fast-uri vulnerable to host confusion via failed IDN canonicalization); CVE-2026-18446 (fast-uri vulnerable to host confusion via backslash authority introducer); CVE-2026-75975 (fast-uri vulnerable to server-side request forgery via malformed IPv6 normalizat) +4 more

High
Category
Supply Chain
Confidence
96% confidence
Finding
fast-uri 3.1.0 is directly present as a transitive dependency of ajv and is associated with multiple high-severity URI parsing issues including host confusion and potential SSRF bypasses. Because this skill is a deployment-governance component that likely validates and interprets structured request data, flawed URI canonicalization in dependency code could undermine security decisions if attacker-controlled URLs, hosts, or schema formats are processed.

Known Vulnerable Dependency: esbuild==0.27.3 — 1 advisory(ies): GHSA-g7r4-m6w7-qqqr (esbuild allows arbitrary file read when running the development server on Window)

Low
Category
Supply Chain
Confidence
60% confidence
Finding
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"demo": "node --import tsx run.js --input ./examples/input.json"
  },
  "dependencies": {
    "ajv": "^8.17.1",
    "ajv-formats": "^3.0.1",
    "consensus-guard-core": "^1.1.15",
    "tsx": "^4.20.3"
Confidence
40% confidence
Finding
Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Unpinned Dependencies

Low
Category
Supply Chain
Content
},
  "dependencies": {
    "ajv": "^8.17.1",
    "ajv-formats": "^3.0.1",
    "consensus-guard-core": "^1.1.15",
    "tsx": "^4.20.3"
  },
Confidence
40% confidence
Finding
Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"dependencies": {
    "ajv": "^8.17.1",
    "ajv-formats": "^3.0.1",
    "consensus-guard-core": "^1.1.15",
    "tsx": "^4.20.3"
  },
  "license": "MIT",
Confidence
40% confidence
Finding
Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"ajv": "^8.17.1",
    "ajv-formats": "^3.0.1",
    "consensus-guard-core": "^1.1.15",
    "tsx": "^4.20.3"
  },
  "license": "MIT",
  "engines": {
Confidence
40% confidence
Finding
Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Missing User Warnings

Low
Confidence
85% confidence
Finding
This .mjs code performs a state-changing write via writeArtifact, which can affect persisted board data. The file contains no confirmation prompt, user-facing log/print, or inline comment/docstring disclosing that the handler will write a decision record.

Static analysis

No suspicious patterns detected.