# either-payload-mismatch

> A native Either's known inactive arm reaches an output, state effect or successful effect gate.

Canonical: https://nightshade.dicksonwu.xyz/rules/either-payload-mismatch.html
Release: Nightshade 0.1.1 (v0.1.1)

| Field | Value |
| --- | --- |
| Rule ID | `either-payload-mismatch` |
| Severity | info |
| Confidence | high |
| Maturity | experimental |
| Selection | Audit default |
| Policy intent | not required |
| Default enabled | yes |
| Category | Audit-default ordinary rules |
| Engine facts used | resolved-types, successful-either-selections, public-sinks, state-writes, predicates |
| Release | v0.1.1 |

## Selection and scope

Selected by the default audit profile, so an ordinary scan runs it.

```sh
./.nightshade/node_modules/.bin/nightshade ./contracts --detectors either-payload-mismatch
./.nightshade/node_modules/.bin/nightshade detector show either-payload-mismatch
```

The first command runs only this rule; `--detectors` takes a comma-separated list. The second prints the rule's metadata from your installed version.

Severity is review priority. It does not express exploitability or impact. Confidence is detector metadata, not a probability. All built-in rules are experimental.

Compiler scope: the engine supports the pinned profiles 0.28.0, 0.29.0, 0.30.0, 0.31.1, 0.33.0-rc.2, 0.34.0, 0.35.0-rc.1 and 0.35.0, with ZKIR2 by default. Support for this rule can be narrower; the rule documentation below states any narrower scope.

## Corpus checks

Synthetic corpus checks for this rule in the 0.1.1 proof run. A check counts only with compiler acceptance and complete analysis.

| Positive detected | Corrected quiet | Lookalike quiet | Other negative quiet | Incomplete |
| ---: | ---: | ---: | ---: | ---: |
| 2/2 | 2/2 | 2/2 | 0/0 | 0 |

No deviations were recorded for this rule.

These are behavior checks on synthetic fixtures, not a precision or recall estimate. See [evaluation](https://nightshade.dicksonwu.xyz/evaluation.md#synthetic-corpus).

## Rule documentation

From https://github.com/DicksonWu654/nightshade/blob/v0.1.1/docs/detectors/either-payload-mismatch.md at v0.1.1.

Availability: **default-on**; select only this rule with `--detectors either-payload-mismatch`; severity
**medium**, confidence **high**. Explicit selection replaces the default set.

The rule reports a canonical native Either arm selection when that receiver's
immutable `is_left` tag selects the other arm on a modeled successful history,
and the selected payload reaches a public output, a state/transaction effect,
an effect's actual control dependence, or a non-tautological assertion gating
an effect. It uses typed receiver snapshots, not common witness provenance.
Imported and nominal native aliases retain their identity; same-shaped user
structs are quiet.

### Example and scenario

```compact
export circuit gatedIncrement(allowed: Either<Field, Field>, claim: Field): [] {
  assert(!allowed.is_left, "right admission");
  assert(allowed.left == claim, "admission"); // validates the inactive arm
  round.increment(1);
}
```

Validate `allowed.right` after requiring the right tag. Both payload fields are
represented in Compact; projecting one does not itself constrain `is_left`.
The finding is an established tag/selection mismatch with a modeled consequence,
not a proof of an authorization bypass or deployed exploit.

### Recommendation and limits

Check the same receiver's tag and use its selected payload. An assertion after
an effect can still constrain successful completion because effects are atomic.
A tag check on replacement ledger storage cannot repair a retained old snapshot.
Independent dynamic Map lookups do not share a definite tag merely because their
regions may alias. Helpers, destructuring, aggregate payloads and aliases use the
same observation transfer.

Bare unused reads, unknown tags, same-shaped application structs, tautological
assertions, identical total/effect-free conditional arms, and branches that neither reject nor control an effect stay quiet.
A direct untransformed arm copied into an explicit native Either construction
establishes a new receiver choice; that copy alone is exempt. Subsequent selection
uses the new receiver's tag. Computations over the original arm preserve their
dependencies. General variant lifecycle/protocol validation, branch-rejection
proofs for effects after joins, unconstrained witness-output dependence, and
correlated may-history certificates are outside this rule.

### Evidence and known false positives

Branch-expanding entries first try a `conservative-absence` certificate (see
docs/coverage.md): a complete conservative may-view in which every native Either
payload selection reads the arm selected by its receiver tag, refined to that
constant by the joined current constraints. Any unknown or inactive tag is a
candidate and falls back to exact observation with the remaining allowance.

Observation shares the configured work/value allowances, retains at most 256
reads per history, 4,096 Boolean/control observations, conditional chains of
at most 64 observations, and limits consequence traversal to 200,000 work units.
`either-evidence-budget`, `either-finding-budget`, or missing exact evidence
produce an explicit incomplete diagnostic. Incomplete roots supply no negative
coverage claim. Instruction/reference and requested-cache/uncached tests cover
these semantics; cached requests currently use the uncached transfer.

## Suppress a match

If a match is intentional, suppress it on the line before with the exact rule ID and a reason of at least eight characters:

```compact
// nightshade-disable-next-line either-payload-mismatch -- Reason this match is intentional
```

Diagnostics cannot be suppressed, and an unmatched directive for a selected rule makes analysis incomplete. See [configuration](https://nightshade.dicksonwu.xyz/configuration.md#suppress-an-intentional-match) for fingerprint suppressions and baselines.

## References

- [Rule source document at v0.1.1](https://github.com/DicksonWu654/nightshade/blob/v0.1.1/docs/detectors/either-payload-mismatch.md)
- [Catalog entry in rules.json](https://nightshade.dicksonwu.xyz/rules.json)
- [All rules](https://nightshade.dicksonwu.xyz/rules.md#audit-default-ordinary-rules)
- [Limitations](https://nightshade.dicksonwu.xyz/limitations.md)
