IOcrPort offers convenient inputs, not a safe ingestion boundary. The adapter invokes Tesseract and maps DTOs. File authorization, budgets, SSRF control, malicious image handling, and output retention remain owner responsibilities.
1. Actual method surface
| Method | Input | Current basic validation |
|---|---|---|
ExtractTextFromFileAsync | local path | non-blank |
ExtractTextFromBytesAsync | byte[] | delegated to SDK |
ExtractTextFromBase64Async | Base64 | delegated to SDK |
ExtractTextFromUrlAsync | URL string | non-blank |
RecognizeRegionAsync | path and rectangle | path, nonnegative origin, positive size |
GenerateCaptcha | width/height/length | synchronous SDK call |
RecognizeCaptchaAsync | byte[] | delegated to SDK |
There is no language hint, MIME, maximum bytes/pixels, or owner identity in the port. Samples must not invent them.
2. Preferred input path
Have the owner retrieve an authorized, scanned object and pass bounded bytes. Do not let an external request select a server path or URL.
// ① Resolve the file through trusted tenant and user context.FileAsset asset = await files.RequireReadableAsync( currentTenant.Id, currentUser.Id, command.FileAssetId, ct);
// ② Enforce scan, type, and size before allocating the byte array.ocrPolicy.EnsureEligible(asset);
byte[] image = await files.ReadBytesAsync(asset, ocrPolicy.MaxBytes, ct);
// ③ The adapter performs OCR, not owner authorization.Result<OcrResultDto> result = await ocr.ExtractTextFromBytesAsync(image, ct);3. Local path risk
File and region methods accept arbitrary paths and only reject blank input. A caller can target configuration, secrets, mounted volumes, or symbolic-link targets accessible to the process.
If path APIs remain, resolve logical IDs under a controlled root, compare canonical paths, reject links/devices, and verify file metadata after opening. A business API should accept object IDs instead.
4. URL risk
The URL method delegates to the SDK without scheme, host, DNS, redirect, timeout, or response-size policy. It presents SSRF and resource-exhaustion risks.
Download through a controlled client that validates every redirect, bounds connection/total time, bytes, Content-Type, redirect count, and decompression. Then call the bytes method.
5. Bytes, Base64, and image bombs
Bytes and Base64 have no limit. Base64 also adds encode/decode memory. A small compressed file can declare enormous dimensions or frames and exhaust decoder resources.
Limit encoded and decoded bytes, width, height, pixels, frames, color depth, metadata, and compression ratio. Validate magic bytes rather than extension/MIME, isolate vulnerable decoders, and enforce tenant CPU/concurrency budgets.
“Scanned” must be an actual state. The current Files finalize path itself does not provide a malware-scan guarantee.
6. Region bounds
The adapter does not load dimensions, validate the rectangle against the image, or protect x + width from integer overflow.
// ① Read bounded header metadata without decoding the entire image.ImageInfo info = await imageInspector.ReadHeaderAsync(asset, ct);
// ② Promote to long before addition to avoid Int32 overflow.long right = (long)command.X + command.Width;long bottom = (long)command.Y + command.Height;
if (command.X < 0 || command.Y < 0 || command.Width <= 0 || command.Height <= 0 || right > info.Width || bottom > info.Height) return OcrErrors.InvalidRegion;7. Result semantics
An SDK Success=false becomes a failure, so a successful OcrResultDto.Success is always true. The DTO also contains Text, RawText, Confidence, and Regions.
All are untrusted provider output. Text may contain PII or privileged material; RawText can be more sensitive; low confidence requires policy or review; regions reveal layout; and output length needs a budget. Never log document text by default.
8. Exception boundary
The adapter catches Tesseract, Leptonica, and IO exceptions. URL, Base64, argument, HTTP, memory, and other runtime exceptions may escape.
Return stable endpoint problem codes, retain details only in restricted diagnostics, and include a correlation ID. Preserve cancellation rather than relabeling it as provider failure.
9. Synchronous CAPTCHA exception
GenerateCaptcha is the only synchronous non-Result operation. Unavailable mode and selected adapter failures throw InvalidOperationException.
try{ // ① Current CAPTCHA generation is synchronous and has no cancellation token. CaptchaResultDto captcha = ocr.GenerateCaptcha(width: 240, height: 80, length: 6); return Ok(captcha);}catch (InvalidOperationException ex){ // ② Normalize unavailable/provider failure at the owner boundary. logger.LogWarning(ex, "OCR captcha is unavailable"); return Problem(OcrErrors.ProviderUnavailable);}Long term, use asynchronous Result<CaptchaResultDto> or a separate service for consistent failure and capacity control.
10. Data governance
Define classification, purpose, provider location, retention, deletion, and audit for both input and output. Local processing still requires temporary-file, core-dump, log, and diagnostic controls.
Do not persist RawText by default. Prefer required structured fields, confidence, provenance, and engine/language-pack version. Human corrections need actor and revision audit.
11. Test matrix
Cover empty/huge bytes, invalid Base64, fake MIME, truncated and multi-frame images, decompression bombs, path traversal/link, SSRF/redirects, region overflow, cancellation, low confidence, log redaction, and unavailable CAPTCHA.
Use licensed, small fixtures. Fuzzing needs process resource limits. Pin quality canaries by language/document type across engine upgrades.
An OCR consumer review should record:
- accepted document/image formats;
- encoded bytes, decoded pixels, and frame limits;
- the authoritative malware-scan state;
- whether local path and URL methods are prohibited;
- language-pack and engine versions;
- confidence threshold and human-review path;
- whether RawText is persisted;
- output retention and deletion SLA;
- tenant CPU/concurrency quota;
- redaction rules for support diagnostics.
12. Operations and source check
Measure queue/execution latency, rejection reason, success, low confidence, engine failure, peak memory, and language-pack version without text, path, or URL labels.
Capacity tests must use the same process limits and language packs as production.
Any relaxed input budget requires a documented threat-model and capacity review.
# ① Review the exact OCR call and exception surface.rg -n "ExtractText|RecognizeRegion|GenerateCaptcha|catch" \ src/Platform/ToolConnectors/BitzOrcas.Platform.ToolConnectors.Infrastructure/Ocr -g '*.cs'