Rule
missing-role-bootstrap
An authenticated ShieldedAccessControl instance initializes but has no role-seeding route.
Specimen 17 of 96 · Audit-default ordinary rules
- Severity
- low
- Confidence
- varies
- Maturity
- experimental
- Selection
- Audit default
- Policy intent
- not required
- Release
- v0.1.1
- Engine facts used
resolved-callsmodule-identitiesconstructor-histories
Selection and scope#
Selected by the default audit profile, so an ordinary scan runs it.
./.nightshade/node_modules/.bin/nightshade ./contracts --detectors missing-role-bootstrap
./.nightshade/node_modules/.bin/nightshade detector show missing-role-bootstrapThe 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.
Rule documentation#
From docs/detectors/missing-role-bootstrap.md at v0.1.1.
Availability: default-on; low severity, high confidence. Reports an authenticated ShieldedAccessControl instance that initializes in every successful constructor history but has no entry-reachable route to seed any role. With an empty role tree, guarded grantRole cannot establish the first role holder.
Example and scenario#
import "access/ShieldedAccessControl" prefix SAC_;
constructor(salt: Bytes<32>) { SAC_initialize(salt); }
export circuit grant(role: SAC_RoleIdentifier, account: SAC_AccountIdentifier): [] {
SAC_grantRole(role, account);
}Initialization stores state and salt; it does not insert an initial role holder. The library's documented constructor calls _grantRole separately.
Recommendation#
Seed an initial role holder, usually DEFAULT_ADMIN_ROLE, with _grantRole during construction. Custom seeded roles and deliberate delayed setup are valid alternatives. Review the intended administrator relationships separately.
Evidence and known false positives#
Requires compiler profile compact-0.34.0-zkir2, exact ShieldedAccessControl and Utils source bytes from compact-contracts revision ec1331cd8195694c747d291e8fc8ab6d2914a976, and complete successful constructor histories containing the canonical initialization write. The rule stops at the authenticated guarded grantRole boundary. Any other reachable raw _grantRole call or application reference to that instance's storage withholds the absence claim, even in dead source branches, zero-iteration loops and captured callback bodies. This check walks owned source statements rather than the pruned CFG. The upstream test mock deliberately exposes delayed bootstrap and remains quiet. Modified libraries and namesakes are outside this rule's identity scope.
This rule does not assess seed adequacy, custom libraries, arbitrary access policies, missing initialization, or whether off-chain deployment procedures correctly perform a deliberately exposed setup operation.
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:
// nightshade-disable-next-line missing-role-bootstrap -- Reason this match is intentionalDiagnostics cannot be suppressed, and an unmatched directive for a selected rule makes analysis incomplete. See configuration for fingerprint suppressions and baselines.