# OpenAI Plugins Security: Essential Considerations for Safe Development

> Secure your OpenAI plugins against attacks like CSRF and token leakage. Learn essential security considerations for safe plugin development including HTTPS, OAuth, and OWASP headers.

- Repository: [OpenAI/plugins](https://github.com/openai/plugins)
- Tags: best-practices
- Published: 2026-07-05

---

**OpenAI plugins require a defense-in-depth security posture covering HTTPS enforcement, PKCE-based OAuth flows, server-side token storage, and strict OWASP headers to protect against CSRF, token leakage, and man-in-the-middle attacks.**

OpenAI plugins are independent code bundles that expose **skill** definitions via JSON manifests and execute in diverse environments ranging from cloud functions to local developer hosts. Because any ChatGPT session can invoke these plugins, developers must implement robust security controls across transport, authentication, and data layers. This guide consolidates security best practices found in the `openai/plugins` repository, drawing from specific implementations in the Zoom, Twilio, and Vercel platform integrations.

## Transport-Layer Security and HTTPS Enforcement

All external endpoints must reject plain HTTP and enforce **TLS 1.2 or higher**. According to the source code in [`/plugins/zoom/skills/zoom-apps-sdk/concepts/security.md`](https://github.com/openai/plugins/blob/main//plugins/zoom/skills/zoom-apps-sdk/concepts/security.md), plugins must redirect HTTP traffic to HTTPS and implement strict transport security headers.

Required **OWASP headers** include:
- `Strict-Transport-Security` with a max-age of at least one year
- `X-Content-Type-Options: nosniff` to prevent MIME sniffing
- `Content-Security-Policy` with `frame-ancestors` restricted to the hosting platform (e.g., `zoom.us *.zoom.us`)
- `Referrer-Policy: same-origin` and `X-Frame-Options` to control embedding behavior

Use valid, non-self-signed certificates for production deployments. For local development, tools like `ngrok` automatically supply trusted certificates that satisfy these requirements.

## Authentication and Authorization Controls

### OAuth with PKCE

Implement **PKCE (Proof Key for Code Exchange)** for all public OAuth clients. As documented in the Zoom security concepts, never expose client secrets in frontend code. Instead, generate a cryptographic verifier server-side, hash it to create a challenge, and store the original verifier in session state.

### CSRF Protection

Generate a cryptographically random `state` parameter before redirecting users to the OAuth provider. Validate this token upon callback to prevent **cross-site request forgery** attacks. The validation logic should return a 403 response if the state parameter mismatch indicates potential CSRF activity.

### Webhook Verification

Verify signatures on all incoming webhook requests before processing payloads. Platforms like Zoom and Twilio provide signature verification mechanisms in [`/plugins/zoom/skills/rest-api/references/authentication.md`](https://github.com/openai/plugins/blob/main//plugins/zoom/skills/rest-api/references/authentication.md) that cryptographically validate the webhook origin.

### Least-Privilege Scopes

Request only the minimum OAuth scopes necessary for the plugin's functionality. Avoid "full-access" tokens that grant broader permissions than required for the specific skills implemented.

## Data Protection and Token Storage

### Server-Side Token Persistence

Persist **access tokens** and **refresh tokens** exclusively on the server side using Redis, encrypted databases, or secure storage like Firestore. Never store tokens in browser storage mechanisms such as `localStorage`, `sessionStorage`, or client-side cookies, as these are vulnerable to XSS extraction.

### Secure Cookie Configuration

When session cookies are required, set `SameSite=None` and `Secure=true` because OpenAI plugins run inside cross-origin embedded frames. This configuration ensures cookies transmit only over HTTPS connections while allowing the cross-origin context necessary for ChatGPT integration.

### Credential Management

Store all API keys, client IDs, and secrets in environment variables (`process.env.*`) rather than hard-coding them in source files. The repository's general recommendations and Twilio skill manifests emphasize that credentials must never appear in client-side bundles or version control.

## Runtime Security and Dependency Hardening

### Automated Security Analysis

Use the **codex-security** skill to run automated security checks on pull requests. The validation script at [`/plugins/codex-security/scripts/validate_report_format.py`](https://github.com/openai/plugins/blob/main//plugins/codex-security/scripts/validate_report_format.py) provides linting capabilities that detect common vulnerabilities before deployment.

### Dependency Management

Regularly update third-party libraries to include the latest security patches. The Vercel next-forge starter notes recommend maintaining Node.js version 18 or higher and React 19.2+ to inherit recent security fixes.

### Secrets Leakage Prevention

Ensure no secrets appear in client-side JavaScript bundles. Deployment agents like Vercel's deployment-expert automatically flag environment variables that are inadvertently exposed to the client build.

## Platform-Specific Security Implementations

Different platforms require additional hardening measures:

- **Zoom**: Enforces OWASP headers, CSP frame-ancestors restrictions, PKCE flows, and webhook signature verification as detailed in [`/plugins/zoom/skills/zoom-apps-sdk/concepts/security.md`](https://github.com/openai/plugins/blob/main//plugins/zoom/skills/zoom-apps-sdk/concepts/security.md)
- **Twilio**: Requires credential hardening, signed webhook events, and IAM policies for HIPAA-compliant configurations per [`/plugins/twilio-developer-kit/skills/twilio-security-hardening/SKILL.md`](https://github.com/openai/plugins/blob/main//plugins/twilio-developer-kit/skills/twilio-security-hardening/SKILL.md)
- **Vercel**: Implements WAF protection, rate-limiting, and DDoS mitigation through the firewall skill at [`/plugins/vercel/skills/vercel-firewall/SKILL.md`](https://github.com/openai/plugins/blob/main//plugins/vercel/skills/vercel-firewall/SKILL.md)
- **Supabase**: Provides row-level security (RLS) and database access controls documented in the Supabase security skill

## Secure Coding Examples

### Express.js Security Headers

Implement OWASP-recommended headers in your Express middleware:

```javascript
app.use((req, res, next) => {
  res.setHeader('Strict-Transport-Security', 'max-age=31536000');
  res.setHeader('X-Content-Type-Options', 'nosniff');
  res.setHeader('Content-Security-Policy',
    "frame-ancestors 'self' zoom.us *.zoom.us");
  res.setHeader('Referrer-Policy', 'same-origin');
  next();
});

```

### Secure Session Configuration

Configure cross-origin compatible cookies for embedded plugin contexts:

```javascript
app.use(require('cookie-session')({
  name: 'session',
  keys: [process.env.SESSION_SECRET],
  maxAge: 24 * 60 * 60 * 1000,
  sameSite: 'none',
  secure: true,
}));

```

### PKCE Implementation

Generate code challenges using Node.js crypto:

```javascript
const crypto = require('crypto');

const verifier = crypto.randomBytes(32).toString('hex');
const challenge = crypto.createHash('sha256')
  .update(verifier)
  .digest('base64url');

req.session.codeVerifier = verifier;
res.json({ codeChallenge: challenge, state: req.session.state });

```

### CSRF State Validation

Protect OAuth callbacks against CSRF attacks:

```javascript
// Before redirect
const state = crypto.randomBytes(16).toString('hex');
req.session.oauthState = state;

// Callback validation
app.get('/auth', (req, res) => {
  if (req.query.state !== req.session.oauthState) {
    return res.status(403).send('Invalid state – possible CSRF');
  }
  // Continue token exchange...
});

```

### Server-Side Token Storage

Use Redis for secure token persistence:

```javascript
const Redis = require('ioredis');
const redis = new Redis(process.env.REDIS_URL);

async function storeTokens(userId, tokens) {
  await redis.set(`zoom:tokens:${userId}`, 
    JSON.stringify(tokens), 
    'EX', 
    tokens.expires_in);
}

```

## Summary

OpenAI plugins security requires comprehensive controls across multiple layers:
- Enforce **TLS 1.2+** and **OWASP security headers** on all endpoints
- Implement **PKCE** for OAuth flows and validate **state parameters** to prevent CSRF
- Store tokens and credentials **server-side only**, never in browser storage
- Configure cookies with `SameSite=None; Secure` for cross-origin embedding contexts
- Verify webhook signatures and request **least-privilege OAuth scopes**
- Update dependencies regularly and use automated security scanning via **codex-security**

## Frequently Asked Questions

### How should OpenAI plugins handle authentication tokens?

OpenAI plugins must store access and refresh tokens exclusively on the server side using encrypted databases or Redis. Never persist tokens in browser storage like `localStorage` or `sessionStorage`, as these are vulnerable to XSS attacks. According to the Zoom security documentation in the repository, tokens should be keyed to user IDs and set with explicit expiration times.

### What transport security requirements apply to OpenAI plugins?

All plugin endpoints must enforce HTTPS with TLS 1.2 or higher and implement strict transport security headers. The source code specifies that plugins must include `Strict-Transport-Security`, `X-Content-Type-Options`, and a restrictive `Content-Security-Policy` that limits frame ancestors to authorized platforms like Zoom or ChatGPT domains.

### How can developers prevent CSRF attacks in OAuth flows?

Developers should generate a cryptographically random `state` parameter before redirecting to the OAuth provider and validate it upon callback. The repository's Zoom implementation demonstrates returning a 403 status code if the state parameter mismatch indicates potential CSRF activity. Additionally, using PKCE (Proof Key for Code Exchange) prevents authorization code interception attacks.

### Are there specific security considerations for plugin dependencies?

Yes, the repository recommends maintaining Node.js 18+ and React 19.2+ to inherit recent security patches, and using the **codex-security** skill to run automated security checks on pull requests. Developers should also ensure no secrets leak into client-side bundles by properly scoping environment variables in `process.env`.