Skip to main content
Sigvex

Signal Aliasing Remediation

How to fix redundant equality constraints that create aliases without adding security.

Signal Aliasing Remediation

Overview

Related Detector: Signal Aliasing

Signal aliasing occurs when two signals are constrained to be equal (a === b) but neither signal is independently constrained. The equality ensures consistency between the two values, but if both are unconstrained, the prover can set them to any field element. The fix is to ensure at least one side of every equality constraint is independently bound to a meaningful value.

Before (Vulnerable)

template UnsafeProcessor() {
    signal input x;
    signal temp;
    signal output out;

    temp <-- complexComputation(x);
    out === temp;  // Alias: out equals temp, but temp is unconstrained
}

After (Fixed – Constrain the Source Signal)

template SafeProcessor() {
    signal input x;
    signal temp;
    signal output out;

    temp <-- complexComputation(x);
    temp * temp === x;  // Independent constraint on temp (e.g., sqrt)
    out <== temp;        // out now inherits the constraint
}

After (Fixed – Replace Alias with Direct Constraint)

template SafeProcessor() {
    signal input x;
    signal output out;

    out <-- complexComputation(x);
    out * out === x;  // Directly constrain out, no alias needed
}

Alternative Mitigations

1. Eliminate the Intermediate Signal

If the intermediate signal exists only as a computation step, remove it and constrain the output directly:

// Before: unnecessary alias
signal temp;
temp <-- a / b;
result === temp;

// After: direct constraint
result <-- a / b;
result * b === a;  // Direct constraint on result

2. Use Component Outputs Directly

Instead of aliasing a component output to a local signal, use the component output directly in downstream constraints:

component hash = Poseidon(2);
hash.inputs[0] <== a;
hash.inputs[1] <== b;
// Use hash.out directly instead of aliasing to a local signal
expectedHash === hash.out;

Common Mistakes

Assuming equality is a constraint: a === b is a constraint, but it only ensures a == b. If neither a nor b is independently bound, the constraint is satisfied for any value the prover chooses.

Chaining aliases: If a === b and b === c and none are independently constrained, you have three unconstrained signals that must be equal. This is equivalent to one unconstrained signal – no security is added by the chain.

Confusing assignment with constraint: a <== b is shorthand for a <-- b; a === b. If b is unconstrained, this still creates an unconstrained alias. The <== operator does not add constraint strength beyond what === provides.

References