This project is not covered by Drupal’s security advisory policy.

Validates uploaded images on the Media: Image bundle using a vision-capable AI provider. Every upload is classified into the Flickr-style Safe / Moderate / Restricted tiers: Restricted content (full nudity, explicit sexual content, gore, graphic violence, graphic medical imagery) is blocked, Moderate content (partial nudity, sexually suggestive content, mild violence) is accepted with a warning to the uploader, and Safe content is accepted silently. Validation runs at the entity level, so it covers the admin UI, the Media Library, JSON:API and programmatic saves.

Recipes Applied

  • core/recipes/image_media_type

Modules and Themes Installed

Requirements

  • Drupal 10.3 or newer, or Drupal 11
  • AI module 1.4 or newer (provides the verifySetupAi config action)
  • AI Validations 1.4 or newer (provides the XSAFE / XWARN / XBLOCK warning tier)
  • Field Validation 3.0 or newer (3.0.0 is a stable release, so no stability flag is needed)
  • A configured default provider for the chat_with_image_vision operation type at /admin/config/ai/settings → Default Providers. Any vision-capable provider works (OpenAI, Anthropic, Google Gemini, etc.).

Installation

On a site that already has a vision provider configured

If a default model is already set for the chat_with_image_vision operation type, this is all you need:


composer require drupal/ai_recipe_validations_image_safety 
drush recipe ../recipes/ai_recipe_validations_image_safety 
drush cache:rebuild

On a brand new site (AI not configured yet)

The recipe's preflight check requires a default model for chat_with_image_vision, and configuring one requires the AI module and a provider module to be installed and set up, so do that first. The recipe does not install a provider for you, because that choice is yours:


composer require drupal/ai_provider_openai drupal/ai_recipe_validations_image_safety 
drush en ai ai_provider_openai key -y

(Substitute ai_provider_openai with the provider module of your choice: ai_provider_anthropic, ai_provider_google_gemini, etc.)

Then, in the admin UI:

  1. Add your API key at /admin/config/system/keys.
  2. Configure the provider at /admin/config/ai/providers.
  3. Set a default model for the chat_with_image_vision operation type at /admin/config/ai/settings → Default Providers.

Finally, apply the recipe:


drush recipe ../recipes/ai_recipe_validations_image_safety 
drush cache:rebuild

Drupal CMS / Project Browser

Install the base AI recipe and configure a vision provider first, then install this recipe from /admin/config/ai. Since 1.1.0 no Composer pre-step is needed: Field Validation 3.0 is stable and resolves on the default minimum-stability: stable.

Recovering from a failed apply

If the apply aborts with "The operation type 'chat_with_image_vision' does not have a default model", your site was rolled back to its pre-apply state. Modules reported as installed earlier in the output were reverted as part of the rollback. Recipe application is atomic, and on a site without a configured provider the preflight cannot pass, because configuring a default model itself requires the AI module. Follow the brand-new-site steps above, then re-run the apply.

What it does

  • Creates the Field Validation rule set media_image on the Media: Image bundle's field_media_image field.
  • Runs the AI image constraint on every image upload and classifies the image as Safe, Moderate or Restricted.
  • Safe: saved silently. Moderate: saved, the uploader sees a warning and a notice is written to the ai_validations log. Restricted: blocked with a clear error message. Anything the model cannot classify is treated as Restricted.
  • Catches uploads from the admin UI, the Media Library, JSON:API posts, migrations and programmatic $entity->save() calls. Headless flows are never blocked by a warning.

Adjusting the tiers

Edit the Block restricted imagery, warn on moderate rule at Structure → Field Validation → AI image safety (Media: Image).

  • To block Moderate content as well, change the MODERATE line of the prompt's === DECISION === block to XBLOCK.
  • To accept Moderate content silently, change it to XSAFE.
  • The blocking message and the warning message are editable on the same form.
  • To return to the plain XTRUE/XFALSE protocol, empty the Warning message field and rewrite the === DECISION === and === OUTPUT FORMAT === blocks for XTRUE / XFALSE. Changing only one of the two blocks every upload.

Full instructions are in the project README.

Upgrading from 1.0.x

The recipe creates its rule set only when it does not exist yet, so re-applying 1.1.0 on a site that already applied 1.0.x leaves the existing rule unchanged. To get the warning tier on such a site, edit the rule as described above, or delete the rule set at Structure → Field Validation and re-apply the recipe.

Cost note

Every image upload triggers one vision-model API call. Bulk migrations, imports, or high-volume user upload flows will incur proportional cost. Test with your provider's pricing before rolling out to production.

Bugs and Feedback

If you encounter any bugs or have feedback about this recipe, please file an issue in the project issue queue.

Credits

Developed as part of the AI Initiative. See the originating issue: #3585696.

Supporting organizations: 

Project information

Releases