{P}eelOpsBETA
SecurityTrustArchitecture

How We Protect Your API Keys and Credentials

{P}eelOps Team
Dec 1, 2025
5 min read

Let's talk about the elephant in the room.

You're about to hand us your Okta API token. Your AWS access keys. Your Cloudflare credentials. The same credentials that, in the wrong hands, could read every user in your directory, spin up crypto miners in your cloud account, or take down your CDN.

That takes trust. And you probably want to know exactly what happens to those credentials before you click "Connect."

Fair. Here's the full picture.


The 30-Second Version

If you're short on time:

  • AES-256-GCM encryption - Same standard banks use. Your credentials are encrypted before they touch our database.
  • Never stored in plaintext - Not temporarily, not for debugging, not ever.
  • Encryption keys stored separately - A database breach alone can't expose your credentials.
  • Authenticated encryption - If anyone tampers with the data, decryption fails.

If you want the details (or your security team is asking), keep reading.


What Actually Gets Encrypted

When you connect a service, here's what we store:

Connection TypeWhat's Encrypted
OAuth2 (Okta, etc.)Access tokens, refresh tokens, expiry timestamps
API Keys (AWS, Cloudflare, etc.)API keys, secret keys, account identifiers
AI ConfigurationYour OpenAI API key

Everything sensitive. Encrypted. Always.


How the Encryption Works

We use AES-256-GCM. If you're not a crypto nerd, here's what that means in plain English:

Your Credentials Never Exist Unencrypted in Storage

The moment you save a connector, your credentials are encrypted before being written to the database:

Your API Key → Encryption → Unreadable bytes → Database

What's actually stored looks like this:

v1:a3f2b1c4d5e6f7a8:9b8c7d6e5f4a3b2c:x9y8z7w6v5u4t3s2r1q0...

Version, initialization vector, authentication tag, encrypted blob. Without the encryption key, it's garbage.

Same Key, Different Output Every Time

Even if you stored the same API key twice, the encrypted output would be different. We use a random initialization vector (IV) for every encryption.

Why? So attackers can't spot patterns like "these two encrypted values are identical, so the underlying credentials must be the same."

Tampering Gets Caught

AES-256-GCM is authenticated encryption. If anyone modifies even a single bit of the encrypted data, decryption fails completely.

We don't just encrypt your data. We verify it hasn't been touched.


The Key Question: Where's the Encryption Key?

This is what actually matters.

The encryption key lives in an environment variable. Completely separate from the database.

Why this matters:

Attack ScenarioWhat They Get
Database breach (SQL injection, backup theft, insider)Encrypted blobs. Useless without the key.
Application server compromiseHarder attack, plus additional protections (key loaded at runtime, tight access controls, monitoring)

No single breach exposes everything. That's defense in depth.


OAuth Token Handling

OAuth tokens are trickier because they expire and refresh. Here's our flow:

  1. You authorize {P}eelOps with Okta (or another provider)
  2. We receive access and refresh tokens
  3. Both encrypted immediately before storage
  4. When we need to call the API, we decrypt the access token in memory
  5. If expired, we use the refresh token to get a new one
  6. New tokens encrypted immediately before storage

At no point are tokens stored unencrypted, written to logs, or exposed in error messages.


What We Don't Do

Let's be explicit:

We don't log credentials. Not in application logs, not in error reports, not in any analytics. If something fails, we log "credential decryption failed" - not the credential itself.

We don't store plaintext "temporarily." No "just for debugging." No "we'll encrypt it later." Encryption happens immediately or not at all.

We don't send credentials anywhere unnecessary. Your API keys leave our servers only to call the APIs they're meant for. That's it.

We don't share credential data. No analytics providers, no third parties, no exceptions.


Your Account Security

Your credentials are only as safe as your {P}eelOps account. Here's how we protect that:

Password Requirements

  • Minimum 12 characters
  • Uppercase, lowercase, numbers, special characters required
  • Common passwords blocked (no "Password123!")

Brute Force Protection

  • 5 failed attempts triggers 30-minute lockout
  • Email notification when lockout occurs
  • Rate limiting on all auth endpoints

Session Management

  • Sessions tracked and revocable
  • Force logout from all devices available
  • Configurable session duration

Team Permissions

  • Role-based access (Owner, Admin, Member)
  • Only Owners and Admins can access connector configurations
  • Members can run commands but never see credentials
  • Activity logging for audit trails

The Bottom Line

When you connect Okta, AWS, Cloudflare, or any service to {P}eelOps:

  1. Your credentials are encrypted with AES-256-GCM immediately
  2. Encryption keys are stored separately from your data
  3. Tampering is detected and rejected
  4. We never log, expose, or share your credentials
  5. Your account is protected by real security controls

We're asking for your trust. We take that seriously.


Questions?

If your security team needs more details, or you have specific compliance questions, reach out. We're happy to go deeper.

This isn't a "set it and forget it" feature. We think about credential security every time we ship code. Because we know what's at stake.

Enjoyed this post?

Subscribe to get new posts and product updates delivered to your inbox.