Field Guard
Field Guard is an open-source Drupal module for config-driven, fail-closed field access. It lets operators name sensitive fields and deny view or edit access unless a non-administrator role explicitly carries the configured permission.
The operator problem
Protecting only rendered field values is not enough. JSON:API and Views can ask whether a field may be filtered or sorted without providing an entity. A neutral answer can leave a sensitive field probeable even when its value is never displayed. Ordinary permission checks also treat administrator roles and user 1 as holding every permission, which can silently bypass separation-of-duty intent.
What the module implements
- Fail-closed definition-level checks when Drupal provides no entity context, preventing guarded fields from remaining available as JSON:API or Views filter and sort surfaces.
- Explicit-role permission evaluation that skips administrative roles and requires the named permission to appear in a regular role's own configuration.
- Deny-only behavior: Field Guard never grants access and defines no permissions of its own; it enforces permissions supplied by the site or another module.
- Configuration-managed policy organized by entity type, bundle, field, and operation, making protection reviewable in configuration diffs and recoverable through normal config deployment.
- Safe defaults: the module ships empty, omitted operations remain unprotected, and empty permission strings are treated as unset rather than as an invisible total denial.
- Cache-correct access verdicts: decisions carry the settings cache tag so a policy change invalidates earlier answers; account-dependent value checks retain user-role and permission contexts, while the account-independent definition-level denial avoids unnecessary per-user cache fragmentation.
- Closed configuration schema for the supported
viewandeditoperations, making misspellings such asviewedorEditfail validation instead of silently leaving a field open.
How the denial works
Field Guard is a deliberately thin wrapper around Drupal's field-access system. For a configured field, it returns AccessResult::forbidden(). Drupal folds field-access results so that a forbidden result cannot be overridden by another permission, an administrative role, or user 1. For value-level checks, the module loads the account's roles, ignores roles marked administrative, and looks for the configured permission on the remaining roles directly. A legitimate grant therefore appears as an explicit, reviewable configuration change.
For definition-level requests with no field-item list, the result is forbidden for every account. This removes the Views handler and JSON:API filtering or sorting surface rather than allowing a caller to infer a protected value through repeated queries. The tradeoff is intentional and covered by kernel tests: even a permission holder cannot filter or sort on a guarded field when no entity context exists.
Honest boundaries
Field Guard governs Drupal's field-access API. It cannot stop direct SQL, Drush, or programmatic reads that bypass that API, and it does not provide audit logging by itself. Protection is exact-match rather than inherited: an unlisted entity type, bundle, field, or operation remains open. Workflow fields such as moderation_state and status should not be edit-guarded here; Drupal evaluates field edit access against the stored value during an API patch, while transition policy belongs in validation that can inspect the incoming value.
Where it fits
Field Guard is a narrow policy primitive for governed content and agent access. It supports our Zero-Trust Architecture, Enterprise Content Management, and AI Governance & MCP Integration practices. Sites that need evidence of sensitive-field access can pair its protection-map seam with a dedicated audit consumer such as Audit Chain.
Configuration example
protected:
profile:
compliance_record:
field_evidence_date:
view: 'view compliance evidence'
edit: 'record compliance evidence'
Install and inspect
composer require drupal/field_guard
drush en field_guard
Field Guard supports Drupal 10.6+, 11.3+, and Drupal 12 on PHP 8.1 or newer. It has no runtime dependency beyond Drupal core's Field and User modules, and installation is inert until a protected-field map is supplied.