Underconstrained Outputs (uc-outputs
)
Summary and Usage
The Underconstrained Output (UCO) detector finds underconstrained output vulnerabilities in ZK circuit code. The UCO detector looks to see if a used output from a component is constrained either by an input value or a single constant value; if neither is true, then the output is not constrained and can result in a vulnerability, as a malicious actor may be able to create valid proofs for bogus statements when outputs are underconstrained.
Usage
The UCO detector is invoked by selecting "Underconstrained outputs"
(uc-outputs
) in the Detector selection during the tool configuration step.
Example and Explanation
The following toy example is designed to determine if the lowest bit of the
input signal inp
is 1. If (inp & 1) = 1
, then outp
should be 1, and otherwise, outp
should be 0.
pragma circom 2.1.8;
template LowestBitIsOne() {
signal input inp;
signal output outp;
outp <-- inp & 1;
outp * (outp - 1) === 0;
}
component main = LowestBitIsOne();
In this example, outp
is assigned to inp & 1
, but is not constrained by the input inp
, which is flagged as a UCO bug.
While the outp * (outp - 1) === 0
constraint does constrain the outp
signal to a boolean value per the overall design
of the circuit, the constraint may be satisfied by the assignment outp = 0
or outp = 1
regardless of the value of inp
, allowing the
attacker to forge arbtrary proofs of the form {inp = <any value>, outp = <0 or 1>}
.
Usage Example
Running the UCO detector yields the following text output log:
ZK Vanguard Output
----Running Vanguard with uc-outputs detector----
Running detector: uc-outputs
[Critical] Underconstrained output signal in component LowestBitIsOne @ uc_outputs_bug.circom:3
Reported By: vanguard:uc-outputs
Location: LowestBitIsOne @ uc_outputs_bug.circom:3
Confidence: 0.99
More Info: placeholder
Details:
In template LowestBitIsOne @ uc_outputs_bug.circom:3
* Signal outp
Line 3 of the above log tells us there is an underconstrained output signal in the LowestBitIsOne
template (defined in uc_outputs_bug.circom
starting on line 3).
Lines 9–10 of the log tell us that outp
is the underconstrained output signal.
Limitations
- This detector may incur false positives if the output signal is designed to be constant constrained, but that constant is computed within the circuit (e.g., the output signal is a hash of a constant value).
- This detector will fail to detect issues where, e.g., an output signal is constrained by an input, but should be constrained by multiple inputs.
Assessing Severity
It is generally rare for output signals to not be a function of input signals or constants, so findings from this detector often indicate severe issues where key computations and constraints have been accidentally omitted. These findings are therefore