# Allowlist bypass via alias or prefix

Allowlist checked on canonical name; alias, doubled prefix, or zero-length encoding reaches the same capability

_Area: Smart contract access control and control flow. Seen in 2 disclosed reports; latest 2026-10-01. Updated 2026-10-24._

## How it works
An access check compares a user-supplied identifier against an allowlist after some normalization step. The check assumes the normalized form is the only way to name the capability. When a second spelling (doubled prefix, alias, zero-length entry) normalizes to an allowed key or collapses a restriction to a no-op, the guard passes while the underlying capability is still reachable. The invariant that breaks: *the checked representation must be the same one the runtime uses to resolve the action.*

## Where it shows up
- Prefix/scheme stripping before lookup (e.g. removing one `node:` before matching a stored `node:test` key) [E1](https://bugbountylibrary.com/r/ghsa%3AGHSA-qhwx-74w5-xhxq.md)
- Allowlists that omit whole families of dangerous entries (process-spawning builtins, `test` family) [E1](https://bugbountylibrary.com/r/ghsa%3AGHSA-qhwx-74w5-xhxq.md)
- Allowed entries whose API accepts exec/spawn arguments (`execArgv`, `--eval`) [E1](https://bugbountylibrary.com/r/ghsa%3AGHSA-qhwx-74w5-xhxq.md)
- Template contexts exposing backing objects with callable no-arg methods (`to_yaml`, `instance_eval`) [E2](https://bugbountylibrary.com/r/h1%3A98259.md)
- Length-derived bitmasks where `length == 0` yields an all-zero mask [E3](https://bugbountylibrary.com/r/c4%3A2023-06-lukso%3AM-07.md)
- Validation that rejects `length > 32` but not `length == 0` [E3](https://bugbountylibrary.com/r/c4%3A2023-06-lukso%3AM-07.md)

## How to review
- Find every place an identifier is normalized (prefix strip, decode, compact) and confirm the allowlist lookup uses the *post-normalization* value the runtime will actually resolve.
- Enumerate the full set of names the runtime accepts, including scheme-only and aliased forms; diff against the allowlist.
- For each allowed entry, ask whether its API can spawn processes, eval, or read hidden fields [E1](https://bugbountylibrary.com/r/ghsa%3AGHSA-qhwx-74w5-xhxq.md)[E2](https://bugbountylibrary.com/r/h1%3A98259.md).
- For length/bitmask checks, test the `0` boundary explicitly: a zero mask makes every AND comparison trivially true [E3](https://bugbountylibrary.com/r/c4%3A2023-06-lukso%3AM-07.md).
- Property to hold: *no input normalizes to an allowed key unless it is exactly that capability, and no restriction compacts to a vacuous check.*

## Variants seen
- Doubled scheme prefix normalizing onto a stored scheme-only key [E1](https://bugbountylibrary.com/r/ghsa%3AGHSA-qhwx-74w5-xhxq.md)
- Dangerous builtin family absent from the deny list, reached via generic passthrough loader [E1](https://bugbountylibrary.com/r/ghsa%3AGHSA-qhwx-74w5-xhxq.md)
- Template Drop exposing arbitrary no-arg methods to user templates [E2](https://bugbountylibrary.com/r/h1%3A98259.md)
- Zero-length allowlist entry producing an all-zero mask [E3](https://bugbountylibrary.com/r/c4%3A2023-06-lukso%3AM-07.md)

## Impact and severity
Sandbox escape to host RCE [E1](https://bugbountylibrary.com/r/ghsa%3AGHSA-qhwx-74w5-xhxq.md), sensitive data disclosure (hashed passwords) [E2](https://bugbountylibrary.com/r/h1%3A98259.md), and write access to nearly any data key on a shared profile [E3](https://bugbountylibrary.com/r/c4%3A2023-06-lukso%3AM-07.md). Severity rises when the bypassed guard protects a shared or host boundary, and when the allowed capability itself accepts exec arguments [E1](https://bugbountylibrary.com/r/ghsa%3AGHSA-qhwx-74w5-xhxq.md).

## Evidence
- E1: https://bugbountylibrary.com/r/ghsa%3AGHSA-qhwx-74w5-xhxq.md
- E2: https://bugbountylibrary.com/r/h1%3A98259.md
- E3: https://bugbountylibrary.com/r/c4%3A2023-06-lukso%3AM-07.md
