Inspiration

AI coding agents are becoming genuinely useful: they can read files, run commands, install packages, and call external services. But that autonomy creates a difficult question: What happens when an agent follows malicious instructions and acts against its user?

Prompt injection is still a major issue. Rather than assuming the model will always behave safely, we designed for the harder case, assuming that the agent may already be compromised.

Our goal was to give users autonomy over their agents. An agent should receive only the access it needs, users should be able to remove that access immediately, and sensitive information should not leave the environment simply because an agent decides to send it somewhere.

What it does

leetsafe is a safety middleware layer for AI coding agents. It gives each agent its own identity and controls what that identity is allowed to access.

Permissions can be:

  • Scoped to a particular resource or network host
  • Time-limited
  • Revoked at any time
  • Delegated only when the delegating agent already has that authority

Network access is denied by default. When containment is enabled, an agent runs in an internal container network with no direct route to the internet or host machine. Its only route outward is through an authorising proxy.

Before the proxy opens a HTTP request or HTTPS connection, it checks the agent’s current permissions. If access has not been granted, the request is blocked or held for human approval before the destination receives a connection.

Permissions are checked live, rather than cached. If a user revokes a permission, the next matching request is denied. Repeated attempts to reach blocked destinations are treated as suspicious behaviour and quarantine the agent by stopping it.

Every grant, revocation, approval, allow, denial, and quarantine decision is recorded on the run timeline with a rule ID explaining why it happened.

How we built it

We built on the provided Agent Launchpad scaffold, which gave us the core agent experience: agent creation, the Playground, persistent workspaces, and the Codex runtime.

Our team built the safety, governance, identity, and enforcement layer:

  1. Human-in-the-loop controls
    Risky agent actions can pause for human review, while ungranted network requests can be held for one-time approval before any external connection is opened.

  2. Budget and canary safeguards
    We added budget circuit breakers, token and cost observability, and a canary tripwire to help users spot suspicious agent behavior and control runaway runs.

  3. Traceability and live observability
    We built live trace events, run history, a security feed, and timeline receipts so users can see policy decisions, approvals, denials, and agent activity in context.

  4. Identity and ownership
    Humans and agents are separate principals. Every agent has an owner, and backend ownership checks happen before grants are considered.

  5. Scoped, revocable grants
    The identity service supports resource:read, resource:write, and network:egress grants. Grants may expire or be revoked. Delegation only narrows authority, and revoking a parent grant also revokes its descendants.

  6. Network containment
    The agent container runs on a Docker internal network with no route off-box. A proxy sidecar is attached both to that internal network and to an uplink network; the agent itself only joins the internal one.

  7. Per-request authorization and authenticated agent identity
    The proxy checks every request and HTTPS CONNECT against live grants before opening an upstream connection. It fails closed if the authorizer cannot be reached, and it uses HMAC-derived credentials so an agent cannot impersonate another agent.

  8. Quarantine and security receipts
    Repeated denied network requests raise strikes and can stop the agent. Every grant, revocation, approval, allow, denial, and quarantine decision becomes a trace receipt with a clear rule ID.

The project uses TypeScript, Fastify, React, Docker-compatible container networking, and a proxy sidecar. It supports BytePlus ModelArk, Gemini through a local Responses adapter, and OpenAI-compatible providers such as OpenRouter.

Challenges, mistakes, and realisations

Detection is not prevention

One of our most important realisations was that identifying a risky command after it has run is not the same as preventing it.

The runtime reports command and tool details after execution. Those events are useful audit evidence, but they cannot honestly be described as having prevented a filesystem, privilege, credential, or package side effect. We therefore treat shell-risk classification as post-execution telemetry and place actual prevention at the network boundary, before a connection is opened.

Our initial proxy idea did not work

We first considered placing the proxy on the host while giving the agent an internal Docker network. Testing showed this was not viable: an internal network removes access to the host as well as the internet.

We changed the design to a dual-network sidecar proxy. The proxy shares an internal network with the agent but is also connected to an uplink network. This lets the proxy reach approved destinations while the agent remains unable to reach the internet or host directly.

An agent cannot be trusted to name itself

A compromised agent could claim to be another agent and attempt to use that agent’s permissions. We addressed this by binding proxy authentication to an HMAC-derived credential. The agent can use its assigned credential, but it cannot forge another agent’s identity.

Human approval can be abused too

Holding requests for human review created a new risk: an agent could flood the approval queue and exhaust both system resources and the operator’s attention.

We added a bound on pending approvals. Excess requests are refused, count as blocked attempts, and can contribute to quarantine.

Security claims must match runtime reality

Container egress enforcement is real only under the isolated container runtime. The local-process, Docker Compose, and current ECS profiles do not provide the same network boundary.

Instead of hiding that difference, the project documents it explicitly and identifies when containment is unavailable.

Accomplishments we are proud of

We built something we did not think we could build at this stage. As a team of Year 2 computing students, we began this hackathon barely understanding many of the security and infrastructure terms we encountered. Over the course of the project, we learned by building, testing, breaking, and redesigning.

We are proud that we turned those unfamiliar concepts into a working middleware system where real users can create agents, review their activity, control permissions, revoke access, and see security decisions recorded in real time.

Most importantly, we built a usable layer that helps users keep AI coding agents under control: limiting what they can access, blocking unapproved network activity, and responding when an agent behaves suspiciously.

We are also proud that we did give up at the first working version. We found weaknesses in our own assumptions, from proxy placement and agent impersonation to approval flooding and cached permissions, and persevered through the merge conflicts and mistakes to improved the design each time. Seeing those lessons become actual safeguards in the product is what makes this project meaningful to us.

What we learned

This project taught us far more than just security concepts and agent infrastructure. As Year 2 students studying during a busy school semester, one of our biggest challenges was simply staying persistent while balancing classes, deadlines, and a project idea that often felt much larger than our current experience.

There were many moments where something did not work: designs had to be reconsidered, tests exposed gaps in our assumptions, integrations failed, and features that looked simple on paper became difficult in practice. Instead of treating those failures as signs to give up, we learned to break the problem into smaller pieces, test each assumption, ask better questions, and improve the project one iteration at a time.

We learned that building a complex system is not about understanding everything at the beginning. It is about being willing to learn unfamiliar concepts, accept that the first solution may be wrong, and keep moving forward when progress is slow.

Most importantly, we learned to be honest about what our system can and cannot do. Security is not a single feature or a claim that an AI agent is “safe.” It is a series of boundaries, checks, trade-offs, and clear limitations that give users more control over what their agents can do.

Current limitations

This is a hackathon proof of concept, not a production identity platform.

The human-principal population currently consists of mock users, so a real deployment would need an identity provider. Resource authorization is demonstrated with mock resources rather than real workspace-file enforcement.

HTTPS grants operate at the hostname level because an HTTP CONNECT tunnel does not reveal encrypted URL paths. Raw TCP and git+ssh traffic are blocked instead of proxied. Quarantine strikes are stored in memory and reset after a server restart.

The container-network topology has been verified on Docker and OrbStack. It should be independently tested before relying on another container engine. Ordinary containers are also not a complete multi-tenant sandbox; Agent Passport specifically enforces outbound network containment.

What’s next for leetsafe

Next, we would connect resource grants to real workspace files, replace mock principals with production authentication, and persist quarantine state.

We would also expand the policy model to cover more tools, databases, cloud APIs, and agent-to-agent communication. Our broader goal is for agents to stay useful and autonomous while users retain control over their data, permissions, and privacy.

Built With

+ 20 more
Share this project:

Updates