Product · How it works

How LogVeil sanitises a diagnostic bundle

This overview is written for the engineer or the security cell evaluating LogVeil. It restates the product's specification for a reader: mechanisms, not adjectives. It shows no screens — until a real installation is running, every excerpt in these pages is a typeset specimen with synthetic values, labelled as such. The vocabulary is the one the attestation itself uses; the companion glossary defines each word.

What it is not

These are commitments, not omissions. LogVeil is not a data-loss-prevention gateway, a SIEM, a log pipeline or a ticketing system. It is not a general document-redaction service; document formats are handled only insofar as they appear inside OEM bundles. It is not a cloud service — a hosted instance is a demonstrator on synthetic data only. It makes no claim of certainty that nothing sensitive remains; the attestation is the product’s honesty mechanism. And there is no automated upload to OEM support portals in the first release.

Threat model

Threat model and sensitivity classes

in development

The recipient — the OEM's technical assistance centre — is assumed to read everything, including metadata, to run automated analysis, and to keep the bundle indefinitely. Intermediaries — e-mail, upload portals, vendor ticketing, contractors — mean a sanitised bundle must be safe if it appears on the internet. An insider on the LogVeil host must not be able to reverse what they are not cleared to, and a database administrator must not be able to read the map. Out of scope: an adversary who holds the tenant key, side channels on the host, and the customer's own network security.

Thirteen classes

Recognisers, transforms, allowlists and the attestation are all keyed by thirteen sensitivity classes. A policy may enable, disable or retarget any of them; the defaults are below.

The thirteen sensitivity classes, what each covers, and its default treatment
Class What it covers Default treatment
S1 IPv4 addresses management and data addresses, subnets, ranges, in every enumerated encoding prefix-preserving cipher into the output pool; dictionary pins first
S2 IPv6 addresses global, unique-local, link-local, EUI-derived interface identifiers per-prefix cipher plus a keyed interface identifier
S3 hardware addresses ARP tables, DHCP leases, wireless clients vendor prefix kept, device part remapped under key; broadcast, multicast and zero preserved
S4 hostnames, domains, DNS names device names, directory domains, reverse-DNS names keyed token per label; the customer's site-code dictionary; a top-level-domain allowlist
S5 location site names, civic and GPS records, SNMP system location, time zones by policy dictionary or typed token
S6 hardware identity serial numbers, asset tags, chassis identifiers, licence keys, SNMP engine identifiers typed token, consistent per value
S7 credentials and keys password hashes, SNMP communities, RADIUS and TACACS secrets, pre-shared keys, API keys, private keys, TLS session secrets dropped and marked by class — never tokenised
S8 certificates PEM bodies, subject and alternative names, fingerprints, issuers body dropped; names rewritten as hostnames; fingerprint tokenised
S9 people usernames, e-mail addresses, phone numbers, engineers' names in filenames keyed token; dictionary for role accounts
S10 organisational identifiers autonomous-system numbers, VLAN names, SSIDs, site tags, object and policy names that encode sites, tenant names dictionary or keyed token, selectable per class
S11 paths and filenames member paths carrying hostnames, addresses or usernames; the bundle's own filename the transform of the class found inside
S12 free text comments, ticket references, descriptions keyword dictionary; an optional local-AI review flag that opens review items
S13 structure subnet sizes, host counts, timing, port mix not rewritten — declared in the attestation as a non-assertion

The residual-leak catalogue

Verification is designed against a versioned catalogue of nine leak classes: container metadata (tar header fields and extended records); gzip header filename, comment and timestamp fields; zip names, extra fields and comments; packet-capture block options and comments; payload copies and checksums inside captures; alternate encodings; semantic identifiers; structural leaks; and members that cannot be rewritten. Every entry maps either to a scanner that runs on every job or to a non-assertion in every attestation, and the catalogue’s version is recorded in the attestation.

Ingest

The bundle as it really is

in development

LogVeil understands the anatomy of the bundle — every member, every nested archive, every filename and header — and has no file-size ceiling.

Containers are detected by their bytes, never by their file extension,

and nested archives are walked to any depth. Handlers in early access cover tar in its three dialects, gzip, zip including its large-archive form, bzip2, xz, zstd, symmetrically encrypted GPG containers (the passphrase is supplied per job and never stored), plain single-file bundles and packet captures, which are recognised and declared; 7z and rar arrive with the full product.

Filenames and member paths are content.

The bundle's own filename, every member path, the owner names in tar headers, the original filename a gzip compressor recorded, zip comments and capture option strings all pass through the same recognisers and transforms as file bodies — because they leak too. Measured on real bundles in our lab: in one Catalyst Center bundle, 55 gzip headers were found carrying original filenames.

There is no size ceiling.

Inputs arrive by chunked, resumable upload or from a mounted path; workers stage to local scratch and process member by member with bounded memory, so a multi-gigabyte member is handled the same way as a small one. Before anything runs, the input's SHA-256 is recorded, and the job refuses to start if scratch space is below the policy's scratch multiplier times the compressed size — ten times by default — or if a member's declared size exceeds the decompression-bomb limit; scratch is wiped on completion or failure. Every job then has an inventory of the members discovered — path hash, size, detected type, depth, container chain — before any transform runs, and the attestation is later checked against it. A truncated or corrupt container is processed as far as it is readable; the truncation offset and unread byte count are recorded, and the attestation states it as a non-assertion. Ingest from SMB or NFS shares, a watched folder and an API token are full product.

LogVeil knows what a bundle family looks like inside — which members are logs, object dumps, certificates, database exports — through a profile for each family. A vendor or product not on the list is added by writing a profile — a declarative description of the bundle family — not by changing the engine.

Bundle formats, by status →

Detection

Three layers, in precedence order

in development

Detection runs in three layers, in precedence order. First, structure-aware content transformers mask by field name and grammar position — the address, hostname and serial keys of a JSON document, the elements of an XML document, the keys of a Perl object dump, the address, hostname and community lines of a Cisco configuration. Second, token-boundary-anchored recognisers with plausibility filters and context scoring find the values that structure does not announce. Third, per-bundle allowlists are compiled from the bundle’s own inventory — version files, object-identifier roots, product constants — together with the policy’s preserve list, so that things which look like addresses and are not are left alone.

False positives and the review queue

A candidate address is rejected or down-scored when it is really an object identifier (more than four dotted components), when it sits in a version, release, build or firmware context, when its first octet is implausible outside a known multicast context, or when it matches a product version pattern declared by the profile. Ambiguous hits go to the review queue, where a person accepts, overrides or marks them as preserved; they are never silently masked and never silently kept, and every decision is recorded and shown in the attestation. The engine is deterministic; it alone produces the map and the attestation.

The encodings, enumerated

Recognisers search every enumerated encoding of a value: dotted-decimal with and without leading zeros; decimal-integer and hexadecimal addresses; IPv4 addresses embedded in IPv6 form; the reverse-DNS forms of both; URL-encoded values; JSON escape sequences; base64 and hexadecimal blobs, decoded, scanned and re-encoded where the transformer knows the field is text in an encoding; and SNMP engine identifiers that embed an address. The list is finite and declared, and the attestation says so: an encoding outside it is a non-assertion, by name.

Content transformers and recogniser packs

Content transformers in early access rewrite values in place inside text lines, JSON, YAML, XML, key-value and INI files, CSV, Perl object dumps, Cisco IOS and IOS-XE configuration grammar, syslog lines and PEM certificates; they handle gzip inside tar and tar inside tar; and they treat sqlite databases and generic binaries as drop-or-pass by policy, with declaration. Full product: semantic rewriting of packet captures (headers, embedded copies of addresses, checksums recomputed), the text layer of PDF members, and database-export blobs, which today are dropped with declaration by default. Recognisers ship in packs — early access: core-network, secrets (the vendors’ password-hash grammars and secret-scanner-class patterns) and Cisco; in development: Check Point and Radware; planned: Infoblox, Fortinet, Juniper, Palo Alto Networks and location. Every recogniser declares its class, patterns, context terms, base score, plausibility filter and test vectors — positives that must match and planted look-alikes that must not — and the conformance harness runs them before a pack is accepted.

Two passes

Nothing is rewritten until the whole map exists

in development

Nothing is rewritten until the whole map exists. The first pass walks every member and collects the observed value set per class. The map is then compiled as a total function over the observed set — dictionary first, algorithmic fallback, validation against the output pool, and an injectivity check: no two originals may share a replacement, and no algorithmic output may collide with a dictionary target or with an observed unmapped value; on a collision the value is re-derived with a recorded tweak counter. The second pass rewrites. No unmapped value leaves the engine unless it is on the preserve list — silent pass-through would make reversal ambiguous.

Two passes and one compiled map: the first pass collects every observed value; the map is compiled — dictionary first, key-derived fallback — and checked so that no two originals share a replacement; only then does the second pass rewrite, and nothing unmapped leaves the engine unless it is on the preserve list. First pass — collect every member is walked and theobserved value set collectedper class; filenames, archivepaths and headers are content Compile the map a total function over theobserved set — dictionary first,key-derived fallback — with aninjectivity check: no twooriginals share a replacement Second pass — rewrite no unmapped value leaves theengine unless it is on thepreserve list; secrets aredropped and marked, nevertokenised NOTHING IS REWRITTEN UNTIL THE WHOLE MAP EXISTS Two passes and one compiled map: the first pass collects every observed value; the map is compiled — dictionary first, key-derived fallback — and checked so that no two originals share a replacement; only then does the second pass rewrite, and nothing unmapped leaves the engine unless it is on the preserve list. First pass — collect every member is walked and theobserved value set collectedper class; filenames, archivepaths and headers are content Compile the map a total function over theobserved set — dictionary first,key-derived fallback — with aninjectivity check: no twooriginals share a replacement Second pass — rewrite no unmapped value leaves theengine unless it is on thepreserve list; secrets aredropped and marked, nevertokenised NOTHING IS REWRITTEN UNTIL THE WHOLE MAP EXISTS

Drawn by code from the product’s specification; not a screen.

The seven stages of a job

  1. ingest

    Containers are detected by their bytes, never by their names, and nested archives are walked to any depth; the input is hashed before anything runs.

  2. inventory

    Every member discovered — path hash, size, detected type, depth, container chain — is recorded before any transform runs; the attestation is later checked against it.

  3. collect

    The first pass walks every member and collects the observed value set per class; filenames, archive paths and container headers count as content.

  4. compile

    The complete map is compiled before anything is rewritten — dictionary first, key-derived transforms as the fallback — and checked so that no two originals share a replacement.

  5. rewrite

    The second pass rewrites. No unmapped value leaves the engine unless it is on the preserve list; secrets are dropped and marked, never tokenised.

  6. verify

    A separate stage with its own code path re-scans the output with independent scanners and fails closed: a canary hit, an unresolved review item or a scanner error means no output.

  7. attest

    A signed Sanitisation Attestation records what was done, what was checked, by which scanners, with what result — and what is explicitly not asserted.

The same key gives the same replacement,

for the same value, across every member, across bundles and across time — so a support thread that spans several uploads stays coherent. Underneath is a per-tenant 32-byte master key with sub-keys derived per class; the key's identifier, never the key, is in every attestation; rotation applies to future jobs only.

Container hygiene.

Consistency extends to container metadata: the owner, group and link fields of tar headers and their extended records; the filename, comment and timestamp fields of gzip headers; zip names, extra fields and comments; and, with the capture transformer, the option blocks of packet captures. Where a rewrite changes a value's length, the rewritten member is spilled to scratch before its container header is written, so text members are never truncated or padded.

Byte-reproducible output.

A fixed modification-time policy (original, or zeroed by policy), a fixed owner, sorted member order, gzip headers written with a zero timestamp and no original filename, and the same compression family as the input mean that two runs of the same input under the same policy version and key produce byte-identical output and an identical attestation body. Per-member checkpoints let a job resume from the last completed member after a crash.

Encrypted bundles.

A bundle decrypted with the operator's key at job start is re-encrypted for the recipient with a key the operator chooses. Whether a given vendor's process accepts a sanitised bundle is a question for that vendor; LogVeil satisfies your own release policy before anything leaves your network — what may go out, under whose rules, with what record — and that decision is yours whatever a vendor's process says.

Verification

Verification, fail-closed, and the attestation

in development

A separate verification stage re-scans the output with independent scanners, fails closed, and signs an attestation that also says what is not claimed.

Five scanners, two of them independent

Verification is a separate stage with its own code path. It runs on the output bundle, never on the engine’s internal state, with five scanners: the engine’s own recogniser packs re-run on the output; a differential canary scan that searches for every original value in the compiled map — and every value in the dictionary’s domain — in every enumerated encoding, across every output member and every container-metadata field; two independent secret scanners, gitleaks and detect-secrets, run unmodified over the files; a container-metadata scanner that checks tar, gzip, zip and capture fields against the residual-leak catalogue; and a binary and entropy classifier that lists every passed-through binary member by name. Any hit in the canary scan fails the job. Fail closed: a job with an unresolved review item, a canary hit or a scanner error produces no downloadable output — there is no partial output to download, ever.

The Sanitisation Attestation

Every output bundle is accompanied by a Sanitisation Attestation: a canonical-JSON manifest signed with the installation’s Ed25519 key, compatible with common signing tools, that records the input’s hashes and size; the member inventory and, per member, the action taken — rewritten, dropped, passed through as a binary, passed through as allowlisted — with before-and-after hashes and substitution counts per class; the policy’s identifier, version and hash; the versions of the profile, the recogniser and transform packs, the engine and the residual-leak catalogue; the tenant’s key identifier; the output pool; the scanners run, with their versions and results; the operator, the reviewer and the timestamps, with the time source declared, because an air-gapped clock is unverified; the review-queue decisions; a truncated container’s offset and unread bytes; and the non-assertions — the statement of what LogVeil is not claiming about this output: sensitivity classes the policy did not cover; encodings outside the enumerated list; binary members passed through unread, by name; structural inference that was not rewritten; member formats it did not recognise; and anything a reviewer chose to override. An attestation without them would be a marketing document, not a record.

The attestation, in full →

Utility for the recipient, and verifying without the server

Alongside verification, utility checks make sure the output is still worth sending: a structural diff of member counts, sizes and line counts; well-formedness of JSON, XML and YAML after rewriting; referential integrity — every masked value appears in exactly the positions the original did; and a check that planted benign look-alikes, such as version strings, survived untouched. Protocol-hierarchy and checksum regression for packet captures is full product. A standalone command, logveil verify, checks an output bundle against its attestation — hashes, membership, signature — without the LogVeil server, on any machine; a human-readable report renders the attestation, with the reviewer’s decisions, for the case file.

Reversal

Reversal under control

in development

When the TAC replies about a masked address, your engineer can translate it back — and nobody else can.

When the TAC replies about a masked address, the customer's engineer can translate it back — and nobody else can. The map is compiled before anything is rewritten and stored encrypted, and reversal is per token: a person holding the Reverser role submits one masked value and a written justification; a second person — a Reviewer or the Platform Admin — approves; the original is returned for that one token; and the whole exchange is written to the append-only, hash-chained audit log. Bulk export of the map is not a function of the product. The two-person rule is enforceable by configuration in early access and on by default in the full product.

The policy and the dictionary →

Roles and keys

Roles, access and keys

in development

Seven roles, enforced by the server

Seven roles, enforced by the server on every request. The Platform Admin manages users and roles, tenants, keys, plugins, retention and system settings — and cannot reverse a token. The Policy Author creates, edits, tests and signs policies and dictionaries for a tenant. The Operator uploads bundles, runs jobs with an approved policy, views findings and downloads outputs and attestations. The Reviewer resolves review-queue items and approves a job for release. The Reverser looks up the original of a masked token, only with two-person approval. The Auditor is read-only over jobs, policies, the audit log and attestations. The Plugin Publisher signs and installs plugin packs. Local accounts use Argon2id password hashing, lockout and session expiry; every state-changing action is written to the audit log with actor, tenant, job and before-and-after hashes; there is no self-registration and no password reset by e-mail, so resets are administrator actions. Directory federation, single sign-on, multi-factor authentication with hardware keys for the Reverser and Platform Admin roles, and per-tenant isolation are full product.

Keys, custody and retention

Each job's map is stored encrypted with AES-256-GCM under a per-job data key; a per-tenant key-encryption key wraps the data keys — envelope encryption — and the key-encryption key is never at rest in plaintext. In early access it is unwrapped at service start from a passphrase held by the Platform Admin, entered rather than configured — the early-access key ceremony, labelled as such in the admin screen. Split-key custody (Shamir shares) or a hardware token are full product; keys sealed to a TPM are the appliance's. Every reversal, key operation and policy signature is written to the audit log. Maps expire per tenant policy — the default is retention while the support case is open plus 180 days — and destruction is a two-person, audited action; retention policy and destruction are full product.

Plugins

Plugins and profiles: how a new vendor arrives

in development

The engine has five kinds of plugin, each with a versioned interface. A container handler detects a container by its magic bytes, iterates its members and writes members back. A content transformer claims a member by type or profile hint, collects observations in the first pass and rewrites the member against the map in the second. Recogniser packs and transform packs carry the detectors and the replacement rules. A bundle profile is declarative YAML — detection rules, member classification by path pattern, member actions, section splitters, decrypt hooks, allowlists and canary fixtures. Adding an OEM never touches core code: a profile plus, only if a new member grammar exists, a content transformer. A conformance harness, logveil plugin test, runs a synthetic bundle through the pipeline and compares the attestation to the expected manifest; recall and the over-mask rate are gates. Packs are versioned and hashed, and every attestation lists the packs used; publisher signatures verified on install, and third-party plugins running out of process in a sandbox with no network and a file-in, file-out contract, are full product.

The user interface

The user interface, in words

in development

An operator must be able to answer "what is in this bundle, what will change, what did change, and what am I signing" without reading raw files; every screen works in light and dark, is keyboard-first, and loads nothing from outside the deployment. The screens of early access are Jobs — upload or path ingest, choice of policy version, a status timeline through ingest, inventory, collect, compile, rewrite, verify and attest; the Bundle Explorer — the member tree with each member’s type, size and action, a sensitivity heat map of hits per class, and a member view with before and after side by side and the class and rule behind every hit; the Review queue; the Policy editor — the dictionary table with overlap and pool-collision validation, class settings, the preserve list, member actions, the canary-corpus test, and signing; the Attestation viewer; the Reversal console; and Admin — users, roles, tenants, key status, plugins and versions, the audit log with export. The application is a static single-page application served from the same origin as the API, with a content-security policy that allows only its own origin, self-hosted fonts, no analytics, no error-reporting service and no content-delivery network. A topology graph of the masked addresses — so the engineer can see that structure survives — timelines, and Hindi interface strings are full product. No screen is reproduced here: until real screens exist, LogVeil is described, not depicted.

AI

AI: optional, off by default

in development

The engine that finds and rewrites values is deterministic, and it alone produces the map and the attestation. AI is disabled unless a Platform Admin enables a provider, and the interface then shows which provider, where it runs and what it may see. Three interchangeable backends exist: a local model server on the same host, pinned to local models with egress blocked at the container network; a privately hosted open model, for demonstrations only; and an external commercial API, for demonstrations only, labelled with its jurisdiction and retention terms. The boundary is enforced in code, not configuration: anything that has not passed verification — raw members, first-pass observations, review-queue candidates — can be sent only to the local provider, and the call site type-checks this; an external provider receives verified output or synthetic data, nothing else. AI drafts recognisers, profiles and canary fixtures from public samples at development time; at run time, locally only, it gives a second opinion on residual free text and opens review items for a person to resolve; with any provider, it explains a verified attestation in plain language. AI never changes a map or an attestation. On the appliance an open model runs on the local GPU.

Deployment: the offline kit →

Status, and the next step

LogVeil is in development. An early-access programme opens after our first field trial.

Early access is a free, guided proof-of-concept on your own bundles inside your own network: you choose the bundles, you write the policy with our help, and you keep the key; we hand over the offline kit, run the first jobs with your engineers, and leave you with the attestations.

Request early access