tarek.kharsa

home / lessons / opencode · lesson 7

SecurityOpenCode · lesson 7 of 82 min read

Configured is not allowed

Policy is its own layer, and the last matching rule wins.

Problem

“Enabled” and “disabled” provider lists mix two questions: how do I use this provider, and may I? A company can't forbid a provider a developer has valid keys for.

Idea

Keep config and permission apart. Permission is a short list of allow/deny rules, and the last rule that matches wins.

Try it: last match wins

pick a provider, flip, reorder or add rules

Rules: 1. deny *  2. allow anthropic. For openai, only rule 1 matches, so it's denied. For anthropic, both match and rule 2 is last, so it's allowed.

statements.findLast(
  (s) => Wildcard.match(action, s.action) && Wildcard.match(resource, s.resource),
)?.effect ?? fallback

Two different questions

Config: how?

Endpoints, options and model overrides.

Says nothing about permission.

Policy: may I?

Ordered allow/deny rules with wildcards.

"Policies do not make unusable resources usable."

A provider can be correctly configured and have valid credentials while policy still denies its use.

Order decides, not specificity

There's no "the more specific rule wins" magic: "A specific resource does not automatically beat a wildcard resource. Written/evaluation order controls the result." You can predict any answer by reading the rules top to bottom, which is what the demo above does. Each caller passes its own default; provider use defaults to allow, so people with no policy see no change.

Small on purpose

The same vocabulary is meant for more actions later, like plugin.load or mcp.connect, with user rules overriding repository rules. The non-goals are written down too: no conditions, no principals, no approval prompts.

Steal this

Keep "is it configured?" and "is it allowed?" in separate layers. Make permission an ordered list where the last match wins, so anyone can predict the result by reading top to bottom.

Use it in your code

A prompt for your coding agent

Run it from the root of your repo. It checks whether the idea fits before it changes anything.

Separate "is it configured?" from "is it allowed?" in this project.

The idea: configuration says how to use something (endpoints, keys, options). Policy says whether you may: an ordered list of allow/deny rules with wildcards, where the last matching rule wins and each caller supplies a default. A configured resource can still be denied.

1. Find enable/disable lists, feature allowlists or permission checks mixed into configuration, for example enabled_providers, disabled_features or allowed_hosts.
2. Tell me whether separating them would help here. If the logic is trivial, say so and stop.
3. If it would, propose a small policy module: rules with an effect, an action and a resource; wildcard matching; and evaluation as "the last match wins, otherwise the caller's default". With no rules, behavior must not change.
4. Move one mixed-in check onto it, with tests for ordering (deny everything, then allow one), wildcards and the default.

No conditions, roles or approval flows for now. Keep the change small.

Read the source

Where this comes from

OpenCode (anomalyco/opencode), the open-source coding agent (these lessons are from its upcoming v2). The files behind this lesson: