How Product Restrictions Are Enforced in the OpenAI Plugin Marketplace

TLDR: Product restrictions in the OpenAI Plugin Marketplace are enforced through a declarative products array inside each plugin's policy object, which is aggregated into marketplace JSON files and filtered at runtime to expose only plugins explicitly approved for specific OpenAI products like Codex.

The openai/plugins repository contains the declarative configuration that governs which plugins appear in which OpenAI product surfaces. The enforcement mechanism relies on JSON-level filtering rather than hardcoded business logic, making the permission system transparent and maintainable.

Declaring Product Restrictions in Plugin Manifests

Every plugin defines its product availability through a policy object in its manifest file. For example, in plugins/game-studio/.codex-plugin/plugin.json, the policy might specify:

{
  "policy": {
    "installation": "AVAILABLE",
    "authentication": "ON_INSTALL",
    "products": ["CODEX"]
  }
}

The products array acts as a whitelist. If the array contains "CODEX", the plugin appears exclusively in the Codex interface and remains hidden from other product surfaces like the ChatGPT Plugin Store.

Aggregated Marketplace Configuration Files

The repository aggregates individual plugin manifests into two canonical JSON files that serve as the single source of truth for the marketplace backend:

Each entry in these files mirrors the policy.products array from the individual plugin manifest, creating a centralized permission matrix that the runtime filters against when serving requests.

Runtime Filtering Logic

When a client requests plugins for a specific product (such as Codex), the marketplace service loads the appropriate aggregated JSON file and iterates over the plugins array. The service includes only those plugins whose policy.products array contains the requested product identifier.

If a plugin omits the products field or provides an empty array, the marketplace treats it as universally available across all products. This declarative approach ensures that enforcement happens at the data layer—plugins simply disappear from responses for products they do not support.

Filtering Implementation Example

The following Node.js snippet illustrates the filtering logic:

import fs from 'fs';
import path from 'path';

// Load the aggregated marketplace file for the API endpoint
const marketplacePath = path.resolve(
  __dirname,
  '..', '..', '.agents', 'plugins', 'api_marketplace.json'
);
const marketplace = JSON.parse(fs.readFileSync(marketplacePath, 'utf8'));

/**
 * Return plugins that are permitted for the given product.
 * @param {string} productId – e.g. "CODEX"
 * @returns {Array<Object>} List of plugin entries.
 */
function listPluginsForProduct(productId) {
  return marketplace.plugins.filter(p => {
    const allowed = p.policy?.products ?? [];
    // If the plugin does not declare a products list, it is assumed to be
    // available for all products (the marketplace treats the field as optional).
    return allowed.length === 0 || allowed.includes(productId);
  });
}

// Example: fetch plugins that Codex can use
const codexPlugins = listPluginsForProduct('CODEX');
console.log('Codex‑eligible plugins:', codexPlugins.map(p => p.name));

This implementation demonstrates three critical behaviors: the JSON file is read once and cached, an empty products array signifies no restrictions, and only explicit matches for the requested product ID are returned.

Summary

  • Declarative manifests: Product restrictions are defined in individual plugin manifests (e.g., plugins/game-studio/.codex-plugin/plugin.json) via the policy.products array
  • Centralized aggregation: Two files (/.agents/plugins/api_marketplace.json and /.agents/plugins/marketplace.json) consolidate permissions for API and UI consumers
  • Runtime filtering: The backend filters the aggregated list based on the requested product ID, returning only plugins that explicitly include that product or have no restrictions
  • Universal access: An empty or missing products array grants availability across all OpenAI products

Frequently Asked Questions

What happens if a plugin omits the products field?

If the products array is missing or empty, the marketplace treats the plugin as available for all products. This optional field defaults to universal access, meaning no restrictions are applied.

Where are the master marketplace files located?

The aggregated marketplace configurations reside at /.agents/plugins/api_marketplace.json (for API consumers) and /.agents/plugins/marketplace.json (for the UI marketplace). These files contain the complete plugin catalog with their respective product restrictions.

Can a plugin target multiple specific products?

Yes. The products array accepts multiple strings, allowing a plugin to whitelist itself for specific offerings like ["CODEX", "CHATGPT"] while remaining inaccessible to other OpenAI products not listed in the array.

How does the backend enforce these restrictions?

The enforcement is entirely data-driven. When processing a request, the marketplace service loads the appropriate JSON file and filters the plugins array to include only entries where policy.products contains the requested product identifier or is empty. Clients receive a pre-filtered list, ensuring users cannot discover or install plugins that are not explicitly approved for that product.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →