Skip to content

Enforcement policy

Everything Shield360 enforces lives in one place: Govern → Policies & rules → Policies. The organisation sets a policy once, and it applies to every project and environment. An environment can override any single setting, and everything else keeps following the organisation.

The same policy drives every enforcement point:

ChannelWhat enforces it
BrowserThe Shield360 browser extension, on AI chat sites in managed Chrome and Edge
AI proxyThe AI proxy on a machine, in a container, or hosted by Shield360
Coding agentsThe hooks the collector installs in Claude Code, Cursor, Codex and other coding agents

Govern → Policies & rules → Policies is one scrolling page with a section for each part of the policy, a What can block right now strip at the top, and one Save for the whole page. See the Policies overview for what every setting does and how developers get unblocked. Violations have their own page, linked as Violations at the top of the Policies page. Older ?tab= links redirect to the matching section.

SectionWhat it sets
Sensitive dataWhat each channel does when a prompt, file or tool call holds a kind of sensitive data, whether a warned person may send anyway, failing closed, and files uploaded to AI sites
AI toolsWhich AI tools people may open or call: allow, warn or block per tool, with a default. Your own AI sites (internal portals and unlisted public sites). Also what the AI proxy does with a model outside the approved list
Coding agentsSecret files, what agents may edit, expensive patterns and prompt injection
Sequence policiesRules over the order of what agents do

Deployment and collection stay under Settings → Data collection → Deployment: install keys, the extension and proxy set-up panels, what the collector gathers (collection policy), approved models and the ingest pipeline. That page shows a summary of the enforcement policy with links to each section.

Groups from your directory, and named people, can have their own policy on top of this one: see People and groups. Per-person narrowing in the collection policy is separate: it only lowers what is collected about someone, never what is enforced.

Organisation default and environment overrides

Section titled “Organisation default and environment overrides”

The Editing switch at the top of the page chooses what the Sensitive data, AI tools and Coding agents sections edit:

  • Organisation default: the policy for every environment in the organisation.
  • Overrides for project / environment: the current project and environment (from the header). Each setting shows Inherited or Overridden. Change a setting to override it, and use its reset control to inherit the organisation’s value again. Remove all overrides puts the environment back on the organisation default.

What applies to an environment is the organisation’s policy with that environment’s overrides on top. A change to the organisation default reaches every environment that does not override that setting.

The People and groups section gives a directory group, or one person, its own policy on top of the organisation default and the environment’s overrides. Use it for exceptions such as “Engineering may use Claude, everyone else may not” or “contractors may not send anyway”.

  • Group: a group synced from your identity provider over SCIM. Until SCIM is connected there are no groups to choose, and you can still add people by name.
  • Person: an account name (jdoe, or ACME\jdoe) or an e-mail address. Names are matched without case and without a Windows domain.

A group or person policy sets only what it changes; every other setting follows the environment and the organisation. It can set what each channel does with sensitive data, which AI tools are allowed, Let people send anyway, failing closed, approved models, prompt injection and file uploads. Your own AI sites and coding-agent edit rules stay organisation and environment settings.

What applies to one person:

  1. Each targeted group they are in, on top of the environment’s policy. When they are in several, the strictest applies, so a contractor who is also in Engineering does not get Engineering’s exception.
  2. Their own policy, which wins over their groups.
  3. Nothing targeted: the environment’s policy, as before.
Enforcement pointWhose policy it enforces
Browser extensionThe browser’s signed-in profile e-mail, recorded by Shield360 when the extension enrolled. Nothing the browser sends later can change it.
Collector and coding-agent hooksThe accounts signed in on the computer, or the account it enrolled as. With several people on one computer, the strictest of them applies, because the hooks cannot tell people apart.
AI proxyThe environment’s policy. A proxy serves many people.

An account name reaches your directory through the SCIM user name or the person’s Shield360 e-mail, through a company AI account e-mail the collector read for that account (for example a company Claude Code login), or through the part before the @ when exactly one directory user has it. A name the directory does not know still gets a person policy set for that name.

Changes take effect on each device’s next policy fetch, and within 30 seconds on every Shield360 server. Each group or person policy is saved on its own and goes through change control like the rest of the page: a freeze stops it, a required comment must be given, and with approval required it waits for a second person. Every change is in the audit log.

Group and person policies are in the organisation export (postgres/enforcement_targets.ndjson). A person’s own policy is in their personal-data export, and erasing the person deletes it, so they follow their groups and the organisation again.

The table has a row for each kind of sensitive data (API key, private key, password, connection string, Social Security number, payment card, access token, cloud credential, email address, phone number, IBAN, IP address) and a default row. Its columns are All channels, Browser, AI proxy and Coding agents. Each cell is one of:

ActionWhat happens
OffNothing is done.
WarnThe person is warned. Where Let people send anyway with a reason is on, they can send it after giving a reason, which is recorded.
MaskEach value is replaced with a placeholder (such as [EMAIL_1]) and the prompt is sent.
BlockThe prompt, file read or tool call is stopped.

A cell left on Inherit follows the next setting down. What one channel does with one kind is the most specific value that is set:

  1. the channel’s value for the kind
  2. the channel’s default
  3. the kind in All channels
  4. the All channels default

When several kinds are found in one prompt, the strictest action applies. Each cell shows what applies after this, and a preview line below the table spells it out for one kind, for example: A payment card in a ChatGPT prompt → Blocked; through the AI proxy → Blocked; in Claude Code → Warned.

Coding agents cannot mask. A prompt has already been handed to the agent when the hook sees it, so there is nothing to rewrite. Mask is not offered in the Coding agents column, and the server refuses it there with 400. Where the coding agents inherit a mask from All channels, they enforce it as Block, so the value still never reaches the model.

The coding-agent hooks used to check only credentials, Social Security numbers and payment cards. So the default policy sets email, phone, IBAN and IP address to Off for coding agents, which keeps them out of code reviews and logs where they are usually noise. You can see and change that in the Coding agents column.

Below the table, Your own kinds of data adds kinds the built-in list does not cover, by keywords or by fixed formats (see Policies for how they match). Each one is a row of the table, marked Yours, and its cells resolve exactly like a built-in kind’s: the channel’s value, the channel’s default, the kind in All channels, then the All channels default. A kind with no cells of its own therefore does whatever the defaults do. Removing a kind removes its cells at the scope you are editing.

The list is one setting. An environment that overrides it uses its own list instead of the organisation’s; reset it to use the organisation’s again.

  • Let people send anyway with a reason: when a prompt is only warned about, the person may send it after giving a reason. It applies to the browser extension and the AI proxy.
  • Block when the policy is unavailable: when a machine, browser or proxy cannot read its policy, refuse instead of allowing. It is available when some channel blocks a kind of data. How coding agents behave then is described in the collection policy.

The browser extension checks files people pick, drag or paste into an AI site, on every site it protects (the built-in AI tools and your AI sites). The file is held before the site sees it:

  • Text files (text, Markdown, CSV, JSON, logs, source code, configuration and key files, and any other file whose start is plain text) and Word, PowerPoint and Excel documents (.docx, .pptx, .xlsx and their macro and template variants) are read on the device and checked with the Browser column above. The strictest action among the files applies. Mask cannot change a file, so it blocks the upload, and the value still never reaches the site. Warn asks the person to confirm, with a reason when Let people send anyway with a reason is on.
  • Files that cannot be checked are PDFs, older Office formats (.doc, .xls), images, archives, audio and video, and any file over 10 MB. The setting Files that cannot be checked decides what happens to them: Off (the default) lets them through, Warn asks the person to confirm, Block stops the upload. Text inside images and scanned PDFs is not read.
  • Check the text of uploaded files is on by default. When it is off, no file is read, and every upload is treated as one that cannot be checked.

A file never leaves the device. A warned or blocked upload is recorded as a guard decision with target file: the file’s type (its extension), its size as a range (under 10 KB, 10–100 KB, 100 KB–1 MB, 1–10 MB, over 10 MB), whether it could be read, the kinds of data found and the decision. The file name and the content are not recorded. A file that goes through counts in the interaction record as an attachment type, as before.

Each AI chat tool (ChatGPT, Claude, Gemini, Microsoft Copilot, Perplexity and others) can be allowed, warned about or blocked when someone opens it in a managed browser or calls it through the AI proxy. Other AI tools sets the default for everything not listed.

The collector still reports use of AI tools and sites it recognises (shadow AI) on every enrolled computer, including tools this policy does not list and places where nothing can enforce it. See Shadow AI.

Your AI sites adds sites to the browser extension’s coverage: your organisation’s own AI portals (for example ai.corp.example.com) and public AI sites the list above does not name. Each site is allowed, warned about or blocked when someone opens it, like a listed tool. On every site that is not blocked, the extension also checks prompts and file uploads with the Browser column of the sensitive-data policy.

An entry is a host name, a wildcard subdomain pattern or an IPv4 address:

EntryCovers
ai.corp.example.comThat host and every subdomain of it, on any port, over HTTP or HTTPS
*.corp.example.comcorp.example.com and every subdomain of it
10.20.30.40That address only

The server refuses, with 400 and a reason, an entry that:

  • has a scheme, path, query, port or user name (https://…, …/chat, …:8443)
  • has a wildcard anywhere but the front, or a wildcard over an address
  • is a single label (intranet, *.com)
  • equals a public suffix or shared hosting domain, or is a wildcard over one (co.uk, *.github.io, *.vercel.app)
  • is, or covers, an AI tool already in the list (chat.openai.com, *.google.com). Set that tool’s action instead.
  • repeats another entry

The list holds up to 50 sites. It is one setting: an environment that overrides it replaces the whole list for that environment. Changes are recorded in the audit log with the list before and after.

Prompts on your AI sites are found with a generic adapter: the extension takes the text field the person last typed in (or the most chat-like visible field), and the nearest button labelled to send or submit. Enter, the send button and form submission are all checked. A portal whose send control has no label is still covered by Enter and form submission. You.com, Character.AI and Google AI Studio, which are in the list above but have no adapter of their own, use the same generic adapter.

Personal or other organisation’s account sets what happens when an AI tool is signed in to a personal account or another organisation’s instead of the company’s. What counts as the company’s is what you entered in Settings → Data collection → AI account settings: approved Anthropic organisations, ChatGPT workspaces, Cursor teams and email domains. See AI account identity.

SettingWhat happens
Off (default)Any account is allowed. Accounts are still detected and reported.
WarnThe person is told their account is not the company’s, and the prompt is recorded as a violation. In the browser they confirm before sending (with a reason, when Send anyway is on). Coding agents warn once per session and carry on.
BlockPrompts from a personal account are stopped. The browser extension and the AI proxy also add the vendor’s tenant restriction header, so the vendor itself refuses any account outside your approved organisations and workspaces.

Where each client enforces it:

ClientDetectsUnder Block
Browser extension, ChatGPT and ClaudeA personal plan (Free, Plus, Pro, Max, Go) the page shows next to the accountStops prompts and uploads; sets ChatGPT-Allowed-Workspace-Id on chatgpt.com and anthropic-allowed-org-ids on claude.ai, claude.com and anthropic.com
Browser extension, Microsoft Copilotcopilot.microsoft.com signs in with personal Microsoft accounts only, so every prompt there is from a personal accountStops prompts and uploads. Microsoft 365 Copilot is always a work account and is not affected.
AI proxyNothing on its ownSets anthropic-allowed-org-ids on requests to Anthropic, including API keys. Sets ChatGPT-Allowed-Workspace-Id only on an upstream on chatgpt.com; the OpenAI API ignores it.
Claude Code and Codex hooksThe account in ~/.claude.json or ~/.codex/auth.json, classified as on the AI accounts pageStops every prompt until the developer signs in with a company account

An account that cannot be identified is allowed (fail open): an API key in a coding agent, a page that does not show its plan, Gemini, and every other site. Warned and blocked prompts appear under Violations as AI-tool decisions. They record the kind of account (personal or other_org), never the email or the organisation.

Outside the approved list sets what the AI proxy does with a request for a model or provider that is not on the environment’s approved list (Approved AI providers and models under Settings → Data collection → Deployment):

SettingWhat happens
Off (default)Nothing is checked.
WarnThe request is forwarded and recorded as a violation.
BlockThe request is refused with 403 and the error code model_not_approved, and recorded as a violation.

The proxy checks each request as the approved list defines it. A provider is approved as a whole unless models are listed; a listed model matches by name, and * matches any run of characters. A request that names no model is decided by its provider. Nothing is checked in an environment whose approved list is off.

Warned and blocked requests appear under Violations as Unapproved models, and raise a models.unapproved_use alert, one per model and outcome in each hour. To send it to a channel, add an Alerts raised by features rule for the kind Unapproved model under Detect & respond → Alerts → Alert rules. The alert names the model and the client, never the person or the computer.

The browser extension does not see which model a chat site uses, so it enforces the AI tools settings only. Coding-agent hooks do not enforce the list yet.

  • Also check files the agent reads: stop reads of secret files (.env, private keys, credential files) and of files holding sensitive data. It takes effect when coding agents warn about or block some kind of data.
  • What coding agents may change: protected paths and expensive patterns. See Privacy & Governance.
  • Prompt injection: for coding agents and the MCP gateway, and the optional model check. See Prompt injection.
  • Reading the policy needs View agent policies.
  • Changing the organisation default, an environment’s overrides, or a group or person policy needs both Manage agent policies and Change what is collected. Change what is collected is the permission these settings needed before they moved.
  • The server enforces this. The screen only disables what you cannot change.
  • Every change is written to the audit log. The record names the setting keys that changed, with their values before and after: compliance.enforcement_policy.update, compliance.enforcement_policy.override.update, compliance.enforcement_policy.override.delete, and for group and person policies compliance.enforcement_policy.target.update and compliance.enforcement_policy.target.delete. The policy holds no secrets.
  • A self-hosted deployment whose licence is read-only refuses changes, like any other configuration. Enforcement carries on.

Browsers, collectors and local proxies fetch their policy from GET /api/collector/device/policy, and the hosted proxy is answered by its resolve route. Every one of them is given the effective policy of its own environment, and browsers and collectors that of the people on them when a group or person policy applies (see People and groups). The response keeps every field it had, with the same names and meanings, and adds new ones:

FieldMeaning
aiGuard, aiGuardKindsThe browser’s default and per-kind actions (unchanged meaning)
proxyGuard, proxyGuardKindsNew: the AI proxy’s default and per-kind actions. Your own kinds of data are not in proxyGuardKinds; the proxy reads them, with their proxy action, from customDataKinds, and masks them with placeholders such as [CUSTOM_EMPLOYEE_ID_1]. The hosted proxy is handed these as its aiGuard and aiGuardKinds. A local proxy uses them when present.
agentGuardKindsNew: the coding agents’ action for every kind (off, warn or block)
agentGuardThe strictest of agentGuardKinds, for hooks that predate per-kind actions
aiTools, aiWarnOverride, guardFailClosed, agentGuardFiles, editPolicy, injectionMode, gatewayInjectionMode, injectionLlmCheckAs before
aiHosts, aiTools (your AI sites)New entries: each of your AI sites is a vendor custom-<id> in aiHosts, with its own action in aiTools. Built-in vendors are unchanged.
customAiHostsNew: the hosts of your AI sites that are not blocked, where the extension checks prompts and uploads
fileUploadScan, fileUploadUninspectableNew: whether uploaded files are read and checked, and what happens to a file that cannot be (off, warn or block)
personalAiAccountsNew: what happens with a personal or other organisation’s AI account (off, warn or block)
customDataKindsNew: your own kinds of data, each as { "id", "name", "match", "actions" }, where actions holds the resolved action for browser, proxy and coding_agents. Empty when there are none. Clients that predate it ignore it, and the built-in fields keep their meaning.
companyAccountsNew, only when personalAiAccounts warns or blocks: the approved Anthropic organisations, ChatGPT workspaces, Cursor teams and email domains, the personal and organisation plan tiers, and (Block only) tenantRestriction, the UUIDs for vendors’ tenant restriction headers. Left out when the AI account settings cannot be read, and clients then do nothing.
versionA hash of the policy handed to the device (without the fingerprint key). It changes whenever the policy does.

The collector writes the per-kind coding-agent actions into the policy file the hooks read (agent-guard.json, field kinds), and your own kinds of data under custom, each with its definition and its coding-agent action (an action the collector does not know is saved as block). The hooks then look only for the kinds set to warn or block, and act at the strictest level among the kinds they find. A policy file without kinds (from an older collector or platform) works as before: its one level applies to the default kinds. The SHIELD360_AGENT_GUARD environment variable still overrides the policy on a machine and ignores kinds.

Before this policy existed, each environment kept its enforcement settings in its own collection policy. The organisation’s policy is made from those the first time anything reads it:

  • If all environments agree, their settings become the organisation default and nothing is overridden.
  • If they differ, the settings most environments share become the organisation default. A tie goes to the settings of a production environment, then to those of the oldest environment. Every other environment gets exactly the overrides that keep what it enforced.

So no environment’s enforcement changes when the policy appears. Overrides made this way may name a kind or tool explicitly with the value it already had. That can change the policy version a client reports without changing what it enforces.

The old per-environment columns are still written with each environment’s effective policy, for anything that reads them directly. PUT /api/collector/policy still works. A change to an enforcement field there becomes an override of the current environment and needs Manage agent policies.

GET /api/compliance/enforcement-policy
PUT /api/compliance/enforcement-policy
GET /api/compliance/enforcement-policy/environment
PUT /api/compliance/enforcement-policy/environment
DELETE /api/compliance/enforcement-policy/environment
GET /api/compliance/enforcement-policy/targets
PUT /api/compliance/enforcement-policy/targets { "kind": "group" | "person", "key": "...", "overrides": { ... } }
DELETE /api/compliance/enforcement-policy/targets { "kind": "group" | "person", "key": "..." }

The organisation is always the caller’s current one, and the environment is always the current project and environment. Neither is named in the request. A group’s key is its SCIM group id; a person’s is their account name or e-mail. A target’s overrides take only the keys it may set (see People and groups); others are refused with 400 naming the key.

A policy is a flat map of setting keys to values:

KeyValues
sensitive.<layer>.<cell>off, warn, mask, block (no mask for coding_agents). layer is all, browser, proxy or coding_agents; cell is default, a built-in kind, or custom_<id> for one of your own.
aiTools.<vendor>, aiTools.defaultallow, warn, block
aiWarnOverride, guardFailClosed, agentGuardFiles, injectionLlmChecktrue, false
editCostPatterns, injectionMode, gatewayInjectionModeoff, warn, block
approvedModelsModeoff, warn, block: what the AI proxy does with a model outside the approved list (see Approved models)
editRulesA list of { "paths": [...], "action": "warn" | "block", "autoAcceptOnly": false, "reason": "..." }
customAiHostsA list of up to 50 { "host": "ai.corp.example.com", "action": "allow" | "warn" | "block" }. Optional; none by default.
fileUploadScantrue (default), false. Optional.
fileUploadUninspectableoff (default), warn, block. Optional.
customDataKindsA list of up to 50 { "id": "employee_id", "name": "Employee ID", "match": { "type": "masks", "masks": ["EMP-######"] } }, or with { "type": "keywords", "keywords": [...] }. id is 1 to 32 lower-case letters, digits or underscores. Optional; none by default. Each kind’s cells are sensitive.<layer>.custom_<id>.
personalAiAccountsoff (default), warn, block: see Company AI accounts only. Optional.
sandboxEgressA list of up to 50 sandbox egress rules, each { "name", "hosts": [...], "ports": [443], "protocol": "rest" | "tcp", "access": "read-only" | "read-write" | "full", "allow": [{ "method", "path" }], "deny": [...], "binaries": [...], "mode": "block" | "warn" }. name is 1 to 40 lower-case letters, digits, - or _, starting with a letter or digit, and unique. ports defaults to [443], protocol to rest, mode to block, and a rest rule with neither access nor allow to full. access and allow cannot both be given, and a tcp rule takes neither, nor deny. Optional; none by default. See OpenShell.
sandboxPaths{ "readOnly": [...], "readWrite": [...] }, up to 64 absolute paths each, that sandboxes may read or write. /, home roots, credential stores and files, and container runtime sockets are refused. Optional; both empty by default.

The organisation’s PUT takes the complete policy as { "settings": { ... } }, and must include sensitive.all.default and every scalar key except the optional ones, which read as their defaults when left out. The required keys are aiWarnOverride, guardFailClosed, agentGuardFiles, injectionLlmCheck, editCostPatterns, injectionMode, gatewayInjectionMode, approvedModelsMode and editRules. The optional ones are customAiHosts, fileUploadScan, fileUploadUninspectable, personalAiAccounts, sandboxEgress, sandboxPaths and customDataKinds. An environment’s PUT takes only the keys it overrides as { "overrides": { ... } }. An empty map, or DELETE, removes every override.

{
"overrides": {
"sensitive.proxy.default": "block",
"sensitive.coding_agents.email": "warn",
"aiTools.deepseek": "block"
}
}

Unknown keys, kinds, vendors or values, and malformed JSON, are refused with 400 and nothing is saved. A refused AI site names the entry and the reason, in err, key (customAiHosts) and detail ({ "index", "host", "reason" }). A refused kind of data names the kind and, when it is one, the keyword or format, in err, key (customDataKinds) and detail ({ "index", "name", "value", "reason" }).