Lint Reference
February 23, 2026 ยท View on GitHub
This document lists active enforced lints in aztec-lint and explains what each lint checks, why it matters, known limitations, and typical remediation.
Source of truth for this data is the canonical lint metadata catalog in crates/aztec-lint-core/src/lints/mod.rs.
Policy note: performance is the canonical metadata policy name; roadmap shorthand cost maps to performance.
AZTEC Pack
AZTEC001
- Pack:
aztec_pack - Category:
privacy - Maturity:
stable - Policy:
privacy - Default Level:
deny - Confidence:
medium - Introduced In:
0.1.0 - Lifecycle:
active - Summary: Private data reaches a public sink.
What it does: Flags flows where secret or note-derived values are emitted through public channels.
Why this matters: Leaking private values through public outputs can permanently expose sensitive state.
Known limitations: Flow analysis is conservative and may miss leaks routed through unsupported abstractions.
How to fix: Keep private values in constrained private paths and sanitize or avoid public emission points.
Examples:
- Avoid emitting note-derived values from public entrypoints.
References:
docs/suppression.mddocs/rule-authoring.md
AZTEC002
- Pack:
aztec_pack - Category:
privacy - Maturity:
preview - Policy:
privacy - Default Level:
deny - Confidence:
low - Introduced In:
0.1.0 - Lifecycle:
active - Summary: Secret-dependent branching affects public state.
What it does: Detects control flow where secret inputs influence public behavior.
Why this matters: Secret-dependent branching can reveal private information through observable behavior.
Known limitations: Heuristic path tracking may report false positives in complex guard patterns.
How to fix: Refactor logic so branch predicates for public effects are independent of private data.
Examples:
- Compute public decisions from public inputs only.
References:
docs/rule-authoring.mddocs/decisions/0003-confidence-model.md
AZTEC003
- Pack:
aztec_pack - Category:
privacy - Maturity:
stable - Policy:
privacy - Default Level:
deny - Confidence:
medium - Introduced In:
0.1.0 - Lifecycle:
active - Summary: Private entrypoint uses debug logging.
What it does: Reports debug logging in private contexts where logging may leak sensitive state.
Why this matters: Debug output can disclose values intended to remain private.
Known limitations: Custom logging wrappers are only detected when call patterns are recognizable.
How to fix: Remove debug logging from private code paths or replace it with safe telemetry patterns.
Examples:
- Do not print private witnesses in private functions.
References:
docs/suppression.mddocs/rule-authoring.md
AZTEC010
- Pack:
aztec_pack - Category:
protocol - Maturity:
stable - Policy:
protocol - Default Level:
deny - Confidence:
high - Introduced In:
0.1.0 - Lifecycle:
active - Summary: Private to public bridge requires #[only_self].
What it does: Checks enqueue-based private-to-public transitions enforce self-only invocation constraints.
Why this matters: Missing self-only restrictions can allow unauthorized cross-context execution.
Known limitations: Rule coverage is scoped to known enqueue bridge patterns.
How to fix: Apply the configured only-self attribute and ensure bridge entrypoints enforce it.
Examples:
- Annotate private-to-public bridge functions with #[only_self].
References:
docs/decisions/0001-aztec010-scope.mddocs/rule-authoring.md
AZTEC020
- Pack:
aztec_pack - Category:
soundness - Maturity:
stable - Policy:
soundness - Default Level:
deny - Confidence:
high - Introduced In:
0.1.0 - Lifecycle:
active - Summary: Unconstrained influence reaches commitments, storage, or nullifiers.
What it does: Detects unconstrained values that affect constrained Aztec protocol artifacts.
Why this matters: Unconstrained influence can break proof soundness and on-chain validity assumptions.
Known limitations: Transitive influence through unsupported helper layers may be missed.
How to fix: Introduce explicit constraints before values affect commitments, storage, or nullifiers.
Examples:
- Constrain intermediate values before writing storage commitments.
References:
docs/rule-authoring.mddocs/decisions/0003-confidence-model.md
AZTEC021
- Pack:
aztec_pack - Category:
soundness - Maturity:
stable - Policy:
soundness - Default Level:
deny - Confidence:
medium - Introduced In:
0.1.0 - Lifecycle:
active - Summary: Missing range constraints before hashing or serialization.
What it does: Reports values hashed or serialized without proving required numeric bounds first.
Why this matters: Unchecked ranges can make hash and encoding logic semantically ambiguous.
Known limitations: The rule cannot infer all user-defined range proof helper conventions.
How to fix: Apply explicit range constraints before hashing, packing, or serialization boundaries.
Examples:
- Add a range check before converting a field to a bounded integer.
References:
docs/rule-authoring.mddocs/decisions/0003-confidence-model.md
AZTEC022
- Pack:
aztec_pack - Category:
soundness - Maturity:
stable - Policy:
soundness - Default Level:
deny - Confidence:
medium - Introduced In:
0.1.0 - Lifecycle:
active - Summary: Suspicious Merkle witness usage.
What it does: Finds witness handling patterns that likely violate expected Merkle proof semantics.
Why this matters: Incorrect witness usage can invalidate inclusion guarantees.
Known limitations: Complex custom witness manipulation may produce conservative warnings.
How to fix: Verify witness ordering and path semantics against the target Merkle API contract.
Examples:
- Ensure witness paths and leaf values are paired using the expected order.
References:
docs/rule-authoring.mddocs/decisions/0003-confidence-model.md
AZTEC030
- Pack:
aztec_pack - Category:
soundness - Maturity:
preview - Policy:
soundness - Default Level:
deny - Confidence:
high - Introduced In:
0.5.0 - Lifecycle:
active - Summary: Note consumption without nullifier emission.
What it does: Reports note pop/consume patterns when the same function does not emit a nullifier.
Why this matters: Consumed notes without nullifiers can enable replay or double-spend style state inconsistencies.
Known limitations: Function-local matching does not prove path-complete nullifier coverage in highly dynamic control flow.
How to fix: Emit nullifiers for consumed notes or switch to helper APIs that enforce consume-and-nullify semantics.
Examples:
- After
pop_noteorpop_notes, emit the associated nullifier in the same function path.
References:
docs/rule-authoring.mddocs/decisions/0003-confidence-model.md
AZTEC031
- Pack:
aztec_pack - Category:
protocol - Maturity:
preview - Policy:
protocol - Default Level:
warn - Confidence:
medium - Introduced In:
0.5.0 - Lifecycle:
active - Summary: Nullifier hash appears missing domain separation inputs.
What it does: Flags nullifier hash call sites where required domain components are not present in hash inputs.
Why this matters: Weak nullifier domain separation can cause collisions across domains or protocol contexts.
Known limitations: Heuristic token matching may miss custom domain-separation helpers or aliases.
How to fix: Include configured domain fields (for example contract address and nonce) in nullifier hash inputs.
Examples:
- Include
this_addressandnonce(or equivalent fields) in the nullifier hash tuple.
References:
docs/rule-authoring.mddocs/decisions/0003-confidence-model.md
AZTEC032
- Pack:
aztec_pack - Category:
protocol - Maturity:
preview - Policy:
protocol - Default Level:
warn - Confidence:
medium - Introduced In:
0.5.0 - Lifecycle:
active - Summary: Commitment hash appears missing domain separation inputs.
What it does: Detects commitment-style hash sinks that do not include configured domain-separation components.
Why this matters: Insufficient commitment domain separation can blur security boundaries and weaken protocol assumptions.
Known limitations: Rule matching focuses on recognizable commitment sink names and hash-shaped inputs.
How to fix: Add required context fields (such as contract address and note type) to commitment hash construction.
Examples:
- Derive commitments with explicit domain tags instead of hashing only payload values.
References:
docs/rule-authoring.mddocs/decisions/0003-confidence-model.md
AZTEC033
- Pack:
aztec_pack - Category:
protocol - Maturity:
preview - Policy:
protocol - Default Level:
deny - Confidence:
high - Introduced In:
0.5.0 - Lifecycle:
active - Summary: Public entrypoint mutates private state without #[only_self].
What it does: Reports public entrypoints that appear to mutate private note/state transitions and lack only-self protection.
Why this matters: Publicly callable private-state mutation surfaces can break intended access boundaries.
Known limitations: Detection relies on recognized mutation patterns and may not cover every custom state transition helper.
How to fix:
Add #[only_self] to the public entrypoint or refactor the mutation into a safer private flow.
Examples:
- Mark public state-transition bridges with
#[only_self]before calling note mutation APIs.
References:
docs/rule-authoring.mddocs/decisions/0001-aztec010-scope.md
AZTEC034
- Pack:
aztec_pack - Category:
soundness - Maturity:
preview - Policy:
soundness - Default Level:
warn - Confidence:
medium - Introduced In:
0.5.0 - Lifecycle:
active - Summary: Hash input cast to Field without prior range guard.
What it does: Finds hash inputs that are cast or converted to Field without an earlier range-style constraint.
Why this matters: Missing range proofs can make hashed representations ambiguous for bounded integer semantics.
Known limitations: Nearby helper-based constraints may not be recognized when they do not resemble explicit range checks.
How to fix: Constrain numeric width before Field conversion and hashing, then keep the guarded value flow explicit.
Examples:
- Assert bounded
amountbefore hashingamount as Field.
References:
docs/rule-authoring.mddocs/decisions/0003-confidence-model.md
AZTEC035
- Pack:
aztec_pack - Category:
correctness - Maturity:
preview - Policy:
correctness - Default Level:
warn - Confidence:
medium - Introduced In:
0.5.0 - Lifecycle:
active - Summary: Suspicious repeated nested storage key.
What it does:
Flags .at(x).at(x)-style nested key repetition that often indicates copy-paste key mistakes.
Why this matters: Repeating nested map keys unintentionally can corrupt indexing logic and authorization behavior.
Known limitations: Some intentionally duplicated keying patterns may require suppression when semantically correct.
How to fix:
Use distinct key expressions for each nested .at(...) level or extract named key variables for clarity.
Examples:
- Replace
.at(owner).at(owner)with the intended second key such as.at(owner).at(spender).
References:
docs/rule-authoring.mddocs/suppression.md
AZTEC036
- Pack:
aztec_pack - Category:
privacy - Maturity:
preview - Policy:
privacy - Default Level:
warn - Confidence:
medium - Introduced In:
0.6.0 - Lifecycle:
active - Summary: Secret-dependent branch affects enqueue behavior.
What it does: Flags private or secret-influenced branching that changes whether or how enqueue-style bridge calls are emitted.
Why this matters: Observer-visible enqueue shape differences can leak private branch decisions.
Known limitations: Pattern matching is currently heuristic and may not cover every custom enqueue wrapper.
How to fix: Refactor enqueue behavior so public bridge decisions are independent of secret branch predicates.
Examples:
- Emit a fixed enqueue pattern and move secret-dependent logic into constrained private computation.
References:
docs/rule-authoring.mddocs/decisions/0003-confidence-model.md
AZTEC037
- Pack:
aztec_pack - Category:
privacy - Maturity:
preview - Policy:
privacy - Default Level:
warn - Confidence:
medium - Introduced In:
0.6.0 - Lifecycle:
active - Summary: Secret-dependent branch affects delivery count.
What it does: Reports branch-dependent behavior where secret inputs influence the number or presence of delivery-style effects.
Why this matters: Varying delivery cardinality on secret predicates can reveal private state through externally visible behavior.
Known limitations: Delivery sink coverage is currently scoped to recognized call patterns.
How to fix: Keep delivery count and emission structure invariant with respect to secret branch conditions.
Examples:
- Avoid conditional delivery emission based on private note values.
References:
docs/rule-authoring.mddocs/decisions/0003-confidence-model.md
AZTEC038
- Pack:
aztec_pack - Category:
correctness - Maturity:
preview - Policy:
correctness - Default Level:
warn - Confidence:
low - Introduced In:
0.6.0 - Lifecycle:
active - Summary: Change note appears to miss fresh randomness.
What it does: Detects change-note construction patterns that appear to reuse deterministic randomness or omit freshness inputs.
Why this matters: Weak randomness freshness can increase linkage risk and break expected note uniqueness properties.
Known limitations: Freshness detection is heuristic and may miss user-defined entropy helper conventions.
How to fix: Derive change-note randomness from a fresh, non-reused source and thread it explicitly into note construction.
Examples:
- Use a per-note fresh randomness value instead of reusing an existing note nonce.
References:
docs/rule-authoring.mddocs/suppression.md
AZTEC039
- Pack:
aztec_pack - Category:
correctness - Maturity:
preview - Policy:
correctness - Default Level:
warn - Confidence:
low - Introduced In:
0.6.0 - Lifecycle:
active - Summary: Partial spend logic appears unbalanced.
What it does: Flags partial-spend arithmetic patterns that do not clearly reconcile consumed, spent, and change values.
Why this matters: Unbalanced partial-spend accounting can cause invalid state transitions or silent value drift.
Known limitations: Equivalent arithmetic forms may not all be recognized by pattern-driven detection.
How to fix: Make spend and change reconciliation explicit and assert conservation-style invariants near the transition point.
Examples:
- Ensure
consumed = spend + changeis enforced before emitting updated notes.
References:
docs/rule-authoring.mddocs/suppression.md
AZTEC040
- Pack:
aztec_pack - Category:
protocol - Maturity:
preview - Policy:
protocol - Default Level:
deny - Confidence:
high - Introduced In:
0.6.0 - Lifecycle:
active - Summary: Initializer entrypoint missing #[only_self].
What it does: Reports initializer functions that are not protected by the expected only-self access restriction.
Why this matters: Unrestricted initializers can allow unauthorized setup flows or protocol-state takeover.
Known limitations: Framework-equivalent guards not expressed through the configured only-self signal may need suppression.
How to fix:
Annotate initializer entrypoints with #[only_self] or move privileged initialization behind a self-only gate.
Examples:
- Mark contract initializer functions with
#[only_self]before deployment use.
References:
docs/rule-authoring.mddocs/decisions/0001-aztec010-scope.md
AZTEC041
- Pack:
aztec_pack - Category:
correctness - Maturity:
preview - Policy:
correctness - Default Level:
warn - Confidence:
medium - Introduced In:
0.6.0 - Lifecycle:
active - Summary: Field/integer cast may truncate or wrap unexpectedly.
What it does: Finds cast patterns between Field and bounded integers that lack nearby guard conditions proving safe range.
Why this matters: Unchecked narrowing conversions can silently corrupt values and invalidate downstream protocol logic.
Known limitations: Guard recognition focuses on known range-check idioms and may miss custom helper abstractions.
How to fix: Add explicit range checks before narrowing casts and keep the guarded value flow local and visible.
Examples:
- Assert value bounds before converting
Fieldinto a narrower integer type.
References:
docs/rule-authoring.mddocs/decisions/0003-confidence-model.md
Noir Core Pack
NOIR001
- Pack:
noir_core - Category:
correctness - Maturity:
stable - Policy:
correctness - Default Level:
deny - Confidence:
high - Introduced In:
0.1.0 - Lifecycle:
active - Summary: Unused variable or import.
What it does: Detects declared bindings and imports that are not used.
Why this matters: Unused items can indicate dead code, mistakes, or incomplete refactors.
Known limitations: Generated code and macro-like patterns may trigger noisy diagnostics.
How to fix: Remove unused bindings or prefix intentionally unused values with an underscore.
Examples:
- Delete unused imports after refactoring call sites.
References:
docs/rule-authoring.md
NOIR002
- Pack:
noir_core - Category:
correctness - Maturity:
stable - Policy:
correctness - Default Level:
deny - Confidence:
medium - Introduced In:
0.1.0 - Lifecycle:
active - Summary: Suspicious shadowing.
What it does: Reports variable declarations that shadow earlier bindings in the same function scope.
Why this matters: Shadowing can hide logic bugs by silently changing which binding is referenced.
Known limitations: Intentional narrow-scope shadowing may be flagged when context is ambiguous.
How to fix: Rename inner bindings to make value flow explicit.
Examples:
- Use descriptive names instead of reusing accumulator variables.
References:
docs/rule-authoring.md
NOIR010
- Pack:
noir_core - Category:
correctness - Maturity:
stable - Policy:
correctness - Default Level:
deny - Confidence:
high - Introduced In:
0.1.0 - Lifecycle:
active - Summary: Boolean computed but not asserted.
What it does: Flags boolean expressions that appear intended for checks but never drive an assertion.
Why this matters: Forgotten assertions can leave critical invariants unenforced.
Known limitations: Rules cannot always infer whether an unasserted boolean is intentionally stored for later use.
How to fix: Use assert-style checks where the boolean is intended as a safety or validity guard.
Examples:
- Convert an unconsumed
is_validexpression into an assertion.
References:
docs/rule-authoring.md
NOIR020
- Pack:
noir_core - Category:
correctness - Maturity:
stable - Policy:
correctness - Default Level:
deny - Confidence:
high - Introduced In:
0.1.0 - Lifecycle:
active - Summary: Array indexing without bounds validation.
What it does: Detects index operations lacking an obvious preceding range constraint.
Why this matters: Unchecked indexing can cause invalid behavior and proof failures.
Known limitations: Complex index sanitization paths may not always be recognized.
How to fix: Establish and assert index bounds before indexing operations.
Examples:
- Assert
idx < arr.len()before readingarr[idx].
References:
docs/rule-authoring.md
NOIR030
- Pack:
noir_core - Category:
correctness - Maturity:
stable - Policy:
correctness - Default Level:
deny - Confidence:
medium - Introduced In:
0.1.0 - Lifecycle:
active - Summary: Unconstrained value influences constrained logic.
What it does: Reports suspicious influence of unconstrained data over constrained computation paths.
Why this matters: Mixing unconstrained and constrained logic can invalidate proof assumptions.
Known limitations: Inference can be conservative for deeply indirect data flow.
How to fix: Constrain values before they participate in constrained branches or outputs.
Examples:
- Introduce explicit constraints at trust boundaries.
References:
docs/rule-authoring.mddocs/decisions/0003-confidence-model.md
NOIR100
- Pack:
noir_core - Category:
maintainability - Maturity:
stable - Policy:
maintainability - Default Level:
warn - Confidence:
high - Introduced In:
0.1.0 - Lifecycle:
active - Summary: Magic number literal should be named.
What it does: Detects high-signal numeric literals used in branch/assert/hash/serialization and related protocol-sensitive contexts.
Why this matters: Named constants improve readability and reduce accidental misuse.
Known limitations: Low-signal plain local initializer literals are intentionally excluded from this rule.
How to fix: Define a constant with domain meaning and use it in place of the literal.
Examples:
- Replace
42withMAX_NOTES_PER_BATCH.
References:
docs/rule-authoring.md
NOIR101
- Pack:
noir_core - Category:
maintainability - Maturity:
preview - Policy:
maintainability - Default Level:
warn - Confidence:
low - Introduced In:
0.1.0 - Lifecycle:
active - Summary: Repeated local initializer magic number should be named.
What it does: Reports repeated literal values used in plain local initializer assignments within the same function/module scope.
Why this matters: Repeated unexplained initializer literals are often copy-pasted constants that should be named for clarity.
Known limitations: Single local initializer literals are intentionally skipped to reduce noise.
How to fix: Extract the repeated literal into a named constant and reuse it.
Examples:
- Replace repeated
let fee = 42; let limit = 42;with a shared constant.
References:
docs/rule-authoring.mddocs/decisions/0003-confidence-model.md
NOIR110
- Pack:
noir_core - Category:
maintainability - Maturity:
preview - Policy:
maintainability - Default Level:
warn - Confidence:
low - Introduced In:
0.1.0 - Lifecycle:
active - Summary: Function complexity exceeds threshold.
What it does: Flags functions whose control flow complexity passes the configured limit.
Why this matters: High complexity makes correctness and audits harder.
Known limitations: Simple metric thresholds cannot capture all maintainability nuances.
How to fix: Split large functions and isolate complex branches into focused helpers.
Examples:
- Extract nested decision trees into named helper functions.
References:
docs/rule-authoring.md
NOIR120
- Pack:
noir_core - Category:
maintainability - Maturity:
preview - Policy:
maintainability - Default Level:
warn - Confidence:
low - Introduced In:
0.1.0 - Lifecycle:
active - Summary: Function nesting depth exceeds threshold.
What it does: Flags deeply nested control flow that reduces readability and maintainability.
Why this matters: Deep nesting increases cognitive load and maintenance risk.
Known limitations: Certain generated or domain-specific patterns can be naturally nested.
How to fix: Use early returns and helper functions to flatten nested control flow.
Examples:
- Refactor nested conditionals into guard clauses.
References:
docs/rule-authoring.md