ExMCP.Security.CORS (ex_mcp v0.9.2)

View Source

Handles Cross-Origin Resource Sharing (CORS) logic.

This module is responsible for validating request origins and building appropriate CORS headers for responses.

Summary

Functions

Builds CORS headers based on configuration.

Validates origin header against allowed origins.

Validates request origin against security policy.

Types

auth_method()

@type auth_method() ::
  {:bearer, token :: String.t()}
  | {:api_key, key :: String.t(), opts :: keyword()}
  | {:basic, username :: String.t(), password :: String.t()}
  | {:custom, headers :: [{String.t(), String.t()}]}
  | {:oauth2, map()}

cors_config()

@type cors_config() :: %{
  optional(:allowed_origins) => [String.t()] | :any,
  optional(:allowed_methods) => [String.t()],
  optional(:allowed_headers) => [String.t()],
  optional(:expose_headers) => [String.t()],
  optional(:max_age) => integer(),
  optional(:allow_credentials) => boolean()
}

security_config()

@type security_config() :: %{
  optional(:auth) => auth_method(),
  optional(:headers) => [{String.t(), String.t()}],
  optional(:validate_origin) => boolean(),
  optional(:allowed_origins) => [String.t()],
  optional(:cors) => cors_config(),
  optional(:tls) => tls_config()
}

tls_config()

@type tls_config() :: %{
  optional(:verify) => :verify_peer | :verify_none,
  optional(:cacerts) => [binary()],
  optional(:cert) => binary(),
  optional(:key) => binary(),
  optional(:versions) => [atom()],
  optional(:ciphers) => [String.t()]
}

Functions

build_cors_headers(cors_config, origin \\ nil)

@spec build_cors_headers(cors_config(), String.t() | nil) :: [
  {String.t(), String.t()}
]

Builds CORS headers based on configuration.

validate_origin(origin, allowed_origins)

@spec validate_origin(String.t() | nil, [String.t()] | :any) ::
  :ok | {:error, :origin_not_allowed}

Validates origin header against allowed origins.

Examples

iex> ExMCP.Security.CORS.validate_origin("https://example.com", ["https://example.com"])
:ok

iex> ExMCP.Security.CORS.validate_origin("https://evil.com", ["https://example.com"])
{:error, :origin_not_allowed}

validate_request_origin(origin, config)

@spec validate_request_origin(String.t() | nil, security_config()) ::
  :ok | {:error, :origin_validation_failed}

Validates request origin against security policy.

This implements DNS rebinding attack protection as required by the MCP spec.