EVERYONE@ is reserved in both directions (L4 auth / ACL)

The subject-token space is opaque bytes with exactly one spelling the evaluators know: kEveryoneSubject"EVERYONE@". An ACE carrying it applies to every resolved subject, which is how a vertex is opened to all comers for one right without enumerating anybody (ADR-0020).

The half that is easy to miss is the other direction, and it is the reason this gets its own example.

What to notice

  • The wire has ONE spelling for a subject token. The ACE’s subject and the resolver’s output are the same opaque bytes — the acl/acl-aces conformance vector sends peer-a and the wildcard as the same opaque VALUE. So a principal that could BE those bytes would be indistinguishable from the wildcard ACE.

  • The core refuses the resolver’s OUTPUT, rather than trusting every integrator to blacklist the string. A caller that resolves to EVERYONE@ is denied at every gate (#908). The deployments at risk are exactly the ones whose resolver passes a caller-supplied identity through — usernames, certificate CNs, peer names — which is the most ordinary resolver there is.

  • It is refused on a BARE vertex too, and that is the discriminating case. The refusal happens before the open-by-default rule, so it is not “the wildcard subject matches no ACE”; it is “this is not a principal at all”. The example checks the bare vertex with an ordinary caller as the ablation, so the deny is not just a vertex that happened to be closed.

  • is_reserved_subject() is public for a reason. A resolver can refuse the token at its own door as well; the core checks it in the two places a subject reaches an ACE comparison.

  • The wildcard grant is still one bit. EVERYONE@ with READ is not EVERYONE@ with access — see access_mask is a bitfield.

  • OWNER@ is not a special subject and never was. ADR-0020 named it once, no evaluator ever special-cased it, so an OWNER@ ACE matched nobody while still closing the vertex it was written to delegate. The erratum (#1033) withdraws the name rather than reserving it: with no document telling an operator to write that ACE, there is nothing for an impersonated OWNER@ principal to match either. The example asserts it is an ordinary token.

  • Nothing here is conditional — the target builds and runs under every CI leg.

Source

  1/*
  2 * SPDX-License-Identifier: Apache-2.0
  3 * SPDX-FileCopyrightText: Copyright 2026 avatarsd LLC
  4 */
  5
  6/**
  7 * @file
  8 * @brief ONE CONCEPT — `EVERYONE@` is the one wildcard subject, and it is RESERVED both ways.
  9 *
 10 * The subject-token space is opaque bytes, with exactly one spelling the evaluators know:
 11 * `tr::graph::kEveryoneSubject` — `"EVERYONE@"`. An ACE carrying it applies to every resolved
 12 * subject, which is how a vertex is opened to all comers for one right without enumerating
 13 * anybody (ADR-0020).
 14 *
 15 * The half that is easy to miss is the OTHER direction. The wire has ONE spelling for a subject
 16 * token: the ACE's subject and the resolver's output are the same opaque bytes. So a principal
 17 * that could BE those bytes would be indistinguishable from the wildcard — and the deployments
 18 * at risk are exactly the ones whose resolver passes a caller-supplied identity through
 19 * (usernames, certificate CNs, peer names). The core therefore refuses to let a RESOLVED subject
 20 * spell it (#908): that caller is denied at every gate, on a guarded vertex and on a bare one
 21 * alike, rather than every integrator being left to know to blacklist the string.
 22 *
 23 * Note what the bare-vertex case means: the refusal happens BEFORE the open-by-default rule, so
 24 * it is not "the wildcard subject matches no ACE" — it is "this is not a principal at all".
 25 *
 26 * `OWNER@` is deliberately absent. ADR-0020 named it once, no evaluator ever special-cased it,
 27 * and so an `OWNER@` ACE matched nobody while still CLOSING the vertex it was written to
 28 * delegate — the erratum (#1033) withdraws the name rather than reserving it.
 29 *
 30 * Runs under ctest as `example_acl_everyone_reserved`; returns non-zero on any failed check.
 31 */
 32
 33#include <cstdio>
 34#include <cstring>
 35#include <span>
 36#include <string_view>
 37#include <vector>
 38
 39#include "libtracer/graph.hpp"
 40#include "libtracer/mem_heap.hpp"
 41#include "libtracer/security_acl.hpp"
 42
 43namespace {
 44
 45using tr::graph::ace_t;
 46using tr::graph::acl_right_t;
 47using tr::graph::graph_t;
 48using tr::graph::kEveryoneSubject;
 49using tr::graph::path_t;
 50using tr::graph::role_t;
 51using tr::graph::status_t;
 52using tr::graph::subject_token_t;
 53using tr::graph::vertex_handle_t;
 54
 55/** @brief Report expectation @p what and record a failure on @p ok. */
 56void check(bool& ok, bool cond, const char* what) {
 57    std::printf("  [%s] %s\n", cond ? "ok" : "FAIL", what);
 58    ok = ok && cond;
 59}
 60
 61/** @brief @p s as opaque subject-token bytes. */
 62std::vector<std::byte> as_bytes(std::string_view s) {
 63    std::vector<std::byte> out(s.size());
 64    std::memcpy(out.data(), s.data(), s.size());
 65    return out;
 66}
 67
 68/**
 69 * @brief The pass-through resolver — the shape #908 exists for.
 70 *
 71 * It hands back whatever the caller context said, which is what an integrator writes when the
 72 * transport already authenticated a name. It is also exactly what would let a peer that managed
 73 * to be called `EVERYONE@` resolve to the wildcard, so the core refuses the OUTPUT rather than
 74 * trusting every such resolver to blacklist the token itself.
 75 */
 76std::expected<subject_token_t, tr::wire::err_t> caller_is_subject(void*, std::string_view caller) {
 77    return as_bytes(caller);
 78}
 79
 80/** @brief A one-byte VALUE. */
 81tr::view::view_t some_value() {
 82    const std::byte one[1] = {std::byte{0x01}};
 83    return *tr::view::over_bytes(one);
 84}
 85
 86/** @brief True iff @p r was refused by an ACL gate. */
 87template <class T>
 88bool denied(const tr::graph::result_t<T>& r) {
 89    return !r.has_value() && r.error() == status_t::PERMISSION_DENIED;
 90}
 91
 92}  // namespace
 93
 94int main() {
 95    bool ok = true;
 96    graph_t g;
 97    g.configure_subject_resolver(caller_is_subject, nullptr);
 98    const vertex_handle_t guarded = g.register_vertex(path_t("/guarded"), role_t::STORED_VALUE);
 99    const vertex_handle_t bare = g.register_vertex(path_t("/bare"), role_t::STORED_VALUE);
100    (void)g.write(guarded, some_value());  // trusted local seeds, so a refused READ is the
101    (void)g.write(bare, some_value());     // only way either read below can fail
102
103    // The wildcard ACE: READ for everybody, and nothing else for anybody.
104    const ace_t wildcard[] = {{.subject = as_bytes(kEveryoneSubject),
105                               .access_mask = static_cast<std::uint32_t>(acl_right_t::READ)}};
106    (void)g.write(path_t("/guarded:acl"), *tr::view::over_bytes(tr::graph::encode_acl(wildcard)));
107
108    // Direction 1 — as an ACE subject, it matches every principal, named or not.
109    check(ok, g.read(guarded, "alice").has_value(), "the wildcard ACE grants READ to alice");
110    check(ok, g.read(guarded, "a-peer-nobody-enumerated").has_value(), "…and to a stranger");
111    check(ok, denied(g.write(guarded, some_value(), "alice")),
112          "…and it is still ONE bit: the wildcard granted READ, not access");
113
114    // Direction 2 — as a RESOLVED subject, it is not a principal at all.
115    check(ok, denied(g.read(guarded, kEveryoneSubject)),
116          "a caller resolving to EVERYONE@ is denied on the guarded vertex…");
117    check(ok, denied(g.read(bare, kEveryoneSubject)),
118          "…and on the BARE one too, which open-by-default would otherwise have allowed");
119    check(ok, g.read(bare, "alice").has_value(),
120          "the ablation: the bare vertex really is open to an ordinary caller");
121
122    // The same predicate, published so a resolver can refuse the token at its own door as well.
123    check(ok, tr::graph::is_reserved_subject(as_bytes(kEveryoneSubject)),
124          "is_reserved_subject() is the check, and it is public for that reason");
125    check(ok, !tr::graph::is_reserved_subject(as_bytes("OWNER@")),
126          "OWNER@ is NOT reserved and NOT special — it is an ordinary opaque token (#1033)");
127
128    std::printf("one reserved subject, %zu bytes: \"%.*s\"\n", kEveryoneSubject.size(),
129                static_cast<int>(kEveryoneSubject.size()), kEveryoneSubject.data());
130    return ok ? 0 : 1;
131}

See also: security-acl module · protocol TLVs · the subject resolver · open by default.