Zero-Trust for Unreal Development
Nothing reaches main without verification. Every change, from every contributor, on every type of file, goes through the same gate: a pull request that has been reviewed, validated by CI, and approved. The level of human review scales with the risk of the change (the inspectability of the file and the blast radius of what it affects), not the seniority or discipline of the author.
This post is what I've learned setting that model up inside an Unreal studio: the principle, the threat model, how each layer works, and the places where the model has to make tradeoffs to survive contact with reality.
The Principle
Zero trust is a security mindset that originated in IT networking. The traditional model was a perimeter model: build a strong wall around the network, and trust anything inside it. Once a credential or a device got through the wall, it could move freely. The problem is well-known. Perimeters get breached, credentials get compromised, and "inside" turns out to be a soft, trusting place where one weak point gives access to everything.
Zero trust drops the assumption that location or identity, by themselves, confer trust. The catchphrase is "never trust, always verify". Each request to access a resource is checked on its own merits, every time, regardless of where it came from or who it's from. Trust is granted per-action, not per-session.
The same principle applies cleanly to source control. The main branch is a shared resource that the entire studio and the build pipeline depend on. A broken main isn't a problem for one person, it's a problem for everyone whose work branches from it. So we treat main the way a zero-trust network treats a sensitive resource: verify every change on its own merits, every time, regardless of who authored it or where it came from.
Why the Threats Are Mundane
The model exists because of how Unreal projects actually fail in practice. The threats aren't malicious, and almost none of them involve bad actors. They're the ordinary ways a complex engine, a large repository, and a team working in parallel break things.
A short, non-exhaustive list of what the model protects against:
- A locally working change that fails to cook, package, or run on device.
- An opaque binary asset (Blueprint, material, Niagara system) that references something that no longer exists, that nobody notices until runtime.
- A change that works in PIE but causes a crash, hitch, or memory spike in a packaged build.
- A change that's technically correct but conflicts architecturally with work already in flight on another branch.
- A change made by someone working in good faith but outside their primary domain, who didn't realize a downstream system depended on the behavior they modified.
- A change that compiles, runs, and looks fine but quietly regresses performance, bundle size, or memory footprint.
- An incomplete or experimental change that wasn't intended to ship, accidentally landing because there was no gate to catch it.
The model doesn't assume people are careless. It assumes people are human, the engine is large, and the interactions between systems aren't fully knowable from a single contributor's point of view. The review step exists to bring more eyes and more context to bear before a change becomes everyone's problem. And "everyone" here ultimately means players, not just the team.
Rules That Fall Out of the Principle
In practice the principle becomes a handful of concrete rules:
Direct pushes to main are blocked for everyone. Producers, designers, artists, engineers, audio, QA, technical directors. No role has push access to main. The only path in is a PR. This is the single most important property of the model: it cannot be bypassed by seniority, urgency, or convenience.
Every PR requires review. Self-merging is not the workflow. A second set of eyes is in the loop before the change lands.
CI must pass. Automated checks run on every PR. If they fail, the PR isn't ready to merge, regardless of how trivial the change looks. The answer is to address the failure or have a conversation about why the check is wrong. The answer is not to merge anyway.
Risk-tiered human review. The reviewer requirement varies by what's being changed. Some files can be reviewed by any peer. Some require an engineer in the chain because the file format makes review impossible without engine-specific tooling, or because the blast radius requires an engineering mental model to assess.
Past trust doesn't carry forward. A senior engineer's PR goes through the same gate as a junior's. Yesterday's good commits don't grant a free pass on today's. The verification is per-change, not per-person.
Each rule corresponds to a class of failure the model is designed to catch. Removing any one of them re-introduces the failure it was protecting against.
Risk Tiering
The reviewer requirement on a given change is driven by two factors. Sometimes only one applies, sometimes both apply at once.
Factor One: Inspectability of the File
Some files are diff-readable, some aren't.
Text files (C++, headers, config, build scripts, shaders, JSON, markdown). Every character that changed is visible in the PR diff. Reviewers can (and routinely do) go deep on intent, tradeoffs, architecture, maintainability, robustness, performance implications. The point isn't that text review is light. It's that the file format doesn't get in the way of doing it.
Opaque binary assets (Blueprints, materials, Niagara systems, animation blueprints, packaged content). The diff tells the reviewer that a file changed, but not what changed inside it. To review the change meaningfully, the reviewer may need to check out the branch, open the asset in the editor, and navigate it to verify the change is safe (no broken references, no logic regressions, no performance impact, no cooked-output surprises). The opaque format affects the mechanics of how review is performed.
Factor Two: Downstream Blast Radius
Some changes are fully readable in the diff but still require engineering review because understanding what they affect needs a mental model that lives mostly in engineering. A header included by hundreds of files. A .uproject or .ini setting that influences how content cooks. A build-script tweak that quietly changes what gets packaged. A change to a foundational utility that other systems depend on. A shader macro toggle, a compiler flag, a third-party plugin update.
These changes might be ten lines of text and entirely diff-readable, but the question "is this safe?" only resolves if the reviewer holds the model of what depends on what: what cooks differently, what regresses performance, what triggers a full rebuild, what affects shipping, what fails on device but not in editor. Engineers tend to hold that model, so they're the required reviewers for these changes even when the file format would otherwise let anyone read the diff.
How the Factors Combine
A single change can invoke both factors at once. A Blueprint that gates a major gameplay system is opaque and has wide downstream blast radius, and engineering review is required on both counts.
The risk tiering follows directly. Changes that are both text-readable and locally scoped can be reviewed by peers with the relevant domain knowledge, regardless of discipline. Changes whose implications require an engineering mental model to assess require an engineer in the review chain.
The logic applies symmetrically. An engineer modifying a Blueprint goes through exactly the same gate as a designer modifying a Blueprint. An engineer modifying a high-blast-radius config file goes through the same gate as a producer modifying it. The gate is determined by what's being changed and what it affects, not by who's changing it.
The Automated Layer
CI is the part of the model that doesn't sleep. Where human reviewers catch intent and architecture, CI catches the mechanical failures: compilation, packaging, shader compilation, project validation, lint, format. The principle is the same: verify each change, every time, with no exceptions based on authorship.
CI is also where the model handles the parts of binary asset review that can be automated. Asset validation, reference checks, redirector hygiene. The intent over time is to push more of the binary-asset review burden into CI, so that human review can focus on intent and design rather than mechanical correctness.
CI verifies the merge result, not just the source branch in isolation. What would main look like if this PR landed right now? That post-merge state is what gets checked. A PR that's green on its own but would break main when combined with other recently-landed work is caught at that check, not by the next person to pull. This is zero-trust one layer deeper. main doesn't trust the PR branch any more than it trusts the author, and the verification covers the change and its interaction with everything already in main.
Identity and Trust
This is the part of the model that's easiest to erode.
The default path is the same for everyone. The Technical Director's PR is reviewed. The Studio Director's PR is reviewed. A producer's documentation change is reviewed. The most senior engineer's hotfix is reviewed, possibly fast, but reviewed. There's no "trusted committer" status that grants free passage to main on the basis of who the author is.
Tech leadership do hold the permission to bypass specific merge policies (the individual required-reviewer rule, for example) in cases where the model has broken down and a change genuinely can't wait. This is a failsafe, not a privilege, and the distinction matters. The bypass exists so the studio isn't held hostage to its own process during a real emergency: a broken build at the wrong moment, a critical fix that the only available reviewer can't get to, a vendor handover with a hard deadline. It does not exist as a faster lane for favored individuals.
The model places a prospective control on the failsafe itself. When a tech leader uses a bypass, another tech leader is expected to be in the loop, observing the change, the rationale, and the action, except in genuinely extraordinary circumstances where no second leader can be reached in time.
The reason this doesn't undermine zero trust is that the bypass is itself a verification surface. Bypass usage is logged and visible. Tech leadership scrutinize each other's use of it, so when a bypass shows up, "why was this necessary?" gets asked seriously, and the answer has to hold up. The accountability hasn't disappeared. It has shifted from per-PR review to post-hoc scrutiny of the bypass itself.
For everyone else, the practical implication is straightforward: there's no bypass path, and the right answer is never to find someone with the permission and ask them to exercise it as a favor. If a change is genuinely urgent, the model accommodates it by accelerating the review, not by skipping it. A reviewer drops what they're doing, looks at the change quickly, and approves or rejects. The gate stays in place. Only the latency through it changes.
Working Effectively Within the Model
A few practices make the model feel like infrastructure rather than friction:
- Work in one context at a time. A clean working tree is half the battle for a clean PR. Changes that picked up half-finished work on three other things during the same session are three changes wearing a single PR as a disguise.
- Keep PRs scoped. The unit of change should match the unit of review.
- Land work in stages. A three-week piece of work doesn't need to land as one PR. Scaffolding, then systems, then polish.
- Write the PR description for the reviewer. What the change does, why, and what to look for. The less obvious the change is from the diff, the more the description has to explain.
- Request the right reviewer. The reviewer pool isn't "anyone with merge rights", it's whoever can meaningfully verify the specific change in front of them.
- Respond to review, don't fight it. Review is collaborative. The PR is better at the end than at the start.
- Don't sit on review requests. If review takes days, authors start batching changes into larger PRs to avoid the latency, which is the same scoping failure arriving from the other direction.
The Tradeoff This Represents
Unreal lets every discipline do an extraordinary range of things that, in earlier engines, would have required an engineer to implement on their behalf. Gameplay logic, VFX behavior, material logic, animation flow, UI behavior, data-driven systems. All of it can be authored directly in the engine, often without writing a line of C++. That accessibility is a fundamental capability of the engine, and it's why studios can move at the pace they do.
The cost of that accessibility is that the tools every discipline uses now reach the same runtime as engineering code. A Blueprint can crash the game. A material can tank frame rate. A Niagara system can leak memory. The same reach that lets a designer author gameplay also means their work can break the build in ways that used to require an engineer to even attempt.
The review model is the cost of that reach. It isn't a tax on a specific discipline. It's the price the studio pays, collectively, for what the engine can do. The alternative to broad capability with verification is not broad capability without verification, it's narrow capability. We have chosen broad capability, deliberately, and the review model is the other half of that choice.
This framing matters because the model can feel adversarial when looked at in isolation. It isn't. It exists because the capability exists, and the two are inseparable.
In One Sentence
We don't trust changes, we verify them. Every one, regardless of author, with verification scaling to risk and the rare failsafe itself subject to review, because what comes after main isn't just the next build. It's a live-service product, where the cost of a subtle, far-reaching failure is paid in player experience and the revenue tied to it.