drupal / ai_recipe_validations_image_safety
Blocks image uploads to Media: Image that contain nudity, sexually suggestive content, gore, graphic violence, or graphic medical imagery. Uses AI Validations and any vision-capable AI provider.
Package info
git.drupalcode.org/project/ai_recipe_validations_image_safety.git
Type:drupal-recipe
pkg:composer/drupal/ai_recipe_validations_image_safety
Requires
- drupal/ai: ^1.4
- drupal/ai_validations: ^1.3
- drupal/core: ^10.3 || ^11
- drupal/field_validation: ^3.0@beta
README
Blocks image uploads to the Media: Image bundle that contain nudity, sexually suggestive content, gore, graphic violence, or graphic medical imagery. Uses AI Validations with any vision-capable AI provider.
Requirements
- Drupal 10.3+ or 11
- AI module 1.4 or newer (provides the
verifySetupAiconfig action and theai_provider_configurationform element) - AI Validations (standalone) 1.3 or newer — the shipped rule stores an empty provider, which this version resolves to the site default both in the rule form ("Default" option) and at validation time (see #3586397).
- Field Validation 3.0 or newer — 3.0 currently has beta releases only.
Composer ignores stability flags during dependency resolution, so
projects with the default
minimum-stability: stablemust allow the beta explicitly before requiring the recipe (see Apply below). The recipe declares^3.0@betaso that when it is unpacked into your rootcomposer.json, the flag is preserved there and later Composer operations keep working. - A configured default provider for the
chat_with_image_visionoperation type (OpenAI GPT-4o, Anthropic Claude 3.5 Sonnet, Google Gemini 1.5 Pro, etc.) at/admin/config/ai/settings→ Default Providers
Note: the AI module still bundles a deprecated copy of ai_validations.
When the standalone package is installed, Drupal's extension discovery
automatically prefers it (shallower path wins) — no uninstall/reinstall
is needed on existing sites, just a cache rebuild. Without the standalone
package, the deprecated copy treats the recipe's empty provider as an
error and blocks every upload with "No AI provider specified to do
validation".
Apply
Set up a vision-capable provider before applying. On a site where the AI module is not yet configured, the recipe's preflight check will abort the apply (see "Recovering from a failed apply" below).
composer require drupal/field_validation:^3.0@beta
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.
The field_validation line is only needed until it tags a stable
3.0.0 release.)
Then, in the admin UI:
- Add your API key at
/admin/config/system/keys. - Configure the provider at
/admin/config/ai/providers. - Set a default model for the
chat_with_image_visionoperation type at/admin/config/ai/settings→ Default Providers.
Finally, apply the recipe:
php core/scripts/drupal recipe ../recipes/ai_recipe_validations_image_safety
drush cache:rebuild
Recovering from a failed apply
If the apply aborts with "The operation type 'chat_with_image_vision' does not have a default model", the 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 check cannot pass, because configuring a default model itself requires the AI module. Follow the setup steps above (enable the modules, configure a default model), then re-run the apply.
What it does
- Applies core's
image_media_typerecipe first (creates the Media: Image bundle if it does not exist). - Installs
ai,ai_validations, andfield_validation. - Creates a field validation rule set
media_imageattached to the Media: Image bundle'sfield_media_imagefield. - Runs the AI image constraint on the
target_idcolumn in entity validation mode — catches UI uploads, JSON:API posts, and programmatic saves alike.
Adjusting the threshold
Default behavior blocks anything outside the "Safe" tier (Flickr-style classification). To allow "Moderate" content and block only "Restricted":
- Go to Structure → Field Validation → AI image safety (Media: Image)
- Edit the Block unsafe imagery rule
- Replace the
=== DECISION ===block of the prompt with:- If the image is SAFE or MODERATE, respond with: XTRUE - If the image is RESTRICTED, respond with: XFALSE
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.
Issue queue
Bugs and feature requests: https://www.drupal.org/project/issues/ai_recipe_validations_image_safety