---
title: Cedar Policy Language Overview
url: https://www.emergentmind.com/topics/cedar-policy-language
type: topic
---

# Cedar Policy Language Overview

Cedar is a new authorization policy language designed to be ergonomic, fast, safe, and analyzable, with the explicit aim of externalizing authorization logic from application code into a dedicated DSL [2403.04651]. Its design supports common authorization use-cases by combining role-based, attribute-based, and relation-based access control in a compact policy form, while balancing optional static validation, deterministic deny-overrides evaluation, a sound and complete SMT encoding, a mechanized Lean model, and a high-performance Rust implementation [2403.04651][2407.01688].

## 1. Design objectives and overall architecture

Cedar was created to meet four potentially competing objectives: expressiveness, safety, analyzability, and performance [2407.01688]. In the extended presentation of the language, these appear as ergonomics, safety, performance, and analyzability: a small, intuitive syntax for RBAC, ABAC, and ReBAC; a default-deny, deterministic evaluation strategy with an optional static validator; policy indexing and linear (or near-linear) evaluation times; and a sound and complete translation to SMT that supports precise queries such as equivalence and change-impact [2403.04651].

These goals determine Cedar’s overall architecture. All policies are first statically validated against a user-supplied schema, which ensures type safety of record lookups and extension-function calls at run time [2407.01688]. Policies that pass validation are compiled into two paths: a Lean “definitional” evaluator and authorizer used as the formal specification and test oracle, and a high-performance Rust evaluator used in production [2407.01688]. In parallel, a symbolic compiler translates policies to decidable SMT formulas, enabling automated reasoning for tasks such as policy-equivalence checking [2407.01688].

A central architectural feature is policy indexing, also called slicing. The language and engine are organized so that only the small subset of policies relevant to a given request need be evaluated, and sound slicing is proved in the mechanized model [2407.01688]. This arrangement is not incidental: the policy structure is designed so that access requests can be decided quickly, while still permitting formal analysis and machine-checked proofs [2403.04651].

## 2. Policy structure, concrete syntax, and expressive fragment

A Cedar policy set is a collection of rules. Each rule has three parts—effect, scope, and condition—written in a compact concrete syntax [2403.04651]. The effect is `permit` or `forbid`; the scope constrains `principal`, `action`, and `resource`; and conditions appear in `when` or `unless` blocks [2403.04651].

A simplified grammar for the core of Cedar is given as follows [2407.01688]:

$$
\begin{aligned}
PolicySet      &::= \{\,Policy\;\}^{*} \\
Policy         &::= Effect\;\scopedExpr\;\bigl[\keyword{when}\;\!CondExpr\bigr]\;\semicolon \\
Effect         &::= \keyword{permit} \mid \keyword{forbid} \\
\scopedExpr    &::= \texttt{(}\;principal\;,\;ActionExpr\;,\;ResourceExpr\;\texttt{)} \\
CondExpr       &::= BoolLit
                \mid Ident
                \mid Expr\;\keyword{and}\;\Expr
                \mid Expr\;\keyword{or}\;\Expr
                \mid \keyword{not}\;\Expr \\
               &\quad\mid Expr\;op\;Expr
                \mid Expr\;\keyword{in}\;\Expr
                \mid Expr\;\keyword{has}\;\Ident\mid\cdots
\end{aligned}
$$

The extended version presents a related grammar in which scope clauses may use exact match or entity-hierarchy membership, for example `principal [in | ==] E_\pi`, `action in [A_1,\dots,A_k]`, and `resource [in | ==] E_r`; expressions include values, variables, field projection, membership, equality, conjunction, and further expression forms [2403.04651].

The expressive fragment is deliberately hybrid. Cedar supports both RBAC-style and ABAC-style policies, together with relation-based patterns, including role membership, attribute tests, wildcards, set and string operations, record projection, and custom extension functions [2407.01688]. The scope restricts principal, action, and resource by exact match or by entity-hierarchy membership, while conditions inspect attributes or group membership [2403.04651]. Extension functions include operators such as `like`, `length`, and IP range checks [2407.01688].

This design is meant to preserve readable policies while combining several access-control paradigms in a single language. A common misconception is to view Cedar as only an RBAC language; the formal descriptions instead present it as a language whose simple syntax “naturally leverages concepts from role-based, attribute-based, and relation-based access control models” [2403.04651].

## 3. Static typing, schemas, and validation

Cedar offers an optional schema and validator to catch run-time errors at authoring time [2403.04651]. The schema has two parts: an entity schema \(M\), which gives for each entity type its record type and allowed parent types, and an action schema \(S\), which gives for each action the allowed principal types, resource types, and context record type [2403.04651]. In one formulation, Cedar’s core types include `bool`, `string`, `num`, `set<\tau>`, `record\{f_1:\tau_1,\dots,f_n:\tau_n\}`, and `entity_T` for each principal, resource, or action type label \(T\) [2407.01688].

The basic typing judgment is

$$
\Gamma \vdash e : \tau
$$

with selected rules such as variable lookup, Boolean literals, equality, set membership, and `has`-tests [2407.01688]. The extended presentation refines this into a judgment of the form

$$
\alpha;\Gamma\vdash e:\tau;\varepsilon
$$

where singleton types \(True,False\), optional versus required attributes, and capabilities \(\alpha\) are used to track which optional attributes have been proved present before use [2403.04651]. For example, `e has f` can establish a capability, and field projection `e.f` is admitted when that capability has been established [2403.04651].

Validation proceeds by converting a rule \(c\) to an expression \(e={\sf toexp}(c)\), instantiating each action environment permitted by the action schema, and checking that the resulting expression has Boolean type in a small, decidable type system [2403.04651]. Because the same rule is checked in each environment \(\Gamma\), the validator is described as precise, with few false alarms, and linear in policy size times the number of actions [2403.04651].

The safety objective is stated strongly. Cedar is intended to guarantee that well-typed policies never “go wrong” at runtime: no record-field missing, no type errors in comparisons, and no infinite recursion in validation [2407.01688]. Ill-typed policies can be rejected statically by a validator, so that at runtime every policy that survives validation can be evaluated without dynamic type checks [2407.01688]. In the proved metatheory, validation soundness is formulated as: if a policy passes schema-validation, evaluating it can never raise a type error [2407.01688].

## 4. Operational semantics, authorizer behavior, and SMT analysis

Cedar is given both concrete evaluation semantics and a symbolic denotational account. For the operational semantics of one policy, the judgment

$$
\langle P,\,r,\,\mathcal{E}\rangle\Downarrow\mathit{sat}
$$

means that policy \(P\), under request \(r=(principal,action,resource)\) and entity store \(\mathcal{E}\), evaluates to satisfied [2407.01688]. In the extended version, expression evaluation is a small-step judgment \(\mu,\sigma\vdash e\to e'\), where \(\mu\) is the entity store and \(\sigma\) is the request environment mapping `principal`, `action`, `resource`, and `context` to values [2403.04651].

Once each policy has been evaluated, the authorizer collects the satisfied `permit` and `forbid` policies and computes the final decision as follows [2407.01688]:

$$
\mathit{decision} =
\begin{cases}
\mathit{Deny} & \text{if }\mathit{Forbids}\neq\emptyset\text{ or }\mathit{Permits}=\emptyset,\\
\mathit{Allow} & \text{otherwise.}
\end{cases}
$$

This is the core deny-overrides rule: forbid-trumps-permit and default-deny [2407.01688]. The extended version states the same behavior as a full authorizer equation in which authorization is computed from the sliced policy set, then returns `Allow` iff the forbid set is empty and the permit set is non-empty [2403.04651].

Slicing is semantically integrated. The cross-product of the ancestors of \(\sigma(\mathit{principal})\) and \(\sigma(\mathit{resource})\) is used to index only those policies with matching scope, so evaluation is linear in the slice rather than in the entire policy set [2403.04651]. The mechanized model proves sound slicing: the indexed slice yields the same decision as the full set [2407.01688].

For analyzability, Cedar policies are translated to SMT-LIB-style formulas. The symbolic compiler guarantees

$$
\langle P,r,\mathcal{E}\rangle\Downarrow\mathit{sat}
\quad\Longleftrightarrow\quad
\mathit{SMT}\models\phi_P(r,\mathcal{E})
$$

and the encoding is described as sound and complete and hence decidable [2407.01688]. The extended exposition explains that each Cedar type is mapped to an SMT sort, records become SMT datatypes with one field per attribute, optional fields become `Option` types, and the entity store and request become uninterpreted SMT constants and functions [2403.04651]. Because Cedar policies only mention a finite “footprint” of entity constants, grounded well-formedness constraints are added only for those entities, rather than general quantified axioms, which keeps the encoding decidable [2403.04651].

The resulting analyses include equivalence, change-impact, subsumption, redundancy, conflict detection, and coverage [2403.04651][2407.01688]. The implementation ships with a command-line tool, `cedar analyze`, and a gRPC API for these analyses [2403.04651].

## 5. Mechanized metatheory and verification-guided development

Cedar is formalized in Lean 4. The evaluator, authorizer, validator, and slicer are written as total, terminating Lean 4 functions over algebraic datatypes, and all definitions are proven to terminate by structural recursion [2407.01688]. The implementation strategy is described as verification-guided development: write an executable model of the system and mechanically prove properties about the model; write production code and use differential random testing to check that the production code matches the model; and use property-based testing to check properties of unmodeled parts of the production code [2407.01688].

The main theorems proved in Lean include forbid-trumps-permit, default-deny, explicit-allow, order-independence, sound slicing, validation soundness, and termination [2407.01688]. For example, forbid-trumps-permit is stated as

```text
theorem forbid_trumps_permit
  (req : Request) (ents : Entities) (pols : Policies) :
  (∃ P, P ∈ pols ∧ P.eff = forbid ∧ satisfied P req ents) →
  (isAuthorized req ents pols).decision = deny
```

and the extended version highlights the corresponding results as default-deny, forbid-trumps-permit, explicit-allow, sound slicing, and validation soundness [2403.04651].

The testing regime is unusually explicit. The Lean model is compiled to an executable oracle, and a fast Rust production engine is checked against it using cargo-fuzz and libFuzzer [2407.01688]. The system generates millions of random triples \((\text{policy set},\mathcal{E},r)\) each day and checks equality between the Rust engine and the Lean model [2407.01688]. QuickCheck-style testing is then applied to the parser/pretty-printer, JSON-schema parser, Rust-only APIs such as template linking and JSON output, and the property that type-checked policies never produce dynamic errors [2407.01688].

This process uncovered subtle defects. Lean proofs found and fixed 4 bugs in Cedar’s policy validator, and DRT and PBT uncovered 21 production bugs in policy evaluation, validation, parsing, formatting, and extension-function handling [2407.01688]. The reported examples include inconsistent IPv4/IPv6 parsing between Rust and Lean, pretty-printer comment loss, raw-string and `like` parsing errors, and validator mis-typing of `has` expressions [2407.01688].

## 6. Performance characteristics and policy idioms

Cedar ships as a Rust-based authorizer and validator, built for single-digit-microsecond decision times, together with a Lean 4 reference specification and validator used to fuzz-test the Rust code for divergences [2403.04651]. In the performance comparison reported in the extended paper, Cedar was evaluated against OpenFGA and OPA/Rego on three example applications—`gdrive`, `github`, and `TinyTodo`—using 100,000 random authorizations on growing data sets [2403.04651]. The median and p99 figures reported for Cedar are \(4.0\mu s\) and \(9.8\mu s\) on `gdrive`, \(11.2\mu s\) and \(18.5\mu s\) on `github`, and \(5.3\mu s\) and \(12.1\mu s\) on `TinyTodo`; the paper states that Cedar is on average 28× faster than OpenFGA and 43× faster than Rego, and that its running time grows only linearly with policy slice size [2403.04651].

The language is illustrated with the `TinyTodo` example, which mixes ABAC and RBAC [2407.01688]:

```text
// Policy 1: ABAC – owners can do anything on their list
permit(principal, action, resource)
  when { resource.has owner
          && resource.owner == principal };

// Policy 2: Readers/Editors can read
permit(
  principal, action == Action::"GetList", resource)
  when { principal in resource.readers
          || principal in resource.editors };

// Policy 3: RBAC – interns forbidden from creating lists
forbid(
  principal in Team::"interns",
   action == Action::"CreateList",
   resource == Application::"TinyTodo" );
```

At runtime, the authorizer slices the policy set to those policies whose scope overlaps the current request, evaluates each condition in Rust, and applies forbid-trumps, default-deny, and explicit-allow to reach a final `Allow` or `Deny` decision [2407.01688].

Several common patterns are explicitly identified. Role-based access is written using a built-in or user-defined `Role::"name"` entity together with `principal in Role::"name"`; attribute-based access uses `resource has f` and equality or inequality on numbers, strings, and dates; delegation can be represented by an attribute such as `delegatees`; and set operations appear in approvals such as `principal in resource.approvers` together with negation [2407.01688]. Cedar also supports policy sets and policy templates; templates can be parameterized by schema values and instantiated multiple times, and large collections rely on slicing to achieve sub-linear evaluation cost in the number of total policies [2407.01688].

## 7. Subsequent research uses and extensions

Later work has treated Cedar not only as a language for application authorization, but also as a target formalism for other security workflows. In "Autoformalization of Agent Instructions into Policy-as-Code" [2606.26649], an LLM-based generator-critic loop translates agent prompts, MCP tool descriptions, and natural-language policy documents into formally verified policies written in the Cedar Policy Language. That system uses the AWS Cedar Policy Engine, emits a Cedar schema from tool JSON schemas, invokes the Cedar CLI as a hard critic, and iterates until all rules pass both hard and soft critics; the resulting policy sets are described as deterministically verified, with enforcement coverage \(55\text{–}100\%\) on MedAgentBench and higher coverage than hand-coded symbolic enforcement in prior work [2606.26649]. This suggests that Cedar’s combination of simple syntax, static typing, and formal semantics makes it suitable as a policy-as-code target beyond its original authorization setting.

In "Automatically Tightening Access Control Policies with Restricter" [2601.14582], Cedar serves as the substrate for automatic least-privilege refinement. Restricter leverages Cedar’s default-deny, deny-overrides semantics, its type system, and its symbolic SMT encoding to tighten overly permissive permit rules with respect to access logs [2601.14582]. The system works by incremental strengthening through SyGuS, using a finite, type-safe set of candidate predicates generated from the Cedar schema and environment [2601.14582]. Across two case studies, the reported results are that Restricter successfully tightened all 5 loosened rules in the classroom-management setting; in the conference-management setting it recovered the ideal tightening in 2 of 5 cases, while the remaining 3 cases removed at least \(80\%\) of over-privileges while preserving at least \(95\%\) of intended but unlogged privileges; overall, 6 of 8 target rules were tightened to the “ideal” form, and all tightened rules removed more than \(70\%\) of over-privilege on average [2601.14582].

Taken together, these later works reinforce a specific picture of Cedar already present in the 2024 papers: a policy language whose syntax is compact, whose semantics are formalized, whose validator and SMT translation are mechanized, and whose implementation supports both efficient enforcement and external reasoning tasks [2403.04651][2407.01688]. A plausible implication is that Cedar’s distinctive contribution lies less in any single access-control paradigm than in the balanced co-design of language fragment, validator, semantics, proof infrastructure, and production engine.

Source: https://www.emergentmind.com/topics/cedar-policy-language