Skip to main content
Sigvex

Unconnected Component Inputs

Detects component instantiations where outputs are read but inputs are not wired, leaving the sub-circuit unconstrained and enabling proof forgery.

Unconnected Component Inputs

Overview

Remediation Guide: How to Fix Unconnected Component Inputs

The unconnected component inputs detector identifies cases where a component is instantiated and its outputs are read, but none of its inputs are wired. When a component’s inputs are not connected, the sub-circuit’s computation is unconstrained – the prover controls what values the outputs take, and the verifier cannot detect the manipulation.

Circom components are template instances. When you write component h = Poseidon(1), the Poseidon template’s constraints are included in the R1CS, but the template’s input signals are free variables unless you wire them. If you read h.out without ever assigning h.inputs[0], the prover can set h.out to any value that satisfies Poseidon’s constraints for some arbitrary input.

Why This Is an Issue

Components encapsulate sub-circuits. Their inputs must be wired to parent signals (via <==) so that the sub-circuit’s constraints connect to the parent circuit. Without input wiring, the component is an isolated island of constraints – the prover can satisfy them independently with any values, then feed those values back into the parent circuit.

A common scenario: a developer instantiates a hash component, reads the output, but forgets to wire the input. The prover can then set the “hash output” to any value, bypassing the hash computation entirely.

How to Resolve

Wire all component inputs using constraining assignments (<==).

// Before: Vulnerable -- component output used, but input never wired
component hasher = Poseidon(1);
// hasher.inputs[0] is never assigned!
digest <== hasher.out;  // prover controls this value

// After: Fixed -- input wired via <==
component hasher = Poseidon(1);
hasher.inputs[0] <== preimage;  // input is now constrained
digest <== hasher.out;          // output is determined by preimage

Examples

Vulnerable Code

template BrokenVerifier() {
    signal input data;
    signal output hash;

    component h = Poseidon(1);
    // BUG: h.inputs[0] is never assigned
    hash <== h.out;  // output is read but input is floating
}

The prover can satisfy Poseidon’s internal constraints with any input and produce a corresponding output. Since no parent signal is wired to h.inputs[0], the hash bears no relation to data.

Fixed Code

template CorrectVerifier() {
    signal input data;
    signal output hash;

    component h = Poseidon(1);
    h.inputs[0] <== data;   // input wired to parent signal
    hash <== h.out;          // output is now determined by `data`
}

Sample Sigvex Output

CRITICAL  unconnected-component-inputs
  Component outputs used but inputs not connected

  Component 'h' (type 'Poseidon') has outputs read but no inputs are assigned.
  The component's computation is unconstrained -- the prover can set the outputs
  to arbitrary values.

  Template: BrokenVerifier
  Confidence: 0.85

  Recommendation: Wire all component inputs using `<==` to ensure the sub-circuit
  is properly constrained.

Detection Methodology

For each component instantiation within a template, the detector builds two sets:

  1. Connected inputs: signals written to the component via assignments where the LHS matches component_name.signal_name (e.g., h.inputs[0] <== data).
  2. Connected outputs: signals read from the component, detected by scanning assignment RHS expressions for references matching component_name.signal_name (e.g., hash <== h.out).

Three cases are checked:

  • No connections at all: the component is instantiated but never used (reported as a separate “disconnected-component” finding at High severity).
  • Outputs read but no inputs wired: the critical case this detector targets (reported at Critical severity, confidence 0.85).
  • Inputs wired but outputs unused: not flagged by this detector (the component’s constraints are active, just unused results).

Limitations

  • Pattern-based input detection. If inputs are wired through an intermediate computation or via dynamic assignment patterns, the detector may not recognize the connection.
  • Does not verify that all inputs are wired – only that at least one is. A component with 3 inputs where only 1 is wired will not be flagged. Partial wiring detection is planned.
  • Array-indexed component inputs (e.g., h.inputs[i] where i is a variable) may not be recognized.

References