Self-hosting changes who operates an AI coding platform. It does not make the platform trusted by default.
An AI development task can combine repository content, model output, shell commands, credentials, package registries, preview servers, and human approval. That is a much larger authority surface than a chat box. The useful security question is not “is it open source?” It is “which input can cause which side effect across which trust boundary?”
This article uses MonkeyCode as a worked example because its public README describes private deployment, managed development environments, model management, AI task management, and project requirements. I reviewed the repository documentation at commit 1ac778f. This is a design review, not a penetration test or a claim about a deployed instance.
Start with authority, not components
A component diagram often says where services run. A threat model must also say what they can do.
developer browser
|
| identity, task text, approvals
v
control plane ---------> model endpoint
| ^
| task + policy | prompt / response
v |
workspace runner ------------+
|
+--> repository credentials
+--> package registries
+--> build tools and shell
+--> preview endpoint
The exact MonkeyCode implementation may divide these responsibilities differently. The diagram is an explicit review model inferred from the capabilities in the README. Replace it with the real topology before using the checklist for an approval decision.
For every arrow, record four fields:
| Field | Question |
|---|---|
| Principal | Which human or service initiated the action? |
| Input | Is the data trusted, untrusted, or generated? |
| Authority | Can the receiver read files, run commands, reach a network, or change a repository? |
| Evidence | Which log proves the decision and result? |
This catches a common modeling mistake: treating model output as data while quietly giving the consumer permission to execute it.
Five abuse cases to model first
1. Repository content becomes instructions
A README, issue, test fixture, or dependency can contain text that attempts to redirect an agent. The control is not a better system prompt. Keep authorization in deterministic policy: permitted tools, path scopes, command classes, network destinations, and approval gates.
Test property:
Untrusted repository text cannot expand the task's original authority.
2. A workspace exposes a credential
Credentials may enter through Git remotes, environment variables, package-manager configuration, cloud metadata, or copied logs. Prefer short-lived task credentials and mount only the secret needed for the current operation. Redaction is a backup control, not the primary boundary.
Test property:
A task that prints its environment cannot recover another task's secrets.
3. One task reaches another workspace
For a team platform, process separation is not automatically tenant separation. Review filesystem namespaces, container privileges, shared caches, Docker sockets, host mounts, preview routing, and cleanup after cancellation.
Test property:
Knowing another task ID or path does not grant read, write, signal, or preview access.
4. Dependency installation becomes unrestricted egress
Builds legitimately contact registries, but unrestricted outbound access also creates an exfiltration path. Define whether a workspace can reach the public internet, internal services, cloud metadata, and arbitrary model endpoints. Log denied destinations without logging secret-bearing URLs.
5. Generated code crosses into a trusted branch
The last boundary is often Git, not the model. Protect the default branch with human review, required tests, scoped repository tokens, signed provenance where appropriate, and a patch-size or sensitive-path gate.
A control matrix that can fail closed
Use a matrix like this during deployment review:
| Boundary | Prevent | Detect | Recover |
|---|---|---|---|
| Browser → control plane | SSO, MFA, role checks, CSRF protection | auth and admin audit log | revoke sessions and tokens |
| Control plane → runner | signed task identity, policy snapshot, least privilege | immutable task/tool events | cancel and quarantine workspace |
| Runner → repository | short-lived scoped token, protected branches | commit and push audit | revoke token, revert patch |
| Runner → network | destination policy, metadata block | DNS/connection telemetry | isolate runner, rotate exposed secrets |
| Task → task | per-task identity and filesystem isolation | cross-scope denial events | destroy affected workers and caches |
| Runner → preview | authenticated routing, safe headers, expiry | access logs tied to task ID | revoke route and terminate process |
“Prevent, detect, recover” matters. A control list containing only prevention assumes the first layer never fails.
Make the review reproducible
Pin the source revision and keep the evidence beside the decision:
git clone https://github.com/chaitin/MonkeyCode.git
cd MonkeyCode
git checkout 1ac778fdba1da1b353f7f5672d2e4550801cf46d
rg -n "privileged|docker.sock|hostNetwork|hostPath" .
rg -n "Authorization|token|secret|password" backend frontend
rg -n "exec|spawn|shell|command" backend
These searches do not prove a vulnerability or prove safety. They create a repeatable starting set for manual tracing. For each relevant hit, document the call path, input origin, permission check, secret handling, emitted audit event, and failure behavior.
Then run adversarial tests in a disposable environment:
- submit repository text that requests an unrelated command;
- attempt to read a sibling workspace and a host path;
- request cloud metadata and an unapproved network destination;
- print likely secret locations and inspect every log surface;
- cancel during clone, dependency install, build, and repository write;
- reuse expired task and repository credentials;
- request a preview URL from another authenticated user.
Record a version, topology, test identity, expected denial, actual result, and evidence location for every case. “Blocked” without a log or packet trace is not a result another reviewer can reproduce.
What the public repository does and does not establish
The official documentation supports that MonkeyCode is AGPL-3.0 open source and offers private deployment. That makes source review and operator control possible. It does not, by itself, establish isolation strength, a compliance outcome, or secure configuration for a particular deployment. Those conclusions require the actual topology, version, identity provider, secret flow, runner privileges, network policy, and adversarial test results.
Disclosure: I contribute to the MonkeyCode project. This threat model is based on the linked public repository and documentation, not an independent security audit.
If you are evaluating a self-hosted setup, join the MonkeyCode Discord to discuss the deployment model with the team. You can also ask there about currently available free model credits; confirm eligibility and usage limits before planning around them.
The safest output of a threat model is not a “secure” label. It is a short list of authority claims that can be denied, observed, and retested after every meaningful deployment change.
Top comments (0)