# Audit BYOK Model Endpoints Before Your AI Agent Gets the Key

> Source: <https://dev.to/jaryn_123/audit-byok-model-endpoints-before-your-ai-agent-gets-the-key-4dna>
> Published: 2026-07-14 04:49:07+00:00

“Bring your own key” looks like a settings feature. For an AI coding agent, it is also a security boundary: a privileged workload will send repository context, prompts, and credentials toward a network destination selected by configuration.

That boundary deserves more than a successful `GET /models`

request.

I reviewed [MonkeyCode](https://github.com/chaitin/MonkeyCode), an open-source AI development platform, at commit [ c58bcd4](https://github.com/chaitin/MonkeyCode/tree/c58bcd4dd4b7031f469a1271f276d22550b8f523). Its source provides a useful concrete case because users can configure model providers while task runtimes receive proxy credentials.

This is a source review, not a penetration test. In particular, I am not claiming encryption, rotation, or revocation behavior that the reviewed files do not establish.

The reviewed [model API-key schema](https://github.com/chaitin/MonkeyCode/blob/c58bcd4dd4b7031f469a1271f276d22550b8f523/backend/ent/schema/modelapikey.go) and [model repository](https://github.com/chaitin/MonkeyCode/blob/c58bcd4dd4b7031f469a1271f276d22550b8f523/backend/biz/setting/repo/model.go) separate a configured provider credential from a runtime API key.

The task path then calls `CreateRuntimeAPIKey`

and gives the runtime a proxy base URL plus that runtime token. In the reviewed repository logic, a token is associated with a user, model, and VM; a token for the same user and VM can be reused and rebound to a model.

That yields two distinct questions:

| Plane | Secret holder | Security question |
|---|---|---|
| Provider plane | Control service | Can this credential call only the intended provider, models, and operations? |
| Runtime plane | Agent VM | Is this delegated token narrowly bound, short-lived, observable, and invalid after its task boundary ends? |

A proxy reduces direct provider-key exposure inside the VM. It does not automatically settle endpoint trust, server-side storage, token lifetime, replay, or revocation.

A configurable model base URL controls where sensitive payloads leave the platform. Audit it like a webhook destination or package registry:

TLS answers “is this encrypted to the named peer?” It does not answer “should this peer receive the repository?” An allow-list or administrator approval supplies that missing policy decision.

Here is a small policy document from the companion files:

```
{
  "endpoint": "https://llm-gateway.example/v1",
  "allowed_hosts": ["llm-gateway.example"],
  "require_https": true,
  "forbid_url_credentials": true,
  "key_scope": "model-inference-only",
  "runtime_credential": {
    "audience": "llm-proxy",
    "bound_to": ["user", "model", "vm"],
    "max_ttl_seconds": 3600
  },
  "egress": { "allowed_ports": [443], "follow_redirects": false }
}
```

The included zero-dependency checker rejects HTTP, URL credentials, unknown hosts, unrestricted key scope, missing bindings, excessive TTL, and redirects:

```
node check-policy.mjs byok-policy.json
node test-policy.mjs
```

Expected output:

```
PASS BYOK endpoint policy
PASS policy accepts the safe fixture and rejects five unsafe properties
```

This is a configuration gate, not a network scanner. Production enforcement must also validate DNS results at connection time, prevent redirect bypass, use a trusted TLS stack, and keep egress policy outside the agent's control.

For each secret type, write down:

``` php
create -> store -> delegate -> use -> observe -> rotate -> revoke -> delete
```

Then demand evidence for each arrow. A schema field proves persistence, not encryption. A generated token proves delegation, not expiry. A proxy proves mediation, not least privilege.

The runtime-token reuse behavior is also a reason to define model-switch semantics explicitly. If rebinding is intentional, ask what happens to an in-flight request using the prior model, how caches are keyed, and which audit event links old and new authority.

My acceptance gate would be: no provider key enters the task VM; the outbound host is approved after DNS and redirect handling; the runtime token is audience-, user-, model-, and VM-bound; expiry and revocation are tested; and logs prove the decision without exposing content.

Disclosure: I contribute to the MonkeyCode project. The observations and limitations above are based on the linked repository at the pinned commit and the local policy tests described here.
