
Adversarial Unicode & Trojan Source gatekeeper
Scans a public GitHub repo, a pull request, a unified diff or a list of files for adversarial Unicode with the 19 rules (USC001-USC019) of dcondrey/unicode-safety-check: bidi controls (Trojan Source), invisible and default-ignorable characters, variation-selector and tag-character payloads (Glassworm), private-use code points, homoglyph and mixed-script identifiers, confusable collisions, misplaced BOM and control characters. Leads with a block/warn/pass verdict, a 0-100 risk score, the top locations (file:line:column) grouped so one trick reads as one finding, and the fix; also returns every finding, a SARIF 2.1.0 log for GitHub code scanning, and model-written exploit explanations that are checked against the findings. Findings and verdict come from deterministic rules; only the explanations use a model. Repo scans read up to 1,000,000 characters, shallowest files first, and list what they skipped.
What you get
A single invisible or reordering character can hide a backdoor from every human reviewer. This gate finds it in a PR or repo before merge and returns the exact line and fix.
Call it
Send the JSON body below to https://agents.writerslogic.com/api/v1/unicode-safety-gate. An unpaid request answers 402 with the price and how to pay; a request that fails with a 5xx status is not charged.
curl -i -X POST https://agents.writerslogic.com/api/v1/unicode-safety-gate \
-H 'content-type: application/json' \
-d '{"files":[{"path":"src/auth.js","content":"const isAdmin = false;\nif (isAdmin // check later ) {\n grant();\n}\n"}]}'
Input
| Field | Type | Required | Description |
|---|---|---|---|
files | array<object>; max 500 items | no | Files to scan in full. Provide exactly one of files, diff, repo or prUrl; total content is capped at 1000000 characters. |
diff | string; length 1..1000000 | no | Unified diff (git diff output). Only added lines are scanned; findings carry new-file line numbers. |
repo | string; length 3..200 | no | Alternative to files and diff: a public GitHub repository, owner/repo or https://github.com/owner/repo[/tree/ref]. Read from its source archive; files are scanned shallowest first up to the character cap and the rest are listed as skipped. |
ref | string; length 0..200 | no | Branch, tag or commit for repo; defaults to the default branch. |
prUrl | string; length 20..300 | no | Alternative to files and diff: a public GitHub pull request, commit or compare URL. Only added lines are scanned. |
identifierPolicy | string; one of "ascii-only", "permitted-scripts" | no | Default ascii-only: any non-ASCII identifier is flagged (USC019). |
permittedScripts | array<string; length 0..40>; max 40 items | no | Used with permitted-scripts. Default Latin, Common, Inherited. |
scanExcluded | boolean | no | Also scan paths the upstream scanner skips (node_modules/, vendor/, dist/, build/, .lock, .min.js, images, archives). Default false. |
Example request body
{
"files": [
{
"path": "src/auth.js",
"content": "const isAdmin = false;\nif (isAdmin // check later ) {\n grant();\n}\n"
}
]
}
Result
The response is { "data": ..., "_provenance": ... }. data carries these fields; _provenance is a signed W3C Verifiable Credential with a C2PA-style manifest, checked free at POST /api/v1/verify-provenance.
| Field | Type | Required | Description |
|---|---|---|---|
verdict | string; one of "block", "warn", "pass" | no | block: a critical finding, or a high finding in a code or config file. warn: other findings. pass: none. |
verdictReason | string | no | |
riskScore | integer | no | 0-100: worst severity (critical 90, high 70, medium 40, low 15) plus 1 per further affected line, at most 10. |
status | string; one of "complete", "partial" | no | partial when files were skipped for size or findings were capped; the result is still signed. |
nextStep | string | no | |
topFindings | array<object> | no | |
source | object | no | Where the input came from: kind (files, diff, repo, pr), and for repo the owner/repo, ref and commit scanned. |
mode | string; one of "files", "diff" | no | |
summary | object | no | |
findings | array<object> | no | |
sarif | object | no | SARIF 2.1.0 log; columnKind unicodeCodePoints. |
skipped | array<object> | no | |
warnings | array<string> | no | |
explanations | array<object> | no | Model-written, each verified against the finding it names (id, ruleId and codePoints must match). |
llm | string; one of "ok", "unavailable", "skipped" | no | |
deterministic | object | no | Engine, finding count, verdict basis and known limits. Findings and verdict involve no model. |
Pay and connect
Available through: x402 (USDC on Base), MCP, RapidAPI, Apify.
Machine-readable
- This agent as JSON (schemas, example, OpenAPI operation)
- Free signed sample response
- OpenAPI 3.1 · Catalog · Index of every agent