Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions docs/changelog.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ description: "Product updates and release notes for Intercept, including depende
<Update label="July 31, 2026" description="v0.2.0" tags={["Release", "Security"]}>
Added tool approval decision scanning to `PromptInjectionGuard` and `PIIRedactor`.

When an agent pauses for tool approval, the run is resumed by passing `Decisions` back to the agent instead of a new prompt. A resumed prompt carries no prompt text, so both middleware previously reported clean while the content a human supplied on the way through reached the AI provider unscanned.
When an agent pauses for tool approval, you resume the run by passing `Decisions` back to the agent instead of a new prompt. A resumed prompt carries no prompt text, so both middleware previously reported clean while the content a human supplied on the way through reached the AI provider unscanned.

Both middleware now scan that content:

Expand All @@ -87,7 +87,7 @@ description: "Product updates and release notes for Intercept, including depende

A paused turn must replay verbatim against the provider that recorded it, so resumed prompts cannot be rewritten. The `redact`, `mask`, `sanitize`, and `warn` actions therefore degrade to logging on this path, recorded in logs as `degraded_from`. Blocked entities and the `block` action still stop the run.

Scanning is enabled by default and can be turned off per middleware with `scan_approval_decisions`.
Scanning is enabled by default. You can turn it off per middleware with `scan_approval_decisions`.

The documentation now also states plainly what Intercept can and cannot inspect, since tool results, attachments, and conversation history never pass through the middleware pipeline.
</Update>
Expand Down Expand Up @@ -145,7 +145,7 @@ description: "Product updates and release notes for Intercept, including depende
<Update label="July 14, 2026" description="v0.1.5" tags={["Release", "Security", "Community"]}>
Hardened the built-in prompt injection detection patterns in `PromptInjectionGuard` to improve protection against common prompt injection attempts.

Also improved the project documentation by adding contribution guidelines and updating the roadmap to help developers contribute consistently to Intercept.
Also improved the project documentation by adding contribution guidelines and updating the roadmap to help you contribute consistently to Intercept.
</Update>

<Update label="June 24, 2026" description="v0.1.4" tags={["Release", "DX", "Docs"]}>
Expand Down Expand Up @@ -197,5 +197,5 @@ description: "Product updates and release notes for Intercept, including depende
- `promptphp/intercept-injection-guard`
- `promptphp/intercept-pii-redactor`

It also added shared configuration through `config/intercept.php`, the `intercept-config` publish tag, prompt injection detection, PII redaction, safe logging, package documentation, Pest tests, and the split-package monorepo structure.
It also added shared configuration through `config/intercept.php` and the `intercept-config` publish tag. It added prompt injection detection, PII redaction, safe logging, package documentation, Pest tests, and the split-package monorepo structure.
</Update>
2 changes: 1 addition & 1 deletion docs/configuration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ This middleware acts on the response rather than the prompt, because the model p

When an agent pauses for tool approval and you resume it with `Decisions`, the prompt text is empty. The new content is whatever a human supplied while resolving the pending tool calls: edited tool arguments and rejection results.

Intercept scans that content by default, before the SDK applies the decisions and runs any approved tool call. Resumed prompts cannot be rewritten, so actions that modify the prompt degrade to logging on this path:
Intercept scans that content by default, before the SDK applies the decisions and runs any approved tool call. Intercept cannot rewrite resumed prompts, so actions that modify the prompt degrade to logging on this path:

| Middleware | Degrades to logging | Still blocks |
| --------------- | ------------------- | --------------------------------- |
Expand Down
2 changes: 1 addition & 1 deletion docs/guides/production-rollout.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ sidebarTitle: "Production rollout"

Intercept middleware can block, redact, mask, log, or modify prompts before they reach an AI provider.

For production apps, it is usually best to roll out gradually.
For production apps, you should usually roll out gradually.

## Recommended rollout path

Expand Down
2 changes: 1 addition & 1 deletion docs/guides/security-notes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ It does not scan:

It cannot change what the SDK stores. The conversation store keeps the original prompt, and the SDK builds the conversation title from it.

This matters most for indirect prompt injection. If a tool fetches a web page, reads a document, or queries a record that contains injected instructions, that content is handed to the model without passing through Intercept.
This matters most for indirect prompt injection. If a tool fetches a web page, reads a document, or queries a record that contains injected instructions, the SDK hands that content to the model without passing it through Intercept.

Tool Approval Guard narrows that gap but does not close it. It inspects what the model *proposed* after reading poisoned content, which is where the damage usually surfaces. It cannot inspect the poisoned content itself. It also only applies to tools that are approval-gated. A tool that runs without approval is never inspected.

Expand Down
16 changes: 8 additions & 8 deletions docs/middleware/injection-guard.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ sidebarTitle: "Injection Guard"
It can block, log, warn, sanitize, or delegate handling to a custom callback.

<Tip>
This middleware is a lightweight heuristic guard. It is designed to catch common prompt injection patterns. Don't treat it as complete protection against every possible attack.
This middleware is a lightweight heuristic guard. It targets common prompt injection patterns. Don't treat it as complete protection against every possible attack.
</Tip>

## Installation
Expand Down Expand Up @@ -185,7 +185,7 @@ public function middleware(): array
}
```

The prompt continues unchanged, but the detection is logged safely.
The prompt continues unchanged, but the middleware logs the detection safely.

Prompt previews are disabled by default because prompts may contain sensitive data. Enable previews only if you are comfortable storing a short prompt sample in your logs.

Expand Down Expand Up @@ -240,7 +240,7 @@ Example input:
</Prompt>


The matched injection phrase is replaced with:
The middleware replaces the matched injection phrase with:

<Prompt description="[removed] and summarize this support ticket.">
[removed] and summarize this support ticket.
Expand All @@ -252,7 +252,7 @@ The matched injection phrase is replaced with:

### Custom patterns

Custom patterns are merged with the built-in patterns by default.
By default, the middleware merges custom patterns with the built-in patterns.

```php
public function middleware(): array
Expand Down Expand Up @@ -404,7 +404,7 @@ $response = $agent->prompt(Decisions::from([
]));
```

The injection attempt above is detected exactly as it would be inside a prompt.
Intercept detects the injection attempt above exactly as it would inside a prompt.

### Actions on a resumed run

Expand All @@ -427,11 +427,11 @@ When Injection Guard blocks a resumed run, the exception names the offending too
Prompt injection attempt detected in tool approval decisions [call_7: arguments.filters.note].
```

The matched text is never included in the message, so it stays safe to log. Follow the guidance in [handling blocked prompts](/guides/handling-blocked-prompts) before surfacing anything to a user.
The message never includes the matched text, so it stays safe to log. Follow the guidance in [handling blocked prompts](/guides/handling-blocked-prompts) before surfacing anything to a user.

### Reading the logs

Detections are logged under a distinct message, `Prompt injection attempt detected in tool approval decisions.`, with a `source` of `approval_decisions`:
Intercept logs detections under a distinct message, `Prompt injection attempt detected in tool approval decisions.`, with a `source` of `approval_decisions`:

```php
[
Expand All @@ -452,7 +452,7 @@ The `degraded_from` key appears only when the configured action could not be app

### Custom callbacks on a resumed run

A callback receives the resumed `AgentPrompt`, a `null` in place of `$next`, and the same detection array it receives on the prompt path. The array has two extra keys that name where the detection came from. The return value is ignored, so throw to stop the run:
A callback receives the resumed `AgentPrompt`, a `null` in place of `$next`, and the same detection array it receives on the prompt path. The array has two extra keys that name where the detection came from. Intercept ignores the return value, so throw to stop the run:

```php
new PromptInjectionGuard(
Expand Down
14 changes: 7 additions & 7 deletions docs/middleware/pii-redactor.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ sidebarTitle: "PII Redactor"
It can redact, mask, log, block, or delegate handling to a custom callback.

<Tip>
This middleware is deterministic and regex-based. It is designed to catch common structured sensitive data. It is not intended to guarantee complete detection of every possible personal identifier.
This middleware is deterministic and regex-based. It catches common structured sensitive data. It does not guarantee complete detection of every possible personal identifier.
</Tip>

## Installation
Expand Down Expand Up @@ -91,7 +91,7 @@ Some entities can still be blocked even when the action is `redact`. By default,
| `api_key` | Common API key formats. |
| `bearer_token` | Bearer authorization tokens. |

Names, addresses, passports, national insurance numbers, and medical identifiers are not included in the current version. These values are harder to detect safely with regex alone and can create false positives.
The current version does not detect names, addresses, passports, national insurance numbers, or medical identifiers. These values are harder to detect safely with regex alone and can create false positives.

## Configuration

Expand Down Expand Up @@ -228,7 +228,7 @@ public function middleware(): array
}
```

The prompt continues unchanged, but detections are logged safely.
The prompt continues unchanged, and the middleware logs detections safely.

Prompt previews are disabled by default because prompts may contain sensitive user data. Enable previews only if you are comfortable storing a short prompt sample in your logs.

Expand Down Expand Up @@ -283,7 +283,7 @@ try {

### Blocked entities

Some entities are treated as high-risk and are blocked by default, even when the action is `redact`.
The middleware treats some entities as high-risk and blocks them by default, even when the action is `redact`.

Default blocked entities:

Expand Down Expand Up @@ -486,7 +486,7 @@ $response = $agent->prompt(Decisions::from([
]));
```

The email address above is detected exactly as it would be inside a prompt.
The middleware detects the email address above exactly as it would inside a prompt.

### Actions on a resumed run

Expand All @@ -499,11 +499,11 @@ A paused turn must replay verbatim against the provider that recorded it, so the
| `redact` | Degrades to logging. |
| `mask` | Degrades to logging. |

Blocked entities still stop the run regardless of the configured action. A credit card, API key, or bearer token in an edited tool argument is refused exactly as it would be in a prompt.
Blocked entities still stop the run regardless of the configured action. The middleware refuses a credit card, API key, or bearer token in an edited tool argument exactly as it would in a prompt.

### Reading the logs

Detections found in approval decisions are logged under a distinct message, `PII detected in tool approval decisions.`, with a `source` of `approval_decisions`:
The middleware logs detections found in approval decisions under a distinct message, `PII detected in tool approval decisions.`, with a `source` of `approval_decisions`:

```php
[
Expand Down
12 changes: 6 additions & 6 deletions docs/middleware/tool-approval-guard.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ Entities listed in `block_entities` stop the run regardless of the configured ac

### Prompt injection patterns

A proposed argument that matches an injection pattern suggests the model was manipulated by content the middleware never saw. It uses the same patterns as [Injection Guard](/middleware/injection-guard).
A proposed argument that matches an injection pattern suggests that content the middleware never saw manipulated the model. It uses the same patterns as [Injection Guard](/middleware/injection-guard).

**This scan is off by default.** Prose a model writes for a human reader routinely contains phrases the patterns match, such as "You are now subscribed to weekly updates.", "From now on we will email you every Monday.", "System: scheduled maintenance at 3pm." None of those indicate manipulation in that context.

Expand Down Expand Up @@ -140,7 +140,7 @@ new ToolApprovalGuard(
| `block` | Throws before the approval is surfaced for review. |
| `log` | Logs the finding and lets the pending approval reach the caller. |

There is deliberately no mutating action. A proposed tool call is part of the paused turn the provider recorded, so rewriting it would desynchronise the run when it is resumed. The same constraint applies to resumed prompts.
There is deliberately no mutating action. A proposed tool call is part of the paused turn the provider recorded, so rewriting it would desynchronise the run when you resume it. The same constraint applies to resumed prompts.

<Warning>
`action: 'log'` on its own is **not** observe-only here. Every entity in the
Expand All @@ -167,7 +167,7 @@ It inspects two kinds of proposal:
- tool calls to a local tool whose approval rule asks for approval
- approvals that the provider reports itself

A tool call that runs without approval is not inspected.
The middleware does not inspect a tool call that runs without approval.

## Streaming

Expand Down Expand Up @@ -197,7 +197,7 @@ try {

## Reading the logs

Findings are logged with a `source` of `pending_approvals`:
The middleware logs findings with a `source` of `pending_approvals`:

```php
[
Expand All @@ -220,7 +220,7 @@ Findings are logged with a `source` of `pending_approvals`:
]
```

Matched values are always recorded as SHA-256 hashes. Set `log_preview` to `true` to add a short cleartext preview, which is off by default because proposed arguments can carry sensitive data.
The middleware always records matched values as SHA-256 hashes. Set `log_preview` to `true` to add a short cleartext preview. The preview is off by default because proposed arguments can carry sensitive data.

The `type` is one of `denied_tool`, `pii`, or `injection`. The `detail` carries the entity type or the matched pattern.

Expand All @@ -245,7 +245,7 @@ Each finding is an `ApprovalFinding` exposing `toolCallId`, `tool`, `type`, `fie

## Configuration

All options may be set globally in `config/intercept.php` under `tool_approval_guard`, or per agent through the constructor. Constructor values always win.
You can set all options globally in `config/intercept.php` under `tool_approval_guard`, or per agent through the constructor. Constructor values always win.

```php
'tool_approval_guard' => [
Expand Down
Loading