> For the complete documentation index, see [llms.txt](https://docs.ebbot.ai/ebbot-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.ebbot.ai/ebbot-docs/developer-resources/ebbot-automations/integrations-sdk/security.md).

# Security

Workflow servers sit between the Ebbot platform and external systems. That makes them security-sensitive by default: they handle credentials, receive inbound events, and perform side effects in other systems.

This page summarizes practical security guidance for workflow servers built with this SDK, with extra focus on API keys, predictable actions and triggers, and common OWASP risks.

## Threat Model First

Before building an integration, identify:

* What secrets the server stores or forwards.
* Which endpoints accept inbound traffic from external systems.
* Which actions can create, update, or delete data.
* Which triggers can be abused to inject fake or replayed events.
* What happens if a connection is misconfigured or compromised.

The goal is simple: minimize trust, minimize blast radius, and make every side effect explicit.

## API Key Rules

Apply these rules to every API key or token your workflow server handles:

* Use the narrowest scopes possible. If an action only needs to read tickets, do not ask for write or admin scopes.
* Prefer short-lived credentials where the upstream system supports them, and have a rotation process for long-lived secrets.
* Keep track of which connection or tenant a credential belongs to, and log security-relevant usage without logging the secret itself.
* Protect secrets in transit and at rest: keep them in `Secrets`, not `Options`; use HTTPS; and never return secrets in action results, trigger payloads, logs, or error messages.

Practical guidance:

* Put confidential values in the `Secrets` model, never in `Options`.
* Do not hardcode API keys in source code, examples, tests, or local scripts.
* Do not copy secrets into trigger options, action arguments, or response payloads.
* Redact secrets from logs and exception messages.
* Treat dynamic field metadata with care: `info=` should not expose secret values in labels, descriptions, or options.

## Actions Without Hidden Surprises

An action should do exactly what its name and docs say it does.

Design actions so that they are:

* Explicit: the display name, description, docs, and argument docs should make the side effect obvious.
* Narrow: prefer `create_ticket` and `close_ticket` over a single vague `manage_ticket` action.
* Validated: enforce input schemas strictly and reject malformed or unexpected arguments.
* Bounded: cap payload sizes, pagination sizes, time windows, and batch sizes.
* Safe by default: avoid destructive behavior unless it is clearly intended and documented.

Avoid hidden surprises such as:

* A "lookup" action that also writes data.
* An action that mutates several remote resources when the user expects one change.
* Silent fallbacks to broader permissions, different tenants, or default resources.
* Returning raw upstream responses that may contain secrets or internal metadata.

Recommended action checklist:

* Document the exact side effect.
* Validate every argument with Pydantic models.
* Require only the specific `env` and `secrets` fields the action needs.
* Return a minimal result schema.
* Define clear error schemas for expected failures.
* Make retries safe where possible, or document when an action is not idempotent.

## Triggers Without Hidden Surprises

Triggers should only dispatch real, verified events.

For inbound webhook-style triggers:

* Authenticate the sender. Verify signatures, bearer tokens, shared secrets, or mTLS depending on what the upstream system supports.
* Reject unauthenticated requests before doing any expensive work.
* Protect against replay attacks with timestamps, nonces, delivery IDs, or equivalent upstream metadata.
* Validate the payload shape before dispatching.
* Dispatch only the fields subscribers actually need.
* Keep the payload stable and predictable. Subscribers should not have to guess which fields may appear.

For subscription setup:

* Use `Options` and `Secrets` only for values genuinely needed per subscription.
* If `events.on_created(...)` provisions upstream webhooks, ensure the callback URL is correct, scoped, and authenticated.
* Roll back cleanly if remote webhook registration fails.

For dispatch behavior:

* Make duplicate deliveries safe where possible.
* Do not dispatch secrets, raw access tokens, or internal-only metadata.
* Be careful with multi-tenant systems: resolve the correct subscription and tenant every time.

## Authentication and Authorization

Use defense in depth.

* Set `auth_token` on the workflow server when you need a shared bearer token protecting server endpoints.
* Use upstream-specific authentication for public webhook endpoints as well; a single shared token is often not enough for external-facing trigger routes.
* Authorize based on the specific connection or subscription in use, not just on the fact that a request reached your server.
* Do not trust client-provided tenant IDs, account IDs, or resource IDs without verifying they belong to the resolved connection.

## OWASP-Aligned Guidance

Workflow servers are typical API services, so the OWASP guidance for web apps and APIs applies directly.

Focus especially on these areas:

* Broken access control: verify that one connection cannot read, write, or trigger events for another connection.
* Cryptographic failures: require HTTPS, protect secrets, and avoid leaking confidential data.
* Security misconfiguration: disable debug settings in production, review CORS exposure, and avoid permissive defaults.
* Vulnerable and outdated components: keep FastAPI, Pydantic, and other dependencies updated.
* Identification and authentication failures: verify webhook signatures and protect internal endpoints.
* Software and data integrity failures: validate inbound payloads and be cautious with dynamic code, templates, and untrusted packages.
* Security logging and monitoring failures: log enough to investigate abuse, but never log secrets or sensitive payloads unnecessarily.
* SSRF and unsafe outbound calls: if your integration calls external URLs, restrict and validate destinations instead of proxying arbitrary user-provided URLs.
* Unsafe consumption of APIs: treat upstream systems as untrusted too. Validate responses before using or forwarding them.

## Secure Connection Modeling

When defining `Options` and `Secrets`:

* Keep `Options` for non-sensitive configuration such as `baseUrl`, region, or account identifiers.
* Keep `Secrets` for API keys, client secrets, refresh tokens, signing secrets, and similar credentials.
* Validate formats early. For example, restrict `baseUrl` to expected hosts or HTTPS URLs when possible.
* Avoid collecting more data than the integration needs.

Example:

```python
from pydantic import BaseModel, HttpUrl


class Options(BaseModel):
    baseUrl: HttpUrl


class Secrets(BaseModel):
    apiKey: str
```

## Logging and Error Handling

Good logs help incident response. Bad logs leak secrets.

* Log high-level events such as action execution, trigger receipt, and dispatch failures.
* Do not log tokens, API keys, authorization headers, or full webhook bodies unless there is a clear and safe reason.
* Return clear user-facing errors, but do not expose stack traces, upstream secrets, or internal configuration.
* Prefer explicit validation errors over mysterious downstream failures.

## Operational Practices

* Run production servers with `dev_mode=False`.
* Rotate compromised credentials immediately.
* Review which actions are destructive and who can install or invoke them.
* Add rate limits or upstream backoff where abuse or accidental loops are possible.
* Test failure cases: invalid signatures, wrong subscription IDs, missing secrets, replayed events, and upstream permission errors.
* Keep documentation current. Security depends on operators understanding what each action and trigger really does.

## Secure-by-Default Checklist

Before shipping a workflow server, confirm:

* Secrets are stored only in `Secrets`.
* Inbound trigger routes authenticate requests.
* Action and trigger schemas are explicit and validated.
* No secrets are exposed in results, payloads, docs, logs, or metadata.
* Each connection and subscription is properly isolated.
* Destructive actions are clearly named and documented.
* Production config uses HTTPS and disables development-only settings.
* Dependency updates and security reviews are part of normal maintenance.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.ebbot.ai/ebbot-docs/developer-resources/ebbot-automations/integrations-sdk/security.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
