Inspiration
Vernice and I came into this hackathon with experience from building different types of projects, from full stack applications and workflow automation for data platform, to AI projects. Through these different projects, we learned that we kept encountering the same trade-off: software becomes useful by receiving access to APIs, credentials, packages and external services, but that access is often much broader and longer-lived than the task actually requires.
Along with that, Vernice and I recently took a module on Ethical Hacking. The module taught us to examine systems from an attacker’s perspective: and to look for weak trust assumptions, exposed credentials, overly broad permissions and paths that allow a small vulnerability to become a much larger compromise.
We also realised this became especially relevant as we started working with AI Agents more recently. Because unlike traditional applications or AI in general in the past, this Agent is now able to read files, generate code, install dependencies and do everything without you even touching it. This just means that the flexibility and use of it powerful, but it also means that a mistake, malicious intentions, prompt injection can act using whatever authority the Runtime already possesses.
Once we saw the problem statement/task for this hackathon we knew what we wanted to do -- what middleware we wanted to build.
Afterwards, when we inspected the starter platform, two implementation details immediately stood out: the disposable Agent Runtime received the real ModelArk API key and ran with a routable Docker network. Although the Runtime was contained in a disposable container, model-authored code still possessed both a valuable credential and a general path to the Internet.
At the same time, our previous software projects taught us that security cannot simply disable everything useful. The Agent should still be able to write code, use its persistent workspace, call a model and reach the approved development services required for its task.
This is how we built Warden Officer. (The Middleware of this project)
We imagined Warden as a checkpoint officer positioned between an Agent and external infrastructure. Instead of permanently trusting the Agent, it asks:
- Who is making this request?
- Which Run does it belong to?
- Where is it trying to connect?
- Was that destination delegated?
- Is the grant still valid and within budget?
- Can its access be revoked immediately if someth
Essentially, our goal was to apply what we had learnt from both software development and Ethical Hacking: preserve the freedom that makes Agents useful, while replacing ambient trust with authority that is temporary, least-privilege, observable and revocable.
What it does
Warden Officer is a capability-scoped security middleware for AI Agent Runtimes.
When an Agent Run begins, Warden creates a short-lived wgt_ grant containing the Run's permitted model access, network destinations, budgets and expiry. The disposable Runtime receives this grant instead of the real provider credential.
All external access must pass through a trusted, dual-homed Warden broker:
- Model requests are limited to approved inference methods and paths.
- The real ModelArk key is injected only inside the trusted broker.
- Generic HTTPS connections are restricted using exact hostname and port allowlists.
- Direct Runtime Internet access is blocked by an internal Docker network.
- Model-call, token and wall-clock usage are tracked for every Run.
- Operators can check whether a destination would be allowed without creating a connection.
- Active grants can be revoked, closing broker access and cancelling the matching Runtime.
- Grant lifecycle, model, network, denial and recovery events are recorded in a correlated, redacted trace.
Warden provides several delegation profiles:
- Model only — permits inference and nothing else.
- Model + GitHub — permits inference and selected GitHub destinations.
- Node development — adds GitHub and the npm registry for development tasks.
- Fully offline — delegates no external access.
The selected profile applies to the next Run. Already-issued authority cannot be silently widened while a Run is active.
How we built it
We preserved the starter platform's existing React frontend, Fastify control plane, AgentService, persistent workspaces and ContainerCodexRunner as instructed.
Warden is integrated as a TypeScript WardenRunner decorator around the existing AgentRunner interface. Before execution, it mints a run-scoped grant and passes only that grant into the Runtime. When execution finishes, the grant is automatically closed.
The broker runs in a dedicated Docker container connected to two networks:
- An internal network shared with the untrusted Runtime, with no direct Internet route.
- An egress network used only by the broker to reach ModelArk and explicitly delegated destinations.
We separated external access into two enforcement planes.
The model plane terminates HTTP at the broker. This allows Warden to validate methods and paths, inject the provider credential, meter usage and redact evidence.
The network plane uses an HTTP CONNECT proxy. Warden enforces the hostname, port, DNS result and resolved address without claiming to inspect the encrypted contents of the connection.
The React Warden rail displays:
- The selected delegation profile.
- Grant status and fingerprint.
- Grant expiry.
- Model-call and token usage.
- Allowed destinations.
- Denied requests and policy reasons.
- Correlated model, network and lifecycle events.
- Revocation and recovery evidence.
The backend stores Agent metadata and a redacted JSONL trace archive so completed Runs remain understandable after execution.
We verified the implementation using Vitest, deterministic security fixtures, real Docker-topology integration tests, GitHub Actions and complete-history secret scanning.
Challenges we ran into
Since this was our first time building a full middleware, our first challenge was understanding where Warden should sit within the existing Agent system. We had to trace how a task moved from the frontend to Fastify, the Agent service and finally the Docker Runtime before we could add security controls without breaking the starter application.
Network isolation was another major challenge. We wanted the Runtime to have no direct Internet access, while still allowing approved requests to reach ModelArk and selected development services through Warden. Several early attempts either blocked too much or left more access than intended.
We also had to carefully manage the lifecycle of each temporary grant. We not only needed to create a grant, we also needed it to expire, track usage, support revocation and cancel only the matching Runtime without affecting other Agents.
Finally, testing security behaviour was more difficult than testing a normal feature. A failed request could indicate that Warden correctly denied it, but it could also mean that a file, dependency or service was missing. We therefore created controlled test cases and correlated traces so we could distinguish an intentional policy denial from an unrelated application error.
Accomplishments that we're proud of
First off, we are proud of finishing this project and designing a middleware, as once again, this is the first time Vernice and myself has built a middleware.
On to the project: We are proud that Warden operates across a real frontend-to-backend-to-Runtime path rather than presenting security controls only in the UI.
A normal Node.js task still succeeds using the Agent's persistent workspace, proving that Warden preserves useful functionality. At the same time, our controlled abuse fixture shows that an undelegated connection to 1.1.1.1:443 is contained at two layers:
- Direct TCP fails with
ENETUNREACHbecause the Runtime has no direct Internet route. - Brokered CONNECT receives HTTP 403 with
host_not_allowed.
Warden records this denial alongside the model calls and grant lifecycle in one correlated trace. We also demonstrate that the provider key remains outside the Runtime, every Run receives a separate temporary grant, and an operator can revoke the active grant and cancel only its matching Runtime.
After revocation, the Agent returns to Ready, the evidence remains available, and the platform continues operating normally. The complete implementation also passes our automated tests, Docker isolation checks and secret-scanning workflow.
What we learned
One of our biggest lessons was understanding how much responsibility sits between an application and its Runtime.
We learned how middleware can intercept requests, attach run-specific context, enforce policy and record evidence without requiring the original application to be completely rewritten. We also became more comfortable tracing a request across the frontend, Fastify API, Agent service, Docker Runtime, Warden broker and external provider.
From a security perspective, we learned that protecting a credential requires more than hiding it from the interface. The Runtime boundary, network routes, logs, command arguments and revocation lifecycle must all be considered together.
Most importantly, we learned that good security middleware should remain mostly invisible during normal use. Valid Agent tasks should continue working, while unsafe actions are denied with clear reasons and enough evidence for the operator to understand what happened.
What's next for Warden Officer
Warden Officer is still a proof of concept, and this was our first time building a full middleware. Our next step would be to improve it gradually based on what we learned during this project.
Some areas we would like to explore are:
- Supporting more AI providers beyond ModelArk.
- Adding proper user authentication and different access roles.
- Creating more delegation profiles for different Agent tasks.
- Improving the dashboard so policy decisions and denied requests are easier to understand.
- Testing Warden with more attack scenarios and unusual Runtime behaviour.
- Exploring Kubernetes or cloud deployment after strengthening the current Docker implementation.
In the longer term, we would also like to investigate external secret storage and stronger isolation between individual Agent Runs. Our goal is to continue developing Warden into a security layer that is practical for developers to use without taking away the flexibility that makes AI Agents useful.
Built With
- byteplus
- capability-based-security
- codex
- credential-brokering
- distributed-tracing
- docker
- fastify
- github
- gitleaks
- http-proxy
- integration-testing
- network-isolation
- node.js
- observability
- policy-enforcement
- react
- restapi
- typescript
- vite
- zero-trust
Log in or sign up for Devpost to join the conversation.