Static Documentation

Voice Provider Security

Version latest · Updated 2026-05-04
Interactive docs View on GitHub

Voice Provider Security#

Custom providers are executable Python code.

Only install providers from trusted sources.

Directory permissions#

Recommended permissions:

sudo mkdir -p /usr/local/lib/incidentrelay/voice_providers
sudo chown root:root /usr/local/lib/incidentrelay/voice_providers
sudo chmod 755 /usr/local/lib/incidentrelay/voice_providers

The providers directory must not be writable by:

  • the web server user;
  • the IncidentRelay application user;
  • untrusted users;
  • the IncidentRelay UI.

Secrets#

Do not hardcode secrets in provider files.

Bad:

api_token = "secret-token"

Good:

"provider_config": {
  "api_token": "${VOICE_API_TOKEN}"
}

Then configure the environment variable for the IncidentRelay service:

export VOICE_API_TOKEN="secret-token"

For systemd, use an environment file or service environment configuration.

Example:

Environment="VOICE_API_TOKEN=secret-token"

Logging#

Providers may log useful operational information, but must not log secrets or full phone numbers.

Good:

import logging

logger = logging.getLogger("oncall.voice")


def mask_phone(phone):
    if not phone:
        return None

    value = str(phone)

    if len(value) <= 4:
        return "****"

    return f"***{value[-4:]}"


logger.info(
    "placing voice call",
    extra={
        "extra": {
            "provider": self.name,
            "phone": mask_phone(request.phone),
            "alert_id": request.alert_id,
            "event_type": request.event_type,
        }
    },
)

Bad:

logger.info(f"calling {request.phone} with token {self.config['api_token']}")

Callback secrets#

Callback secrets should be unique and hard to guess.

Use channel-level secrets when possible:

{
  "callback_secret": "long-random-secret"
}

Avoid short secrets:

test
123
secret
change-me

Provider webhook signatures#

If your provider signs callbacks, validate the signature inside parse_callback().

Example:

def parse_callback(self, payload, headers=None, raw_body=None, query_args=None):
    signature = headers.get("X-Provider-Signature") if headers else None

    if not self._is_valid_signature(raw_body or b"", signature):
        raise RuntimeError("invalid provider callback signature")

    ...
- The providers directory must not be writable by the web server user.
- The providers directory must not be writable from the IncidentRelay UI.
- Provider files should be reviewed before installation.
- Secrets should be passed through environment variables.
- Provider logs must not contain API tokens, passwords or full phone numbers.
- Callback secrets should be unique and hard to guess.
- Provider-specific webhook signatures should be validated when supported.

Do not allow untrusted users to upload provider files.