Skip to main content
CID222 Docs

Content detection

Run the CID222 detection pipeline over any text with POST /api/v1/guardrails/detect, and read the entities, actions and masked text it returns.

  • Version: 0.4
  • Role: admin_user, normal_user, viewer
  • Type: reference

CID222 exposes its detection engine directly, so you can scan any text for PII, secrets, toxicity and prompt injection without sending it to a model. The same engine runs on every chat request.

Detect content

POST /api/v1/guardrails/detect

Runs the full detection pipeline — PII, secrets, toxicity, jailbreak and injection — over a block of text and returns the entities found, the decided action, and a masked copy of the text.

This is the only surface on the gateway that carries an /api/v1 prefix. Every other endpoint sits at the root, for example /chat/completions and /models.

The endpoint returns 200, not 201. It accepts either a JWT or a gateway API key (Authorization: Bearer cid_key_<64 hex>). A request that arrives unauthenticated from loopback or an RFC1918 address is admitted with no tenant context, which is how the bundled red-team service reaches it; per-tenant filter overrides do not apply to those calls.

Request body

ParameterTypeRequiredDescription
textstringYesText to analyse, 1–50,000 characters
check_typestringNoprompt (default) or response
hap_versionnumberNoToxicity model version, 1 or 2 (default 2)
filterstringNoAccepted by the DTO and then discarded — see the note below

Warning

filter is validated and then dropped: the controller does not pass it to the detection service, so naming a filter here changes nothing. Scope a filter's behaviour with a per-tenant filter override instead.

Unknown fields are stripped silently rather than rejected, because the gateway runs a global validation pipe with whitelist: true. A misspelled field name produces no error.

Example request

curl -X POST https://<appliance-fqdn>/api/v1/guardrails/detect \
  -H "Authorization: Bearer cid_key_0123456789abcdef" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "My name is John Smith and my email is john@example.com",
    "check_type": "prompt"
  }'

Response

The response reports the overall action, a count, the list of detected entities, and a masked copy of the input.

{
  "action": "mask",
  "detectionCount": 2,
  "maskedText": "My name is [PERSON_NAME] and my email is [EMAIL]",
  "detectedEntities": [
    {
      "type": "PERSON_NAME",
      "value": "[PERSON_NAME]",
      "action": "mask",
      "confidence": 0.95,
      "source": "ml",
      "filterName": "ML Detector (ONNX NER)",
      "start": 11,
      "end": 21
    },
    {
      "type": "EMAIL",
      "value": "[EMAIL]",
      "action": "mask",
      "confidence": 0.95,
      "source": "regex",
      "filterName": "Regex Detector",
      "start": 39,
      "end": 55
    }
  ],
  "processingTimeMs": 142,
  "normalization": { "applied": [], "originalText": "" }
}

normalization.applied lists the evasion decoders that ran on the input — rot13, base64, leetspeak, unicode, case — and is an empty array when none applied. normalization.originalText is always an empty string: the controller blanks it so the raw input is never echoed back.

Warning

Raw values are never returned. detectedEntities[].value carries the entity's placeholder, or [REDACTED] when the detector produced none. The original sensitive text does not appear anywhere in the response.

Detected entity fields

FieldTypeDescription
typestringDetection category, for example EMAIL, PERSON_NAME, violence, jailbreak
valuestringPlaceholder such as [EMAIL], or [REDACTED] — never the raw value
actionstringallow, flag, mask or reject
confidencenumber0–1. Regex detections are fixed at 0.95
sourcestringWhich detector produced it, see the table below
filterNamestringThe detector or filter-group identity, not the individual rule
start, endnumberCharacter offsets in the input; absent for whole-text safety detections

source takes one of these values:

sourceEmitted by
regexRegex patterns loaded from the input-filter rows
mlThe ONNX NER model
hap_detectorThe 13-label toxicity model
jailbreak_detectorThe ONNX jailbreak and injection model
injection_scanThe deterministic SQLi and XSS scan
code_rule_detectorCode Safety regex rules
code_ml_detectorThe Code Safety auditor, one entry per reported CWE
mrzThe passport MRZ parser, on the image path
identity_layoutThe identity-document layout extractor, on the image path

filterName reports the detector or the filter group, not the rule that fired. A regex detection reports Regex Detector and carries the seed rule's name internally; a toxicity detection reports the filter group, for example Content Safety (HAP Model - 13 Categories).

Detection actions

ActionMeaning
allowNo action. The content is clean or below threshold
flagThe detection is logged; the content passes through unchanged
maskThe entity is replaced with its placeholder and the request continues
rejectThe content is blocked

Note

When several entities match, the strongest action wins: reject beats mask, mask beats flag, flag beats allow.

On the chat surface a rejection is not an HTTP error. The stream emits {"type":"content_rejected"} for a blocked prompt or {"type":"output_content_rejected"} for a blocked reply, then [DONE].

PII entity types

The seeded PII filter group covers 17 rules. The ONNX NER model emits 21 native labels; the regex layer adds Turkish formats and validators the model does not carry. Where both fire on the same span, the detections are merged.

TypeDescriptionDetected byDefault action
EMAILEmail addressesRegex, NERmask
PHONEPhone numbers — US, international, Turkish mobile and landlineRegex (6 patterns), NERmask
PERSON_NAMEPerson namesNER, plus one regex for uppercase names on Turkish ID cardsmask
SSNUS Social Security numberRegex, us.ssn checksum, NERmask
TC_KIMLIK, ID_NUMBERTurkish national IDRegex (5 patterns including OCR-tolerant), tr.tckimlik checksum, NERmask
ID_DOCUMENT_NOTurkish ID card document and serial numberRegexmask
CREDIT_CARDCard numbersRegex, Luhn plus brand and length checkmask
IBAN, ACCOUNT_NUMBERIBAN and Turkish domestic account numbersRegex, ISO 13616 mod-97mask
VKN, TAX_IDTurkish tax numberRegex, tr.vkn checksummask
PASSPORTPassport numbers — US, generic EU, TurkishRegex, NERmask
IP_ADDRESSIPv4 and IPv6Regex, NERmask
LICENSE_PLATETurkish vehicle platesRegex, province-range check, NERmask
CRYPTO_ADDRESSCrypto wallet addressesNER onlymask
LOCATION, STREET_ADDRESS, CITY, ZIPCODEAddresses, cities, regions, postal codesNER, plus a Turkish postal-code regexflag
ORGANIZATIONCompany and institution namesNER onlyflag
DATE_TIMEDates and timesNER onlyflag
URLURLsNER onlyflag

Note

Default actions come from the shipped seed rows. An administrator changes them per rule, and a per-tenant or per-group override can change the action for one department without touching the rule.

Secret and credential detection

A separate DLP filter group covers secrets and credentials. Nine of its rules are regex-only.

TypeCoversDefault action
API_KEYOpenAI, Anthropic, AWS access and secret keys, GitHub, Slack, Google, CID inspection keys, and a generic pattern — 10 patterns in totalmask
password_assignment, db_password, secret_assignmentInline passwords and secret assignmentsmask
rsa_private_key, private_key_generic, openssh_private_keyRSA and OpenSSH private keysmask
postgres_connection, mysql_connection, mongodb_connection, redis_connectionDatabase connection URIsmask
jwt_token, bearer_token, google_refresh_token, refresh_token_assignmentJWTs, bearer tokens and refresh tokensmask
webhook_secret, stripe_webhookWebhook signing secretsmask
mac_colon, mac_hyphenMAC addressesmask
mrn_labeled, mrn_formatMedical record numbersmask
cve_idCVE identifiersflag

Warning

Only the API-key rule declares a model label, so only it reports type: "API_KEY". The other DLP rules declare none, so their type is the regex pattern name shown above, while value carries the placeholder — [PASSWORD], [RSA_PRIVATE_KEY], [MRN], and so on. Match on the placeholder if you need a stable category.

Safety categories

Three detectors classify content beyond PII: a 13-label toxicity model, a 2-label attack model, and a deterministic injection scan.

LabelDetectorCoversDefault action
violenceToxicityUnlawful violence toward people or animalsreject
crimeToxicityNon-violent crime — financial, property, drugreject
sexual_crimeToxicityNon-consensual sexual acts, traffickingreject
child_exploitationToxicityChild sexual abuse materialreject
defamationToxicityReputation-damaging falsehoodsreject
dangerous_adviceToxicityDangerous specialised advicereject
weaponsToxicityWeapons of mass destruction, illegal armsreject
hateToxicityHate speech targeting protected attributesreject
self_harmToxicitySuicide, self-harm, eating disordersreject
cyber_crimesToxicityHacking, malware, denial of servicereject
privacyToxicityTracking, doxxing, identity theftflag
intellectual_propertyToxicityPiracy, plagiarism, counterfeitingflag
sexual_contentToxicityAdult sexual contentflag
jailbreakAttack modelRole-play attacks, system-prompt extractionreject
injectionAttack modelPrompt-injection attemptsreject
sql_injectionInjection scanSQL injection, detected deterministicallyreject
xssInjection scanCross-site scripting, detected deterministicallyreject

The toxicity and attack models each cover eight languages: en, tr, de, fr, es, ar, it and nl. The injection scan is language-independent — it parses the string rather than classifying it — and a low attack-intent score from the attack model demotes its verdict from reject to flag.

Toxicity thresholds are per label, in three levels (block, flag, log-only), and ship tuned per label rather than at one global value. Attack-model thresholds are likewise per label and three levels. Both sets are baked into their service image and have no environment override, so changing them means rebuilding the image.

Confidence scores

Every detection carries a confidence between 0 and 1. Regex detections are fixed at 0.95, because a compiled pattern either matched or did not. Model detections carry the model's own score.

A detection is boosted by 0.1, clamped at 1.0, when a context keyword registered for its entity type appears within 50 characters of the span. The boost is context-keyword driven; it is not awarded for two detectors agreeing.

A validated entity passes only if its final confidence reaches 0.6. A detection that arrives with no confidence at all is assumed to be 0.8.

Note

Accuracy and latency depend on text length, language, detector and filter configuration. See performance and accuracy before quoting a number.

Query stored detections

GET /admin/detections and GET /admin/detections/stats read what the pipeline recorded. Both require the admin_user or auditor role and the detections.view capability, and both are scoped to the tenants the caller can already read.

ParameterTypeDescription
page, limitnumberPagination. Defaults 1 and 10; limit is capped at 100
entity_typestringFilter by detection category, for example EMAIL
action_takenstringmasked, rejected or flagged
message_rolestringuser, assistant or system
tenant_idstringFilter by tenant
group_idstring (UUID)Narrow to one tenant group's members; a group the caller does not own answers 404
session_idstringFilter by session
start_date, end_datestringISO 8601 date range
searchstringFree-text search
curl -X GET "https://<appliance-fqdn>/admin/detections?entity_type=EMAIL&action_taken=masked" \
  -H "Authorization: Bearer <admin-jwt>"

The response is paginated:

{
  "data": [],
  "meta": { "total": 42, "page": 1, "limit": 10, "totalPages": 5 }
}

Last updated on

On this page

Download PDF