What happened in the OpenCode security incident in October 2026?
Incident report
OpenCode disclosed a breach on October 17, 2026 affecting a subset of hosted Console users who had linked external model providers. It reported that 1.4% of Console users were affected and that they had been notified by email. Its announcement is reproduced in BleepingComputer's October 19 reporting.
Reviewed October 21, 2026. This report distinguishes the published account from our technical analysis. Seekrit publishes this article; the later sections explain what our credential broker can change, and what it cannot.
The central issue for developers is where an AI-provider key lives. A coding client on your machine, a hosted account console, and an inference gateway can all appear in one workflow. They do not necessarily hold the same secrets or share the same exposure. Before changing anything, identify which component received the real credential.
What is known about the OpenCode breach?
The public scope concerned Console-linked providers. That does not establish that every local OpenCode installation was compromised. OpenCode associated the incident with a large-scale distillation attack, but the statement did not explain the access-control failure or how the keys were obtained. Source: OpenCode's announcement, as reproduced in the reporting linked above.
BleepingComputer also reproduced a customer notice giving October 17 at 00:30 UTC as the earliest possible key exposure. It reported user complaints about unexpected charges and Google Cloud project suspensions. Those are reported customer experiences, not a published audit of total losses. Source: BleepingComputer.
For an incident reader, the useful distinction is between an affected product, a possible exposure window, and a fully explained exploit. The first two help scope a response. They do not supply the third.
Timeline and evidence
| Date | Published information | What it establishes |
|---|---|---|
| October 17, 00:30 UTC | Earliest possible exposure in the customer notice reproduced by BleepingComputer. | A reported investigation boundary, not a proven intrusion timestamp. |
| October 17 | OpenCode announced the Console breach and customer notifications. | Company-reported product scope and response. |
| October 19 | BleepingComputer published its report and said its request for further details had not received a response by publication. | News coverage, not a technical postmortem. |
Sources: OpenCode announcement and October 19 coverage.
This timeline should not be expanded with unrelated service errors or an unconnected vulnerability merely because they occurred nearby. To establish causation, a report needs evidence linking the exploited component to the credential access.
Does a distillation attack explain how keys were stolen?
No. A description of what someone wanted to do with access is different from an explanation of how they obtained it.
In general, model distillation uses outputs from one model to help train another. That term alone says nothing about authorization. An organization may have legitimate permission to query a model, or an attacker may generate requests using credentials belonging to someone else. The technical questions are who authorized the calls, which account paid for them, and how the caller acquired its access.
For a hypothetical stolen-key workflow, the sequence is straightforward:
- A party obtains a reusable provider credential.
- It submits requests that the provider attributes to that credential's account.
- It uses the responses for its own purpose while the account owner bears the usage or other consequences.
This is a general explanation of credential abuse, not a reconstruction of OpenCode's intrusion. It does not identify an attacker, demonstrate model training, or prove a particular exploit.
Calling the activity distillation therefore leaves the defensive question open: what allowed someone to use a customer's authority? That is the question a credential architecture can address even while the root cause is unknown.
Why does hosted bring-your-own-key change the trust boundary?
When you give a hosted service a provider key, the service needs a way to use it. Encryption at rest may protect its database files, but an authorized component must still obtain usable authentication for outgoing requests.
Imagine a team with an inference key used by both a developer tool and a production worker. Uploading that same key to a hosted gateway adds another place where the team's provider authority can be exercised. A compromise there could affect the shared provider account even if the production worker itself remains untouched.
This example is our architectural analysis. It is not a claim about how OpenCode stored keys, what encryption it used, or how its internal permissions were configured.
The practical lesson is to distinguish three things:
| What changes | What it accomplishes | What it does not accomplish |
|---|---|---|
| Encrypt the gateway's stored keys | Protects stored values when decryption authority remains separate and secure. | Hides keys from the component authorized to decrypt them. |
| Give each integration its own provider key | Makes permissions, usage attribution, and revocation more specific. | Prevents theft of the key given to that integration. |
| Keep the provider key outside the hosted gateway | Removes that gateway's stored copy of the reusable credential. | Makes every permitted request safe or free of cost. |
The last option is the one to examine when the requirement is that a third party must not hold the provider key at all.
What should teams do with potentially exposed provider keys?
Start with the vendor's notice and your own record of where keys were saved. Then work at the provider that issued each credential. The following is our response guidance, not a claim about additional incident findings.
Revoke the old authority. Deleting a key from an integration removes that integration's saved copy. It does not invalidate a copy someone already took. Replace the credential at its issuer and explicitly revoke the old one. If exposure makes continued use unacceptable, revoke before restoring service.
Find every legitimate consumer. A key may also serve a worker, another engineer's machine, or a test environment. Inventory those dependencies so replacing it does not leave an overlooked process using the old value. Use separate credentials going forward where their access needs differ.
Review provider-side evidence. Examine usage, billing, and available access records. Requests made directly with a stolen key may never pass through the coding tool's own logs. Preserve timestamps and identifiers useful to a provider investigation without copying the secret into a support ticket.
Reduce the replacement's permissions. Match access to the actual workload. Use the issuer's available restrictions and spending controls, and verify whether each control blocks usage or merely alerts. A notification after a large bill is different from an enforced limit.
Check the new route. A successful request proves the application can work; it does not prove the old credential is dead or absent from other stores. Verify those separately.
How would Seekrit help an OpenCode user?
The strongest design uses Seekrit to hold the provider key for a broker you control. The local coding client makes requests through that broker, and the broker applies the credential only when forwarding an allowed request. You do not upload the reusable provider key to the hosted Console.
This is an alternative request path, not a switch that retrofits the hosted Console's internal storage. You must configure a supported client integration and decide which hosted features you still need.
OpenCode's current provider documentation
describes custom providers and settings.baseURL overrides for proxy
endpoints. It also notes that settings depend on the selected runtime package.
That provides a configuration seam; it does not prove every model, transport,
or authentication mode will work with an arbitrary broker. Validate the
specific client version and provider you deploy.
Separate the credential holder from the agent
Seekrit's proxy accepts placeholders such as
{{seekrit:ANTHROPIC_API_KEY}} and substitutes an allowed secret into an
outbound request. Its configuration restricts upstream destinations, secret
names, methods, and paths. It also scrubs supported echoes of injected values
from responses; that is defense in depth, not a reason to allow arbitrary
upstream endpoints.
The important placement is:
| Component | What it should receive |
|---|---|
| Coding client and its tools | Placeholder plus limited permission to call the broker |
| Independently controlled broker | Seekrit service token and required provider credentials |
| Seekrit API's ordinary storage | Ciphertext and wrapped environment keys |
| Model provider | The real credential on the authenticated request |
Keep the broker's token, process, files, and administration outside the agent's reach. Running a second process under the same unrestricted user account is not a strong boundary against an agent that can inspect that user's files or processes. Use an isolation boundary appropriate to the threat, and protect remote ingress with authentication and authorization.
A placeholder is a secret name, not caller authentication. Configure broker access separately and avoid exposing a publicly usable inference proxy.
Do not give the agent a replacement master credential
A Seekrit service token contains private-key
material. Anyone holding it can decrypt the environments granted to it.
Placing SEEKRIT_TOKEN in the coding client's environment, workspace, or
hosted Console simply gives that component a different sensitive credential.
The token belongs with the trusted broker.
Likewise, seekrit-run injects plaintext into the process
it starts. It is useful for trusted applications, but wrapping the coding
agent itself does not keep keys out of that agent. An in-process SDK also
decrypts in the caller's address space. Choose those tools when the process
is supposed to hold the value, and a separate broker when it is not.
In the ordinary Seekrit storage model, client-side encryption separates stored ciphertext from decryption keys. Optional third-party sync deliberately grants decryption and sends values to a destination; enabling such a copy would restore that destination's custody.
Distinguish key theft from misuse of allowed access
Under this design, a compromise confined to a hosted Console that never received your provider key or broker's decryption token cannot extract those credentials from its stored records. This is the concrete exposure it avoids. It does not prove that Seekrit would have prevented the OpenCode intrusion.
Someone who controls a client authorized to use the broker may still make permitted inference requests. They could generate costs or send sensitive source material to the model. Destination and path restrictions do not fully constrain request content, model selection, or volume. Add application-level authorization and usage controls where required, and maintain provider limits.
A broker compromise remains serious too. The design moves credential use to a smaller trusted component; that component still needs careful operation.
A migration plan worth testing
Start with one provider and a disposable test key. Configure the broker with only that provider's required operations, and configure the client with a placeholder. Verify a normal request, a denied destination or operation, an unauthenticated caller, and the absence of real keys from client diagnostics.
Then create a production key scoped to this workload, store it in Seekrit, and grant it only to the broker. Remove superseded hosted and local copies, revoke the old upstream key, and confirm the client has no fallback path using an older saved credential. Document how the broker reloads rotated values and how access is cut off if a caller is compromised.
The result should be easy to explain: the coding tool can ask for model work, but it cannot read the reusable provider key. For another perspective on the same custody boundary, see our Railway incident report.