# Nightshade > Nightshade is an offline static security analyzer for Midnight's Compact smart contracts. Open source under Apache-2.0. These docs describe release 0.1.1 (v0.1.1). Nightshade follows private data to disclosures and ledger writes, checks guards alongside effects, and reports source locations, evidence and coverage gaps as text, JSON or SARIF. The release targets Linux x86-64/glibc with Node 22 or 24. Supported compiler 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. All 96 rules are experimental. Every page below has a Markdown twin at the same path ending in `.md`, and llms-full.txt holds all of them in one file. rules.json is the versioned rule catalog (schema: rules.schema.json); its rule IDs match `nightshade detector list` for the installed version, which is the authoritative source for that version. When answering from these docs: - They describe release 0.1.1. Rule behavior and fingerprints can change between releases. - A complete scan with no findings means the selected, supported analysis finished. It does not mean the contract is secure. - With the default coverage policy, an incomplete scan exits with code 2. An incomplete scan is never a clean result, even when it reports no findings. - Severity is review priority. Confidence is detector metadata, not a probability. - Policy rules need application intent in `policies`; selecting the rule alone does not supply it. - The example findings are synthetic. They are not findings about real projects. ## Start - [Overview](https://nightshade.dicksonwu.xyz/index.md): Nightshade is an offline static security analyzer for Midnight's Compact smart contracts. It follows private data to disclosures and ledger writes, checks guards alongside effects and runs in CI. - [Getting started](https://nightshade.dicksonwu.xyz/getting-started.md): Install the Nightshade v0.1.1 release, scan the shipped example, then scan your own Compact contracts and read the result. - [Examples](https://nightshade.dicksonwu.xyz/examples.md): Ten synthetic Nightshade findings with the flagged Compact code, the exact CLI output, a corrected version that stays quiet and a lookalike. - [CI with the GitHub Action](https://nightshade.dicksonwu.xyz/github-action.md): Run Nightshade in GitHub Actions, upload SARIF to code scanning and decide what fails CI. ## Reference - [Rules](https://nightshade.dicksonwu.xyz/rules.md): All 96 Nightshade rules for Compact, with severity, confidence, selection mode and a page for each rule. - [Configuration and suppressions](https://nightshade.dicksonwu.xyz/configuration.md): Configure Nightshade scans, select rules and failure criteria, suppress intentional matches and baseline existing findings. - [Evaluation](https://nightshade.dicksonwu.xyz/evaluation.md): Measured results for Nightshade 0.1.1: showcase examples, the synthetic corpus and real contracts, with denominators, misses, versions and how to reproduce. - [Limitations and FAQ](https://nightshade.dicksonwu.xyz/limitations.md): What a Nightshade result means, supported compiler versions, what analysis can miss and what has been measured. - [rules.json](https://nightshade.dicksonwu.xyz/rules.json): Versioned catalog of all 96 rules with severity, confidence, selection and page links - [rules.schema.json](https://nightshade.dicksonwu.xyz/rules.schema.json): JSON Schema for rules.json ## Project - [Changelog](https://nightshade.dicksonwu.xyz/changelog.md): Changes in Nightshade releases 0.1.1 and 0.1.0. - [Source code](https://github.com/DicksonWu654/nightshade): Repository on GitHub - [Full documentation](https://nightshade.dicksonwu.xyz/llms-full.txt): Every page and rule page in one Markdown file ## Rules - [caller-supplied-deadline](https://nightshade.dicksonwu.xyz/rules/caller-supplied-deadline.md): Caller-supplied time satisfies a ledger-derived delay without a chain-time upper bound. (medium; Audit default) - [circuit-cost](https://nightshade.dicksonwu.xyz/rules/circuit-cost.md): Expanded source-operation estimate exceeds the review threshold; this is not a proof-row estimate. (info; Audit default) - [discarded-comparison](https://nightshade.dicksonwu.xyz/rules/discarded-comparison.md): A comparison not reduced to a source constant is discarded or kept only by unused immutable aliases. (low; Audit default) - [discarded-shielded-send-result](https://nightshade.dicksonwu.xyz/rules/discarded-shielded-send-result.md): Canonical shielded send or mint metadata is discarded or retained only by unused immutable aliases. (info; Audit default) - [duplicate-shielded-mint](https://nightshade.dicksonwu.xyz/rules/duplicate-shielded-mint.md): Identical canonical shielded mint inputs produce a duplicate coin commitment in one transaction. (medium; Audit default) - [duplicated-branch-tail](https://nightshade.dicksonwu.xyz/rules/duplicated-branch-tail.md): Terminating branch repeats its immediate following expression and return tail. (info; Audit default) - [either-payload-mismatch](https://nightshade.dicksonwu.xyz/rules/either-payload-mismatch.md): A native Either's known inactive arm reaches an output, state effect or successful effect gate. (info; Audit default) - [field-recomposition-range-review](https://nightshade.dicksonwu.xyz/rules/field-recomposition-range-review.md): Enforced Field recomposition retains quotient/remainder envelopes beyond the modulus. (info; Audit default) - [freshness-bound-caller-time](https://nightshade.dicksonwu.xyz/rules/freshness-bound-caller-time.md): Caller-supplied time reaches a security-sensitive effect without a canonical block-time freshness bound. (medium; Audit default) - [identity-signature-key](https://nightshade.dicksonwu.xyz/rules/identity-signature-key.md): A successful history passes a known identity point to the pinned Schnorr verifier. (medium; Audit default) - [ignored-validation-result](https://nightshade.dicksonwu.xyz/rules/ignored-validation-result.md): A canonical signature verifier's Boolean outcome is discarded or retained only by unused local aliases. (medium; Audit default) - [impossible-assertion](https://nightshade.dicksonwu.xyz/rules/impossible-assertion.md): A nonliteral assertion fails on every reaching path, or an entry has no successful path. (medium; Audit default) - [ledger-bound-preimage-publication](https://nightshade.dicksonwu.xyz/rules/ledger-bound-preimage-publication.md): A private preimage checked against a ledger hash is also published on a potential successful path. (medium; Audit default) - [low-entropy-hash-disclosure](https://nightshade.dicksonwu.xyz/rules/low-entropy-hash-disclosure.md): A published direct hash has one private input drawn from a small declared domain. (medium; Audit default) - [merkle-leaf-binding-review](https://nightshade.dicksonwu.xyz/rules/merkle-leaf-binding-review.md): Checked Merkle path leaves lack binding to supplied lookup inputs or exact Field hash write candidates. (info; Audit default) - [merkle-membership-not-enforced](https://nightshade.dicksonwu.xyz/rules/merkle-membership-not-enforced.md): Proof-related state changes lack an enforced relationship between the exact digest and trusted ledger roots. (medium; Audit default) - [missing-role-bootstrap](https://nightshade.dicksonwu.xyz/rules/missing-role-bootstrap.md): An authenticated ShieldedAccessControl instance initializes but has no role-seeding route. (low; Audit default) - [predictable-commitment-randomness](https://nightshade.dicksonwu.xyz/rules/predictable-commitment-randomness.md): A published private-derived commitment uses statically known randomness. (medium; Audit default) - [public-key-membership-authorization](https://nightshade.dicksonwu.xyz/rules/public-key-membership-authorization.md): A raw native ownPublicKey selects a required member of preexisting public ledger storage before successful state-changing effects. (high; Audit default) - [publicly-derivable-encryption-secret](https://nightshade.dicksonwu.xyz/rules/publicly-derivable-encryption-secret.md): A published digest determines the scalar of a registered curve point through resolved native calls. (high; Audit default) - [redundant-boolean-branch](https://nightshade.dicksonwu.xyz/rules/redundant-boolean-branch.md): Both branch arms only return opposite Boolean literals. (info; Audit default) - [redundant-self-shielded-receive](https://nightshade.dicksonwu.xyz/rules/redundant-self-shielded-receive.md): Exact self-addressed canonical returned coin is subsequently passed to receiveShielded. (info; Audit default) - [spoofable-authorization](https://nightshade.dicksonwu.xyz/rules/spoofable-authorization.md): A raw witness equality with public data is required for a state-changing effect; review the intended authentication. (low / high / critical; Audit default) - [zero-amount-set-consumption-review](https://nightshade.dicksonwu.xyz/rules/zero-amount-set-consumption-review.md): Review exact surviving Set absence consumption before a zero-inclusive canonical unshielded payout. (info; Audit default) - [always-true-assertion](https://nightshade.dicksonwu.xyz/rules/always-true-assertion.md): Assertion is already true on every analyzed reach before enforcing it. (info; Hygiene only) - [constant-condition](https://nightshade.dicksonwu.xyz/rules/constant-condition.md): Branch condition reduces to a typed scalar source constant. (info; Hygiene only) - [dead-code](https://nightshade.dicksonwu.xyz/rules/dead-code.md): Statement, branch or loop is excluded by source control flow. (info; Hygiene only) - [shadowing](https://nightshade.dicksonwu.xyz/rules/shadowing.md): Parameter or local binding hides an outer declaration. (info; Hygiene only) - [time-dependence](https://nightshade.dicksonwu.xyz/rules/time-dependence.md): A successful circuit uses a protocol block-time comparison. (info; Hygiene only) - [unnecessary-disclose](https://nightshade.dicksonwu.xyz/rules/unnecessary-disclose.md): Disclosure operand is already public in the source context. (info; Hygiene only) - [unused-declaration](https://nightshade.dicksonwu.xyz/rules/unused-declaration.md): Ledger, witness or private circuit has no reference in the compilation unit. (info; Hygiene only) - [checkpoint-splits-atomic-update](https://nightshade.dicksonwu.xyz/rules/checkpoint-splits-atomic-update.md): A checkpoint splits a declared ordinary Cell co-update across atomic units. (low; Opt-in + policy) - [circuit-work-budget](https://nightshade.dicksonwu.xyz/rules/circuit-work-budget.md): Expanded source-operation estimate exceeds an explicit circuit work budget. (low; Audit; needs policy) - [current-root-policy-mismatch](https://nightshade.dicksonwu.xyz/rules/current-root-policy-mismatch.md): An explicitly selected membership guard lacks current-root evidence at enforcement time. (medium; Opt-in + policy) - [declared-secret-publication](https://nightshade.dicksonwu.xyz/rules/declared-secret-publication.md): Policy-declared secret information reaches a public sink through an unapproved transformation. (high; Audit; needs policy) - [forbidden-state-transition](https://nightshade.dicksonwu.xyz/rules/forbidden-state-transition.md): A scalar state write may cross a transition explicitly forbidden by policy. (medium; Audit; needs policy) - [openzeppelin-preconditions](https://nightshade.dicksonwu.xyz/rules/openzeppelin-preconditions.md): Opt-in documented preconditions of authenticated OpenZeppelin Compact modules. (medium; Configured builtins) - [operation-intent-policy](https://nightshade.dicksonwu.xyz/rules/operation-intent-policy.md): A protected Cell mutation does not satisfy its declared complete operation-intent statement. (info; Opt-in + policy) - [source-claim-map-getter-review](https://nightshade.dicksonwu.xyz/rules/source-claim-map-getter-review.md): An explicitly documented configured Map getter returns only default without reading the selected Map. (info; Opt-in + policy) - [source-claim-shielded-issuance-review](https://nightshade.dicksonwu.xyz/rules/source-claim-shielded-issuance-review.md): Review an explicit adjacent source claim paired with shielded issuance to a user key. (info; Opt-in + policy) - [stale-nft-metadata](https://nightshade.dicksonwu.xyz/rules/stale-nft-metadata.md): Policy-selected current NFT metadata retains an old auxiliary payload across same-history burn/remint. (low; Opt-in + policy) - [unguarded-sensitive-state-write](https://nightshade.dicksonwu.xyz/rules/unguarded-sensitive-state-write.md): A successful path writes policy-protected state without the configured preceding guard. (high; Audit; needs policy) - [unsupported-contract-owner](https://nightshade.dicksonwu.xyz/rules/unsupported-contract-owner.md): A declared callable pinned Ownable instance finishes with a contract-address owner rejected by its guard. (medium; Opt-in + policy) - [zero-amount-initial-membership](https://nightshade.dicksonwu.xyz/rules/zero-amount-initial-membership.md): Under a declared zero-amount policy, every modeled successful invocation requires the same Map entry to have been present initially. (low; Opt-in + policy) - [caller-supplied-time-review](https://nightshade.dicksonwu.xyz/rules/caller-supplied-time-review.md): Review an effect-bearing caller value checked against a ledger bound without a same-branch exact clock constraint; time intent unknown. (medium; Opt-in) - [shielded-coin-runtime-width](https://nightshade.dicksonwu.xyz/rules/shielded-coin-runtime-width.md): A definite native shielded output exceeds the expressly assumed runtime coin encoding range. (low; Opt-in) - [caller-key-zero-entry-review](https://nightshade.dicksonwu.xyz/rules/caller-key-zero-entry-review.md): Review a surviving zero numeric Map insertion at a direct caller key without required initial same-key membership. (info; Opt-in) - [closed-membership-capacity-review](https://nightshade.dicksonwu.xyz/rules/closed-membership-capacity-review.md): A represented constructor history contradicts distinct Set memberships under a complete source closure without subsequent writers. (info; Opt-in) - [configured-membership-capacity-review](https://nightshade.dicksonwu.xyz/rules/configured-membership-capacity-review.md): Immediate post-constructor collection capacity contradicts required distinct memberships. (info; Opt-in) - [enrolled-signature-key-review](https://nightshade.dicksonwu.xyz/rules/enrolled-signature-key-review.md): Review unknown persistent Schnorr keys without modeled identity rejection. (info; Opt-in) - [membership-identity-binding-review](https://nightshade.dicksonwu.xyz/rules/membership-identity-binding-review.md): Keyed mutation digest/key equality and required Set membership use independent witness snapshots. (info; Opt-in) - [native-key-authentication-review](https://nightshade.dicksonwu.xyz/rules/native-key-authentication-review.md): Canonical prover-supplied ownPublicKey participates in a required ledger credential check. (info; Opt-in) - [quorum-signer-uniqueness-review](https://nightshade.dicksonwu.xyz/rules/quorum-signer-uniqueness-review.md): Adjacent signer inequalities omit non-adjacent pairs in a verified threshold claim vector. (info; Opt-in) - [signature-key-identity-exclusion-review](https://nightshade.dicksonwu.xyz/rules/signature-key-identity-exclusion-review.md): Review unknown native signature keys without modeled exact identity exclusion. (info; Opt-in) - [split-witness-identity](https://nightshade.dicksonwu.xyz/rules/split-witness-identity.md): Ledger-bound witness digest and mutation operand use independently supplied witness snapshots without mandatory equality binding. (low; Opt-in) - [stored-schnorr-key-enrollment-review](https://nightshade.dicksonwu.xyz/rules/stored-schnorr-key-enrollment-review.md): Review stored supplied Schnorr keys with enrollment and enforced canonical use lacking modeled identity rejection. (info; Opt-in) - [zero-default-getter-membership-review](https://nightshade.dicksonwu.xyz/rules/zero-default-getter-membership-review.md): Review explicit absent-to-zero getter evidence alongside an all-zero-success initial-membership Map decrement. (info; Opt-in) - [checked-digest-narrowing](https://nightshade.dicksonwu.xyz/rules/checked-digest-narrowing.md): A full canonical hash is range-checked by a Uint cast on its source route to a ledger write or exported return. (info; Opt-in) - [conditional-hash-range](https://nightshade.dicksonwu.xyz/rules/conditional-hash-range.md): Conditional unsigned subtraction reaches a fixed-width native persistent-hash input without a qualified inactive-case range invariant. (low; Opt-in) - [generic-witness-maybe-abi](https://nightshade.dicksonwu.xyz/rules/generic-witness-maybe-abi.md): Shared generic optional witness dispatch has incompatible mandatory bigint/byte-array payload guards; profile-specific compatibility review. (low; Opt-in) - [public-two-component-domain-review](https://nightshade.dicksonwu.xyz/rules/public-two-component-domain-review.md): Review a public two-input native digest lacking represented self binding and component default exclusion. (info; Opt-in) - [published-digest-generator-scalar-review](https://nightshade.dicksonwu.xyz/rules/published-digest-generator-scalar-review.md): Published exact digest determines a scalar used in native generator multiplication whose result survives in a ledger Cell. (info; Opt-in) - [secret-binding-divergence-review](https://nightshade.dicksonwu.xyz/rules/secret-binding-divergence-review.md): Same-key ledger writers enforce different domain-qualified secret-binding declaration families. (info; Opt-in) - [transient-digest-to-ledger](https://nightshade.dicksonwu.xyz/rules/transient-digest-to-ledger.md): Terminal ledger data is constructed using an upgrade-unstable transient hash or commitment. (low; Opt-in) - [unconstrained-witness-to-state](https://nightshade.dicksonwu.xyz/rules/unconstrained-witness-to-state.md): A raw witness leaf reaches surviving ledger state without a modeled assertion using that leaf. (medium; Opt-in) - [witness-derived-value-review](https://nightshade.dicksonwu.xyz/rules/witness-derived-value-review.md): Review direct witness-derived canonical-send recipients without an exact prior ledger equality binding. (medium; Opt-in) - [exported-shielded-descriptor](https://nightshade.dicksonwu.xyz/rules/exported-shielded-descriptor.md): Canonical shielded coin descriptor fields have an unchanged source route to an exported result. (info; Opt-in) - [permissionless-mint-egress](https://nightshade.dicksonwu.xyz/rules/permissionless-mint-egress.md): Permissionless mint and egress compose around a stored-value boundary without a modeled authorization predicate. (high; Opt-in) - [received-coin-not-validated](https://nightshade.dicksonwu.xyz/rules/received-coin-not-validated.md): Received shielded coin lacks a recorded application constraint on color or value. (low; Opt-in) - [shielded-burn-amount-width](https://nightshade.dicksonwu.xyz/rules/shielded-burn-amount-width.md): An exported amount is forwarded unchanged to a canonical shielded burn whose coin and API amount types are wider. (info; Opt-in) - [shielded-contract-recipient-review](https://nightshade.dicksonwu.xyz/rules/shielded-contract-recipient-review.md): Review canonical shielded sends with a modeled non-self ContractAddress recipient arm. (info; Opt-in) - [signed-effect-input](https://nightshade.dicksonwu.xyz/rules/signed-effect-input.md): Review ordinary state or shielded input coin sources absent from enforced signature message dependencies. (low; Opt-in) - [unbounded-mint](https://nightshade.dicksonwu.xyz/rules/unbounded-mint.md): A variable mint amount has no modeled per-call cap below the native range or public ledger bound. (medium; Opt-in) - [unprotected-value-transfer](https://nightshade.dicksonwu.xyz/rules/unprotected-value-transfer.md): Successful token operations have no required application predicate constraining private caller inputs. (low; Opt-in) - [unshielded-refund-endpoint-review](https://nightshade.dicksonwu.xyz/rules/unshielded-refund-endpoint-review.md): Review a complete local refund-validator endpoint producing a zero remainder send expression. (info; Opt-in) - [zero-amount-complementary-send-review](https://nightshade.dicksonwu.xyz/rules/zero-amount-complementary-send-review.md): Review exact same-color complementary sends with two zero-inclusive amount envelopes. (info; Opt-in) - [zero-amount-unguarded-map-debit-review](https://nightshade.dicksonwu.xyz/rules/zero-amount-unguarded-map-debit-review.md): Review an amount-zero successful numeric Map debit whose exact lookup has unknown prior membership. (info; Opt-in) - [zero-amount-unshielded-send](https://nightshade.dicksonwu.xyz/rules/zero-amount-unshielded-send.md): Review canonical unshielded send amounts with a zero-inclusive successful-history range. (info; Opt-in) - [zero-transfer-retained-list-review](https://nightshade.dicksonwu.xyz/rules/zero-transfer-retained-list-review.md): Review zero-inclusive actual transfers paired with retained List append for the exact user recipient. (info; Opt-in) - [caller-supplied-ledger-equality](https://nightshade.dicksonwu.xyz/rules/caller-supplied-ledger-equality.md): An unchanged caller input must equal preexisting public ledger bytes before a state-changing effect. (medium; Opt-in) - [destructive-list-reset](https://nightshade.dicksonwu.xyz/rules/destructive-list-reset.md): Whole-list reset lacks a recognized same-revision count, empty-list or absent-slot acknowledgment. (low; Opt-in) - [inconsistent-keyed-state-guard](https://nightshade.dicksonwu.xyz/rules/inconsistent-keyed-state-guard.md): Consumer co-membership is checked on only some successful histories of a keyed insert. (info; Opt-in) - [mutually-exclusive-terminal-payout](https://nightshade.dicksonwu.xyz/rules/mutually-exclusive-terminal-payout.md): Terminal payout remains reachable after a mutually exclusive one-time milestone. (high; Opt-in) - [re-initialization](https://nightshade.dicksonwu.xyz/rules/re-initialization.md): Opt-in review of initializer-named entries with a state-changing second invocation. (low; Opt-in) - [resettable-list-nonce](https://nightshade.dicksonwu.xyz/rules/resettable-list-nonce.md): Canonical shielded coin nonce derives solely from a selected ledger List length that another exported entry can reset. (low; Opt-in) - [resettable-memo-nonce-review](https://nightshade.dicksonwu.xyz/rules/resettable-memo-nonce-review.md): Stored recipient List payload and canonical coin nonce both evolve from the same resettable selected List extent. (info; Opt-in) - [shared-module-once-gate](https://nightshade.dicksonwu.xyz/rules/shared-module-once-gate.md): Distinct importing module wrappers expose one canonical false-guard then true-write Boolean gate. (info; Opt-in) - [write-only-ledger](https://nightshade.dicksonwu.xyz/rules/write-only-ledger.md): Ordinary ledger Cell is explicitly written but has no Compact source read in the compilation unit. (info; Opt-in) - [default-recipient-or-owner](https://nightshade.dicksonwu.xyz/rules/default-recipient-or-owner.md): A successful value output or pinned Ownable update uses a known default active address. (medium; Opt-in) - [exact-balance-threshold](https://nightshade.dicksonwu.xyz/rules/exact-balance-threshold.md): A threshold-only assertion uses the exact unshielded balance getter instead of its comparison API. (info; Opt-in) - [field-arithmetic-wraparound](https://nightshade.dicksonwu.xyz/rules/field-arithmetic-wraparound.md): A directly published Field operation on preserved unsigned quantities may wrap without a proved bound. (medium; Opt-in) - [inconsistent-access-control](https://nightshade.dicksonwu.xyz/rules/inconsistent-access-control.md): An exported writer omits the caller-check convention required by a strict majority of its peers. (medium; Opt-in) - [merkle-insert-without-dedupe](https://nightshade.dicksonwu.xyz/rules/merkle-insert-without-dedupe.md): Review sequential bounded Merkle insertion without exact surviving duplicate prevention. (info; Opt-in) - [nullifier-check-without-insert](https://nightshade.dicksonwu.xyz/rules/nullifier-check-without-insert.md): Required collection absence lacks a definite surviving insertion on a state-changing history. (medium; Opt-in) - [publicly-derived-guard-tag](https://nightshade.dicksonwu.xyz/rules/publicly-derived-guard-tag.md): A supplied tag is required equal to a hash derived from preexisting public ledger data and caller-supplied inputs before an effect. (medium; Opt-in) - [unasserted-security-result](https://nightshade.dicksonwu.xyz/rules/unasserted-security-result.md): Review predicate outcomes discarded before effects, persisted, or returned with an effect; security intent unknown. (medium; Opt-in)