GitHub - ultramancode/spring-ai-privacy-guardrails: Privacy and security guardrails for Spring AI: request-scoped PII tokenization, least-privilege disclosure to tools, and tool authorization with Spring Security. Configurable content inspection using rules, HTTP guard models, or local ONNX classifiers. PII detection with Presidio and JVM-local OpenNLP.

GitHub

5 min read Original article ↗

Maven Central CI License

English | 한국어 | Documentation

Apply privacy protection, tool authorization and content inspection to your application.

Tokenize detected PII before it reaches the model. Reveal only the originals a tool needs, then protect its result again.

PII tokenization and per-tool disclosure, with optional tool authorization and content inspection

Featured In

Three Core Features

Use these features independently or together.

What you need Feature
Keep detected PII out of the model and allow originals only for selected tools Privacy
Limit tool visibility and execution using the current user's permissions Tool Authorization
Check requests and responses with rules, local ONNX or an HTTP guard model Content Inspection

Add Protection to an Application

Use Java 17 or later, Spring AI 2.0.0 or later and Spring Boot 4.0.0 or later. See repository configuration and Maven setup.

Add the client starter:

dependencies {
    implementation "io.github.ultramancode:spring-ai-privacy-guardrails-chat-client-spring-boot-starter:0.4.0"
}

For this privacy example, enable the COMMON preset to detect email addresses. Add to src/main/resources/application.yml:

spring:
  ai:
    privacy:
      rules:
        enabled: true
        presets: [COMMON]

Create the client through GuardrailsChatClientFactory in an application @Configuration class. Select privacy protection in its policy:

@Bean
ChatClient chatClient(ChatModel chatModel, GuardrailsChatClientFactory guardrailsChatClientFactory) {
    GuardrailsPolicy policy = GuardrailsPolicy.builder()
            .privacy()
            .build();
    return guardrailsChatClientFactory.builder(chatModel, policy)
            .build();
}

Inject this bean into your service and call it:

String response = chatClient.prompt()
        .user("Contact alice@example.com.")
        .call()
        .content();

The model receives a replacement token instead of the email address. For readability, the examples below use [EMAIL_TOKEN] to represent the generated token:

See Getting Started for feature setup and combinations.

Use All Three Features Together

This customer lookup example combines privacy protection, Spring Security tool authorization and content inspection. Passing content inspection does not grant permission to run the lookup tool.

The example below uses the COMMON preset above with the Security starter and a configured inspector. It assumes that a ToolCallback bean named customerLookupToolCallback provides a customerLookup tool that looks up customers by email address. This configuration replaces the earlier chatClient bean and adds an admin-only tool authorization policy:

@Bean
AuthorizationManager<ToolAuthorizationContext> toolAuthorizationManager() {
    return AuthorityAuthorizationManager.hasRole("ADMIN");
}

@Bean
ChatClient chatClient(ChatModel chatModel, GuardrailsChatClientFactory guardrailsChatClientFactory,
        ToolCallback customerLookupToolCallback) {
    // Original PII disclosure: pass only original email addresses to customerLookup
    ToolDisclosurePolicy toolDisclosurePolicy = ToolDisclosurePolicy.allowEntityTypesByToolName(
            Map.of("customerLookup", List.of("EMAIL_ADDRESS")));
    GuardrailsPolicy.Privacy privacySettings = GuardrailsPolicy.Privacy.builder()
            .toolDisclosurePolicy(toolDisclosurePolicy)
            .build();
    GuardrailsPolicy policy = GuardrailsPolicy.builder()
            .privacy(privacySettings)   // Privacy: tokenize detected PII
            .toolAuthorization(true)   // Security: check the ADMIN role with Spring Security
            .inspection()              // Inspection: check for prompt injection, prompt leaking and toxic language
            .build();
    return guardrailsChatClientFactory.builder(chatModel, policy)
            .defaultTools(customerLookupToolCallback)
            .build();
}

The authorization policy checks the current user's ADMIN role. The disclosure map uses the registered tool name as its key and the list of allowed PII entity types as its value. The inspection checks depend on the selected inspectors and their configuration.

Call it from an authenticated request:

String response = chatClient.prompt()
        .user("Look up the customer with email alice@example.com.")
        .call()
        .content();

The inspector receives the request with the email replaced by [EMAIL_TOKEN]. A BLOCK decision stops the main model call. An ALLOW decision passes the same protected request to the model, while tool access still depends on the user:

  • Admin (ADMIN role): the model may request customerLookup. Immediately before execution, permission is checked again, then alice@example.com is restored for the tool. Other PII entity types remain tokenized.
  • User without the ADMIN role: customerLookup is omitted from the model's tool list. Even if the model requests it by name, the tool is not executed and the email is not restored.

Before a lookup result is sent back to the model, its detected PII is tokenized and the protected content is inspected again. If that inspection returns BLOCK, the next model call is stopped.

See tool registration and MCP integration. For custom disclosure logic, use a separate policy class. Final-response protection and inspection are separate opt-in output policies.

Add the Features You Need

Need Next step
Detect your own employee or customer identifiers Java rules and presets
Broader detection or NER models Presidio and OpenNLP choices
Per-user tool visibility and execution Spring Security setup
Input and optional output inspection Content inspection setup
Tokenize, redact or block PII in the final answer Output protection
Diagnose unexpected behavior Troubleshooting

Sample

The sample application uses fixed examples to illustrate Local Tool, RAG, MCP, Security and Inspection. See the Sample Guide for screenshots and run instructions.

Inspector showing Local Tool, RAG, MCP, Security and Inspection

Demo videos: English · 한국어

Compatibility

Component Minimum supported version
Java 17
Spring AI 2.0.0
Spring Boot 4.0.0
Spring Security 7.0.0

We continue to verify compatibility and support new releases of Java, Spring AI, Spring Boot and Spring Security as they become available. The Boot starter uses the Spring Security version selected by the Spring Boot BOM.

Documentation

  • Getting Started: common setup and first steps for privacy protection, tool authorization and content inspection
  • Configuration: dependencies, client creation and reusable policies
  • Privacy Protection: analyzers, tokenization, tool disclosure, output protection and processing limits
  • Spring Security Tool Authorization: tool authorization policy, advanced tool configuration, Tool Search, and security-context handling
  • Content Inspection: opt-in rules, local ONNX classifiers and HTTP guard models
  • Architecture: modules and model, tool, and session execution flow
  • Threat Model: protected assets, trust boundaries, controls, limitations, and separately managed areas
  • Evaluation and Benchmarks: verification coverage and interpretation limits
  • Sample Guide: Inspector scenarios, runtime endpoints, and the evidence each view verifies
  • Full Sample Guide: optional analyzer and real-model integration examples

Build and Verify

./gradlew --no-daemon clean check

This command runs the repository's tests and verifies its module rules. Run ./gradlew verifyDocTranslations to check translation synchronization. See Evaluation for the demo analyzer regression test and JMH benchmarks.

Contributing

See Contributing. All contributions are provided under the Apache License 2.0.