CodeGraph DLP inspects selected content before it is sent to a model provider and after a provider response is received. It can block, mask, warn, or record a match. Administrators select categories and actions, check the result with synthetic data, and configure alerts for the security team.
Control boundary
Configure DLP under security.dlp in config.yaml. These settings control
request and response checks, sensitive-data categories, actions on a match,
and alert delivery.
The API exposes authenticated DLP configuration, policy, and activity operations under the live
/api/v1/security/dlp surface. Consult the deployed OpenAPI schema for request and
response fields. Reading configuration requires an active user;
changing configuration requires administrator access.
Actions and meaning
| Config value | Operational meaning |
|---|---|
BLOCK (block) |
Stop the protected request and return a blocked outcome. |
MASK (mask) |
Replace matched content before it crosses the protected boundary. |
WARN (warn) |
Allow processing but emit warning evidence. |
LOG_ONLY (log_only) |
Record the match without changing the content. |
On a match, CodeGraph selects the highest-priority action from the matching
categories and pre_request.default_action: BLOCK, MASK, WARN, LOG_ONLY.
When the selected action is WARN or LOG_ONLY, the system records the match
and continues processing the original content.
The table describes request actions. On a response match, ContentScanner.scan_response()
always produces masked text and returns blocked=False, even when its action field
contains BLOCK, WARN or LOG_ONLY. Check the actual result and modified text,
not just the action label.
Configure policy
The checked-in configuration has separate pre_request and post_response controls plus category,
keyword, and webhook settings. The default categories include credentials, PII, and source-code
signals. Check the active categories and patterns in your installation settings.
Save settings in the interface
- Sign in as an administrator and open Security → DLP.
- In the DLP section selector, choose Settings. Enable DLP, pre-request checks, and post-response checks.
- Select the default action for each direction. For example,
BLOCKbefore a request stops transmission on a match; response masking follows the behavior described above. - Select Category. Enable the required categories and select their actions.
Account for the shared priority: a category set to
WARNstill blocks a matching request when the default action isBLOCK. - Select Save DLP. Return to Settings and check the values after reloading the page. In Status, check whether DLP is enabled at runtime; in Activity, find the configuration-change record.
- Follow the deployment validation steps below: a clean request should pass, and a synthetic match should produce the selected result.
The interface saves settings through PUT /api/v1/security/dlp/config.
For automation, supply enabled, pre_request, post_response,
and categories. Each direction has enabled and default_action;
each category has enabled and action. Obtain category keys from
GET /api/v1/security/dlp/config. Repeat that GET after saving and
compare the stored values. The service writes the security.dlp section,
reloads the security configuration, and returns the updated state.
For each deployment, document:
- whether global security and DLP are enabled;
- which categories are enabled and their action and severity;
- approved keyword lists and their owner;
- pre-request and post-response default actions;
- webhook endpoint ownership, secret reference, timeout, retry, and notification actions;
- exception, expiry, review, and rollback process.
Use a synthetic marker to verify the selected action. Record the result and remove the marker after the check.
Request and response flow
Before a protected model call, CodeGraph scans the system and user prompt through the configured
pre-request policy. BLOCK stops the call; MASK forwards modified content; WARN and LOG_ONLY
can still allow the original content to reach the selected provider.
For ordinary SecureLLMProvider.generate(), the response is scanned before returning it.
In generate_stream(), chunks are yielded before the assembled response is scanned;
that check cannot retract chunks already delivered. Review both directions when deciding what data may leave
or re-enter the customer boundary. See LLM security for the complete egress model.
Alerts and SIEM
DLP can create webhook alerts and maps actions to SIEM event types including dlp.block,
dlp.mask, dlp.warn, and dlp.log. These are separate outcomes:
- the scanner detected a match;
- the action changed or allowed content;
- the dispatcher accepted an event;
- a configured handler reported delivery;
- the downstream webhook or SIEM actually received and indexed it.
Find the event in the receiving system and retain the record with its identifier. Use handler status, retry counts, and buffer state to diagnose delivery. Compare these details with the received record. See the SIEM integration guide to configure destinations and check event export.
Check the scanner locally
From the CodeGraph source root with its Python dependencies installed, save this example
as check_dlp.py and run python check_dlp.py. The policy exists only in memory and
does not change deployment configuration. The marker contains no real secret.
from src.security.config import (
DLPAction, DLPCategoryConfig, DLPConfig, DLPPatternConfig,
DLPPreRequestConfig, DLPPostResponseConfig,
)
from src.security.dlp.scanner import ContentScanner
config = DLPConfig(
enabled=True,
categories={"synthetic": DLPCategoryConfig(
enabled=True, action=DLPAction.BLOCK,
patterns=[DLPPatternConfig(
name="demo_marker", regex=r"DLP_DEMO_MARKER", mask_with="[MASKED]",
)],
)},
pre_request=DLPPreRequestConfig(enabled=True),
post_response=DLPPostResponseConfig(enabled=True),
)
scanner = ContentScanner(config)
clean = scanner.scan_request("ordinary example")
request = scanner.scan_request("DLP_DEMO_MARKER")
response = scanner.scan_response("DLP_DEMO_MARKER")
assert not clean.has_matches and not clean.blocked
assert request.has_matches and request.blocked
assert response.has_matches and not response.blocked
assert response.modified_content == "[MASKED]"
print("Clean request passed; marked request blocked; response masked")
Expect the printed message and exit status 0. An AssertionError identifies an
unexpected result. This checks the scanner only; it does not call a provider or test
the API, streaming client or alert delivery.
Validate the deployment
Use non-sensitive synthetic values for each enabled category:
- record the effective policy and release revision;
- submit a prompt expected to pass and one expected to match;
- verify the selected action and whether the provider call occurred;
- verify masking in the returned or forwarded content without logging the original secret;
- inspect authenticated DLP activity;
- verify webhook or SIEM receipt where configured;
- restore the approved policy and record the result.
Test pre-request and post-response independently. Run the scenario again after provider, policy, pattern, or security-profile changes.
Limits and incident handling
Pattern matching can miss transformed, fragmented, encoded, domain-specific, or previously unseen sensitive data and can also produce false positives. Check matching and clean-content examples for each category. Use the results to refine the patterns and repeat the check.
On a suspected leak, stop the affected workflow, preserve secret-free audit evidence, rotate the exposed credential if applicable, identify provider and receiver scope, and follow the customer incident process. Policy changes made during recovery must have an owner, reason, review, and expiry.