Back to skill

Security audit

rizzforms

Security checks for vulnerabilities and agentic risk

Overview

The skill is not clearly malicious, but it gives an agent broad RizzForms admin authority over forms, webhooks, and potentially personal submissions without enough scoping or consent guidance.

Review before installing. Use this only when you intentionally want RizzForms managing the form backend, prefer the narrowest API key permissions available, confirm before creating or changing forms/webhooks, and treat submissions and webhook payloads as potentially personal data subject to your privacy obligations. The package also claims a bundled CLI that is not present in the inspected artifact.

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

Note
Location
references/api.md:172
Finding

Non-Constant-Time Webhook Signature Comparison in Node.js Example

Content
View full analysis

Vulnerability Details

File Location: references/api.md, lines 172–177
Vulnerability Type: Timing side channel in authentication verification
Risk Level: Low

javascript
const crypto = require("crypto");
const expected = crypto.createHmac("sha256", signingSecret)
  .update(rawBody).digest("hex");
if (expected !== req.headers["x-rizzforms-signature"]) {
  return res.status(401).end();
}

Technical Analysis

The documented Node.js webhook-verification example compares the calculated HMAC and the supplied signature using JavaScript's ordinary string inequality operator (!==). Ordinary string comparisons are not guaranteed to run in constant time: execution may vary according to properties of the compared values, potentially including the position of the first differing character.

Because this reference is intended to be copied into webhook handlers, it may lead users to implement signature authentication with a timing side channel. The Ruby and Python examples in the same document appropriately use constant-time comparison functions, but the Node.js example does not.

Exploitation requires an attacker to submit a large number of chosen signatures and obtain sufficiently precise timing measurements. Network jitter, runtime optimization, and the absence of a guaranteed character-by-character comparison make remote exploitation difficult and environment-dependent; therefore, the finding is rated Low rather than treated as a reliable signature bypass.

Attack Path

  1. An attacker identifies a webhook handler implemented from the documented Node.js example.
  2. The attacker sends repeated requests containing the same chosen body and controlled X-RizzForms-Signature values.
  3. For each candidate signature prefix, the attacker gathers many response-time measurements to reduce network noise.
  4. If the runtime's comparison behavior creates a measurable prefix-dependent timing difference, the attack ...[truncated 1051 chars]
Remediation
View remediation

Remediation Suggestions

Replace the ordinary string comparison with Node.js crypto.timingSafeEqual() over equal-length byte buffers. Validate the signature format and length before comparison because timingSafeEqual() throws when buffer lengths differ.

javascript
const crypto = require("crypto");

const expected = crypto
  .createHmac("sha256", signingSecret)
  .update(rawBody)
  .digest();

const suppliedHex = req.headers["x-rizzforms-signature"];
if (
  typeof suppliedHex !== "string" ||
  !/^[0-9a-fA-F]{64}$/.test(suppliedHex)
) {
  return res.status(401).end();
}

const supplied = Buffer.from(suppliedHex, "hex");
if (
  supplied.length !== expected.length ||
  !crypto.timingSafeEqual(expected, supplied)
) {
  return res.status(401).end();
}

Additional hardening measures should include:

  • Verify the signature against the exact raw request bytes before JSON parsing or body transformation.
  • Reject missing, malformed, duplicated, or unexpectedly encoded signature headers.
  • Apply request-size limits and rate limiting to reduce timing sampling opportunities.
  • Avoid logging signing secrets or complete attacker-supplied authentication headers.
  • Add tests covering valid signatures, invalid signatures, malformed hexadecimal input, missing headers, and unequal lengths.
  • Document secret rotation and ensure old signing secrets are invalidated according to the intended rotation policy.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (6)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · references/api.md (reported line 152)May include surrounding context.

md
URL must be HTTPS. Private/reserved IPs are blocked (SSRF protection).

### DELETE /api/forms/:endpoint_token/plugins/:id — Remove Plugin

Requires: `can_create_forms`.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · SKILL.md (reported line 4)May include surrounding context.

md
---
name: rizzforms
description: |
  Create forms, configure webhook delivery, manage submissions, and generate
  embed HTML using the RizzForms API and bundled CLI. Use this skill whenever
  the user asks to add a contact form, feedback form, signup form, lead capture
  form, waitlist form, or any form that collects submissions and delivers them

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill activation guidance is unusually broad and directs use for many generic requests about forms, site integrations, and submissions. Over-broad routing can cause the agent to invoke a capability that collects data, manages webhooks, and uses admin credentials in situations where a narrower or safer skill would be more appropriate, increasing the chance of unintended external actions.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill explicitly supports transmitting form submissions, including personal data like names, emails, IP addresses, and message contents, to external webhooks, but it does not require any user-facing privacy disclosure, consent check, or data-handling warning. This creates a meaningful risk of collecting and forwarding personal information to third parties without adequate notice or governance.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · references/api.md (reported line 75)May include surrounding context.

text

Response includes: `endpoint_token`, `submission_url`, `json_url`, `embed_html`,
`examples` (curl commands), `help` (setup guidance).

### GET /api/forms — List Forms

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

This markdown file describes submission detail responses including source IP, user agent, referrer, and raw payload fields, but it does not provide any user-facing warning about handling potentially sensitive personal data. Under the markdown-specific missing-warning rule, documentation should disclose behaviors that may affect user data or privacy.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.