Overview
Formal policies can enforce different actions at three evaluation stages: session, request, and response. Each stage has specific actions available based on when the policy is evaluated.Evaluation Stages
Session
When: Connection establishment and, for SSH and Kubernetes exec, while
the session runs Actions:
allow, block, mfa, quarantine,
suspend, impersonate Use for: Authentication, connection-level access
control, reacting to session monitorsRequest
When: Before query reaches resource Actions:
allow, block,
rewrite, decrypt Use for: Query validation, SQL rewriting, blocking writes, decrypting secrets for the upstreamResponse
When: After data returns from resource Actions:
allow, block,
filter, mask, encrypt, rewrite Use for: Data masking, PII redaction, filtering results, encrypting secrets before they leaveCommon Action Parameters
All actions support these parameters:Block Action
Deny access and terminate the connection or query.Parameters
block_with_formal_message returns Formal’s default block text. That message includes the policy ID plus the session ID and request ID when they are available, so users can share those identifiers with their security team.
Example
Suggest approved MCP alternatives
Usemcp_suggest_alternatives to block an unapproved MCP server and tell the AI agent what to do next. The block message becomes an advisory written for the agent. It lists the MCP resources you have registered in Formal, excluding the blocked one.
The advisory tells the agent to ask the user to choose one of these options:
- Switch to one of the approved MCP servers.
- Request the blocked server. The agent looks for a form about MCP requests with
formal form listand submits it withformal form fill. - Do nothing for now.
message when it builds the advisory. If the advisory cannot be built, Formal returns message, or a short default text when message is empty.
This policy blocks tool calls to MCP servers that have no Formal resource, such as servers the Formal Endpoint intercepts on a laptop. It is the policy that the Block unknown MCPs control on the Guardrails page generates.
Allow Action
Explicitly permit an operation. Use in combination with default deny policies.Example
Rewrite Action
Modify a SQL query before it reaches the resource, or modify an HTTP request or response in transit.Parameters
HTTP-based resources include HTTP, LLM, and MCP resources.
When several active policies rewrite the same message, Formal applies all of their header rewrites. If more than one sets a body, only one of them takes effect. Scope policies so that body rewrites don’t overlap.
Example
Example: Rewrite LLM request headers
Example: Redact SSNs from LLM request bodies
String-replace sensitive values in the outbound LLM body so coding agents can continue without sending SSNs upstream. Preferbody rewrites over blocking the session when the goal is redaction.
Filter Action
Remove rows from the result set based on conditions.Example
Mask Action
Redact or obfuscate sensitive data in responses.Parameters
With type safety on, Formal keeps typed columns valid, such as numbers, booleans, dates, JSON, and UUIDs.
nullify, redact, the hash subtypes, and reduce_decimal_precision keep their output when the column’s type can hold it. Every other mask on a typed column returns the fallback:
fallback_to_nullreturnsNULL.fallback_to_defaultreturns a placeholder such as0,{}, or an all-zero UUID. Boolean columns getNULLinstead.
Formal turns on type safety only when
typesafe_fallback is set. A typesafe
key on its own has no effect.Masking Types
type and sub_type do different jobs. type only sets the privacy level. sub_type picks the function that transforms the value. When you omit sub_type, Formal uses type as the subtype. That shortcut works for nullify, hash.with_salt, hash.no_salt, and redact.constant_characters. fake and redact.partial always need an explicit sub_type.
Masking Subtypes
Subtypes that end in_with_fake replace the value with a random fake value of the same kind. Pair them with type: "fake". Pair the partial subtypes, such as the email and character-level ones, with type: "redact.partial".
Redaction, hashing, and numbers
Redaction, hashing, and numbers
redact.constant_characters: Replace the value withredactredact: Replace the value withredact. With type safety on, keepsredactwhen the column’s type can hold it, such as-1in an integer columnreplace_characters_with: Replace every character withredact. With"redact": "*",secretbecomes******redact.first_n_characters: Replace the firstcharacters_countcharacters. With"redact": "*"and a count of 3,hellobecomes***loredact.last_n_characters: Replace the lastcharacters_countcharacters. With"redact": "*"and a count of 3,hellobecomeshe***mask_everything_except_last: Replace every character except the last one. With"redact": "*",sensitivebecomes********e. This subtype ignorescharacters_countnullify: ReturnNULLhash.no_salt: Hash the value. The same input always gives the same output, so joins still workhash.with_salt: Hash the value with a random salt. The output changes on every readreduce_decimal_precision: Truncate toprecisiondigits after the decimal point. With a precision of 2,123.456becomes123.45. Non-numeric values are unchanged
Email
email_mask_username:jane@example.combecomes****@example.comemail_mask_domain_name:jane@example.combecomesjane@*******.com. The masked domain is always*******.comemail_mask_while_preserving:jane@example.combecomesj***@e******.comemail_mask_with_fake: Random fake email address
* when the value isn’t an email address.Personal information
Personal information
person_full_name_mask_with_fakeperson_first_name_mask_with_fakeperson_last_name_mask_with_fakeperson_gender_mask_with_fakeperson_ssn_mask_with_fakephone_mask_with_fake
Location
Location
postal_address_mask_with_fakecity_mask_with_fakestate_mask_with_fakecountry_mask_with_fakezip_mask_with_fakelocation_mask_except_state_country: Keep only the US state and the country from a comma-separated address.1 Main St, Springfield, IL, USAbecomesIL, USA
Payment
Payment
payment_credit_card_number_mask_with_fakepayment_credit_card_cvv_mask_with_fakepayment_credit_card_exp_mask_with_fakepayment_credit_card_type_mask_with_fakepayment_currency_with_fakepayment_ach_routing_with_fakepayment_ach_account_with_fakepayment_bitcoin_address_with_fakepayment_bitcoin_private_key_with_fake
Network
Network
network_url_mask_with_fakenetwork_domain_mask_with_fakenetwork_ipv4_mask_with_fakenetwork_ipv6_mask_with_fakenetwork_mac_mask_with_fake
Company
Company
company_name_with_fake
Character-level subtypes repeat
redact once per masked character. If
redact is empty, those characters are removed instead of replaced. Always
set redact, for example to "*".Examples
Mask email usernames:Encrypt & Decrypt Actions
Encrypt and decrypt sensitive HTTP values in-line, so plaintext secrets never reach places that should not see them. Formal encrypts secrets on the way out and decrypts them on the way back in, so tokens stay protected end to end.- The
encryptaction on the Formal Endpoint is only available on macOS. - The
encryptaction on the Connector requires configuring a cloud KMS key for token encryption. See Token Encryption for more information.
decryptruns at the request stage. It decrypts Formal-encrypted values before the upstream receives them. If a value fails to decrypt, the request is forwarded unchanged.encryptruns at the response stage. It encrypts values before they leave the proxy. If encryption fails, the response is blocked.
Parameters
Each target is an object:
Example: Encrypt tokens in a response
Example: Decrypt a request header for the upstream
MFA Action
The MFA action requires device-owner verification before proceeding with the connection. When a policy returns themfa action, the Formal Endpoint prompts for device-owner verification before the connection proceeds. On macOS this is Touch ID or the device passcode. On Windows this is Windows Hello (fingerprint, facial recognition, or PIN).
When a Connector evaluates the policy, it raises the challenge in the Control Plane and waits. The user’s Formal Endpoint picks up the challenge and shows the prompt. The user needs the Endpoint running to answer it.
Parameters
If verification fails or times out, Formal blocks the connection with
MFA authentication failed or timed out. Please try again.
Example
Quarantine Action
Stop a user who shows high-risk behavior.quarantine is a session-stage action for SSH and Kubernetes exec sessions. It is usually paired with session monitors, which re-evaluate session policies while the session runs.
What happens depends on when the rule matches:
- While a session runs: Formal ends every active session of the user and blocks the user. Blocked users can’t open SSH, Kubernetes, or RDP sessions until an admin unblocks them.
- When an SSH session starts: Formal refuses that session. The user is not blocked.
Parameters
To unblock a user, go to Users, open the user, and click Unblock User. Blocked users show a Blocked badge. You can also block a user manually with Block User.
Example
Suspend Action
End one session without blocking the user.suspend is a session-stage action for SSH and Kubernetes exec sessions.
- While a session runs: Formal ends that session. The user can reconnect.
- When an SSH session starts: Formal refuses that session.
Parameters
Example
Impersonate Action
Run Kubernetes API requests as the end user instead of the Connector’s identity.impersonate is a session-stage action for Kubernetes resources. Formal adds the Impersonate-User and Impersonate-Group headers to each request it forwards.
Parameters
Example
Rule Conflicts and Precedence
When multiple policies apply to the same query, Formal resolves conflicts using least privilege:Example of Conflict Resolution
Scoping Policies with Connectors, Resources, Spaces, and Technologies
To prevent policy conflicts when using thedefault keyword, limit which Connectors, Resources, Spaces, or technologies a policy applies to.
Include/Exclude Connectors
Useincluded_connectors to apply a policy only to specific connectors:
excluded_connectors to exclude specific connectors:
Include/Exclude Resources
Useincluded_resources to apply a policy only to specific resources:
excluded_resources to exclude specific resources:
Include/Exclude Spaces
Scoping by Space covers every Connector and Resource the Space contains. Useincluded_spaces to apply a policy only to specific Spaces:
excluded_spaces to exclude specific Spaces:
Connectors that belong to no Space are never in scope for
included_spaces,
and are always in scope for excluded_spaces.Include/Exclude Technologies
Useincluded_technologies or excluded_technologies to scope a policy by the Resource’s technology identifier, such as postgres, ssh, or llm: