API Tutorials

Lista de permissões de IP CaptchaAI e segurança de chave de API

Uma chave de API exposta em repositório público costuma ser achada por scanners automatizados em minutos — e a chave da CaptchaAI dá acesso direto ao seu saldo. Este guia mostra como armazenar a chave com segurança, restringir o acesso por IP e montar uma rotina de rotação.

Neste guia você vai:

  • Entender por onde as chaves costumam vazar antes que aconteça com você.
  • Configurar variáveis de ambiente e um .env fora do controle de versão.
  • Validar a chave com uma chamada real ao endpoint getbalance.
  • Montar uma rotação sem downtime, com chave secundária pronta.
  • Redigir a chave dos logs, do Docker e do pipeline de CI/CD.

Por onde as chaves de API costumam vazar

Scanners automatizados varrem repositórios públicos e imagens Docker publicadas por engano atrás de padrões como CAPTCHAAI_API_KEY=. O mapa abaixo resume os quatro caminhos mais comuns.

Exposed API key:
  ├── Leaked in Git repository
  ├── Hardcoded in client-side code
  ├── Shared in documentation
  └── Visible in logs

Impact:
  ├── Balance drained by unauthorized users
  ├── Usage spikes from abuse
  └── Key disabled by service provider

Qualquer um desses quatro caminhos basta para drenar o saldo. Trate a lista acima como checklist de auditoria, não como curiosidade.


Como armazenar a chave sem deixar rastro no código

A regra é simples: se a chave aparece em texto plano num arquivo versionado, ela já vazou — falta só alguém encontrar.

Nunca deixe a chave escrita no código-fonte

# BAD — key in source code
API_KEY = "abc123def456"  # DO NOT DO THIS

# GOOD — environment variable
import os
API_KEY = os.environ["CAPTCHAAI_API_KEY"]

# GOOD — .env file (not committed to Git)
from dotenv import load_dotenv
load_dotenv()
API_KEY = os.environ["CAPTCHAAI_API_KEY"]

Arquivo .env fora do controle de versão

# .env (add to .gitignore!)
CAPTCHAAI_API_KEY=your_api_key_here

.gitignore

# Always ignore .env files
.env
.env.local
.env.production

Gerenciadores de segredo para times maiores

Com várias pipelines e ambientes, um .env por máquina fica difícil de auditar. Ferramentas como AWS Secrets Manager ou HashiCorp Vault centralizam a chave e registram quem acessou — e a chave nunca deve aparecer em commits, mensagens de chat ou tickets de suporte.


Carregando a chave a partir do ambiente, com validação

A classe abaixo falha rápido se a chave não estiver definida, em vez de deixar o erro aparecer só na primeira chamada real.

import os


class CaptchaConfig:
    """Load CaptchaAI config from environment."""

    def __init__(self):
        self.api_key = os.environ.get("CAPTCHAAI_API_KEY")
        if not self.api_key:
            raise EnvironmentError(
                "CAPTCHAAI_API_KEY not set. "
                "Set it in your environment or .env file."
            )
        self.base_url = os.environ.get(
            "CAPTCHAAI_URL", "https://ocr.captchaai.com"
        )

    def validate(self):
        """Verify the API key works."""
        import requests
        resp = requests.get(f"{self.base_url}/res.php", params={
            "key": self.api_key,
            "action": "getbalance",
            "json": 1,
        }, timeout=10)
        data = resp.json()
        if data.get("status") != 1:
            raise RuntimeError(f"Invalid API key: {data.get('request')}")
        return float(data["request"])


# Usage
config = CaptchaConfig()
balance = config.validate()
print(f"Key valid, balance: ${balance:.2f}")

O validate() confirma três coisas antes de qualquer solve real:

  • Que a chave existe no ambiente.
  • Que o endpoint reconhece a chave.
  • Que o saldo retornado é maior que zero.

Rotação de chave: quando trocar e como não travar produção

Trate a rotação como rotina, não como resposta a incidente. Uma chave secundária configurada de antemão evita downtime na troca:

import os
import datetime


class KeyManager:
    """Manage API key rotation."""

    def __init__(self):
        self.primary_key = os.environ.get("CAPTCHAAI_API_KEY")
        self.secondary_key = os.environ.get("CAPTCHAAI_API_KEY_BACKUP")
        self.active_key = self.primary_key

    def get_key(self):
        return self.active_key

    def rotate(self):
        """Switch to secondary key."""
        if self.secondary_key:
            self.active_key = self.secondary_key
            print("Rotated to secondary key")
        else:
            print("No secondary key configured")

    def test_key(self, key):
        """Verify a key is valid."""
        import requests
        resp = requests.get("https://ocr.captchaai.com/res.php", params={
            "key": key, "action": "getbalance", "json": 1,
        }, timeout=10)
        return resp.json().get("status") == 1


# Usage
keys = KeyManager()

# If primary fails, rotate to secondary
if not keys.test_key(keys.get_key()):
    keys.rotate()

Um cronograma trimestral é um ponto de partida razoável; encurte para mensal se várias pessoas compartilham a mesma chave.

Rotacione imediatamente, fora do cronograma, quando:

  • A chave apareceu em um log, ticket ou repositório público.
  • Alguém saiu do time e tinha acesso a ela.
  • O saldo caiu de um jeito que não bate com o uso esperado.

Validando a requisição antes de enviar

Valide antes de enviar:

import requests
import logging

logger = logging.getLogger(__name__)


class SecureSolver:
    """Solver with security best practices."""

    def __init__(self, api_key):
        self.api_key = api_key
        self.base = "https://ocr.captchaai.com"

    def solve(self, method, **params):
        # Validate inputs
        self._validate_params(method, params)

        data = {"key": self.api_key, "method": method, "json": 1}
        data.update(params)

        # Log without exposing key
        logger.info(
            "Submitting %s solve for %s",
            method, params.get("pageurl", "unknown"),
        )

        resp = requests.post(
            f"{self.base}/in.php", data=data, timeout=30,
        )
        return resp.json()

    def _validate_params(self, method, params):
        """Prevent common security mistakes."""
        # Ensure pageurl is a valid URL
        pageurl = params.get("pageurl", "")
        if pageurl and not pageurl.startswith(("http://", "https://")):
            raise ValueError(f"Invalid pageurl: {pageurl}")

        # Ensure method is valid
        valid_methods = {
            "userrecaptcha", "turnstile", "geetest",
            "base64", "post", "bls", "turnstile_staging",
        }
        if method not in valid_methods:
            raise ValueError(f"Unknown method: {method}")

O que a validação evita

Sem essa checagem, uma pageurl mal formada chega ao in.php e consome uma tentativa de resolução à toa.


Logs que não vazam a chave

Redigir a chave nos logs também ajuda a manter a retenção de logs alinhada com a LGPD.

import logging
import re

logger = logging.getLogger(__name__)


class SafeFormatter(logging.Formatter):
    """Redact API keys from log messages."""

    KEY_PATTERN = re.compile(r'[a-f0-9]{32}', re.IGNORECASE)

    def format(self, record):
        msg = super().format(record)
        return self.KEY_PATTERN.sub("[REDACTED]", msg)


# Configure safe logging
handler = logging.StreamHandler()
handler.setFormatter(SafeFormatter("%(levelname)s: %(message)s"))
logger.addHandler(handler)
logger.setLevel(logging.INFO)

# Key is automatically redacted in logs
logger.info(f"Using key: abc123def456ghi789jkl012mno345pq")
# Output: INFO: Using key: [REDACTED]

Testando a redação em CI

Adicione um teste que grave um log com chave falsa e confirme que [REDACTED] aparece na saída.


Segredos em containers Docker

A chave embutida na camada de build fica exposta mesmo que o Dockerfile "pareça" limpo. Injete a chave em tempo de execução:

# Dockerfile — DO NOT embed keys here
FROM python:3.11-slim
WORKDIR /app
COPY . .
RUN pip install requests
CMD ["python", "solver.py"]
# docker-compose.yml
services:
  solver:
    build: .
    environment:

      - CAPTCHAAI_API_KEY=${CAPTCHAAI_API_KEY}
    # Or use Docker secrets:
    secrets:

      - captchaai_key

secrets:
  captchaai_key:
    file: ./secrets/captchaai_key.txt

O mesmo princípio vale em Kubernetes: chave como Secret via secretKeyRef, nunca como ConfigMap em texto plano.


Segurança no pipeline de CI/CD

Imagine uma scale-up com workers de automação autorizada em sa-east-1 na AWS: se a chave vazar de um notebook, ela funciona em qualquer região do mundo — a menos que a lista de permissões de IP esteja ativa.

GitHub Actions

# .github/workflows/test.yml
jobs:
  test:
    runs-on: ubuntu-latest
    steps:

      - uses: actions/checkout@v4
      - name: Run tests
        env:
          CAPTCHAAI_API_KEY: ${{ secrets.CAPTCHAAI_API_KEY }}
        run: python test_solver.py

Nunca deixe o segredo aparecer na saída do CI — nem em texto de erro, nem em echo de debug.

Outras plataformas de CI

O mesmo princípio vale fora do GitHub Actions: no GitLab CI use masked variables, no CircleCI use contexts. Em runners self-hosted compartilhados, confirme que o secret não fica em cache reutilizado entre jobs.


Erros comuns que levam ao vazamento em produção

A maioria dos vazamentos não vem de um ataque sofisticado — vem de um passo de higiene que ficou de fora da rotina.

  • Reaproveitar a mesma chave entre desenvolvimento, staging e produção.
  • Colar a chave numa mensagem de chat "só para testar rápido".
  • Deixar a lista de permissões de IP desativada porque "funciona sem ela".
  • Adicionar .env ao .gitignore só depois do primeiro commit, sem limpar o histórico.

Problemas comuns e como resolver

Os sintomas abaixo aparecem quando algo na configuração da chave já deu errado — use a correção como primeiro passo, antes de abrir um ticket de suporte.

Problema Causa Correção
ERROR_WRONG_USER_KEY Chave incorreta ou expirada Verifique a chave no painel da CaptchaAI
Drenagem inesperada de saldo Chave vazada ou compartilhada Rotacione a chave imediatamente, audite o acesso
A chave funciona localmente, mas não no CI Variável de ambiente não definida no runner Adicione a chave aos segredos do CI/CD
Chave aparece no histórico do Git Arquivo .env foi commitado por engano Rotacione a chave, adicione .env ao .gitignore, limpe o histórico com git filter-branch

Checklist de segurança antes de ir para produção

Marque cada item antes do primeiro deploy em produção e revisite a lista a cada rotação de chave.

Prática Status
Chave de API em variável de ambiente
.env adicionado ao .gitignore
Nenhuma chave no código-fonte
Chaves redigidas nos logs
CI/CD usa gerenciador de segredos
Cronograma de rotação de chaves definido
Monitoramento de saldo ativo

Perguntas frequentes

O que fazer se minha chave de API vazar?

Gere uma nova chave no painel da CaptchaAI, revogue a antiga e verifique o saldo em busca de uso não autorizado.

Como faço a rotação da chave sem interromper os workers em produção?

Configure uma chave secundária antes de precisar dela. Ative-a, confirme que os workers respondem e só então revogue a antiga.

É possível restringir a chave de API por IP no painel da CaptchaAI?

Consulte as configurações de restrição de IP e coloque na lista de permissões apenas os IPs dos seus servidores de produção.

Como evito que a chave apareça nos logs da aplicação?

Use um formatter que redija padrões de chave antes de gravar a mensagem, como no exemplo de SafeFormatter acima.

Vale a pena usar um gerenciador de segredos em vez de variáveis de ambiente no CI/CD?

Para times pequenos, variáveis de ambiente do CI já resolvem. Com várias pipelines compartilhando a mesma chave, um gerenciador dedicado facilita a rotação e a auditoria.


Guias relacionados


Proteja seu investimento — proteja sua chave de API da CaptchaAI hoje mesmo.

Os comentários estão desativados para este artigo.