XCAICX docs Product Contact

Security & threat model

What the design defends against, what it deliberately does not, and where the real boundaries are. Written to be shown to a customer's security team.

What leaves the camera#

DataLeaves?
Frames, crops, thumbnails, any imageryNever
Detections, boxes, tracksNever
Event contentsNever
Licence activation: device fingerprint, batch token, SDK versionOnce, at first boot, if online
Heartbeat: counts of inferences, frames, stream-seconds, events, per modulePeriodically, if online

That is the complete list. Inference runs on the unit; there is no upload path for image data because there is no code that could use one.

With cfg.offline = 1 the SDK never opens a socket at all, and building with -DXCAICX_WITH_TLS=OFF removes the HTTP client from the binary entirely. For a site that wants to verify rather than trust that, the second option is the one to offer: a binary with no network stack linked in cannot exfiltrate anything, and that is checkable with ldd and strings.

The licensing threat model#

What it stops#

Verified by the 45 checks in core/tests/test_license.cpp:

AttackResult
Flip a byte in the payloadBadSignature
Re-encode payload with a module enabled, keep the signatureBadSignature
Copy a licence to another cameraWrongDevice
Wind the clock back to dodge expiryClockRollback
Use a token past its term and graceExpired
Use a revoked licenceRevoked
Forge a batch key with your own Ed25519 key403 at activation
Present a validly-signed key never issued by this authority403 — no seat behind it
Replay a usage record to avoid billingDeduped server-side
Reboot to reset the metered counterCounters resume from disk

You can exercise every row yourself in the token lab, which runs real Ed25519 against a throwaway keypair generated in your own browser.

What it does not stop#

Do not

Offline licensing is deterrence, not DRM. An attacker with root on the camera and a disassembler can patch out the check. That is true of every software licensing scheme that runs on hardware the attacker controls, and any vendor who tells you otherwise is selling you something.

What the design actually buys:

  • Casual copying is dead. Device binding plus signatures stop the realistic threat: an integrator cloning one paid image onto fifty cameras.
  • Entitlements cannot be widened. Enabling a module you did not buy requires forging Ed25519, not editing a config file.
  • Seat accounting is server-side. Unit counts cannot be inflated on-device.
  • Tamper leaves evidence. Weak fingerprint sources are recorded per activation and surface in xcaicxctl fleet.

Escalating#

If the threat model demands more, the escalation is hardware, and the SDK already supports it as a deployment decision rather than a code change:

  1. Bind XCAICX_DEVICE_ID to a secure element, TPM or fused SoC serial.
  2. Have the bootloader verify SDK integrity as part of a signed boot chain.
  3. Keep the rootfs read-only with state_dir on the only writable partition.

Cryptography#

PropertyChoice
SignatureEd25519
Token formatXCAICX1.<base64url(payload)>.<base64url(sig)>
Signed bytesThe ASCII of XCAICX1.<base64url(payload)> — the encoded payload
VerificationOpenSSL libcrypto on the device; public key compiled in
Key custodyPrivate key server-side or in an HSM, never on a camera

Signing the encoded payload rather than re-serialised JSON means verification never depends on signer and verifier agreeing on key order or whitespace. The C++ verifier and the Python signer are independent implementations tested against each other's output, precisely because that drift is what breaks licensing systems in practice.

Server surface#

  • Interactive API docs are disabled in production. They grant no access on their own, but publishing the whole admin surface tells an attacker exactly what to aim at.
  • Admin key comparison is constant-time. A naive == leaks the prefix to a patient attacker.
  • The service refuses to boot without an admin key, rather than defaulting to an open admin surface.
  • /v1/usage trusts the token, not the body, for whose usage a record belongs to. Trusting body.license_id would let any device attribute usage to another account.
  • /v1/activate is rate-limited at the edge, since it is the one unauthenticated endpoint that mints credentials.
  • The service index carries no repository link and no admin endpoint listing.

Data at rest#

On the camera#

state_dir, mode 700, holds the unit token, usage counters, the spool, the cached revocation list and the clock high-water mark. The token is a credential: anyone who copies it gets a licence bound to that fingerprint, which is why binding matters more than file permissions.

Writes are tmp-file + fsync + rename, so power loss cannot corrupt state.

On the server#

The database holds customers, batches, licences (including live tokens), activations and usage. It is both a billing record and a customer list. Encrypt the volume, restrict access to the one process, and keep backups out of version control.

Reporting a vulnerability#

Email [email protected] with enough detail to reproduce. We will confirm receipt, tell you what we found, and tell you when a fix ships. If a fix requires firmware — as a signing-key compromise would — we will say so plainly rather than describing it as a configuration change.

Please do not test against production licensing infrastructure or against other people's cameras. If you need an environment to test against, ask and we will provide one.

For a customer's security review#

The questions industrial security teams actually ask, with the short answers:

QuestionAnswer
Does video leave the site?No. Inference is on-device; only counts are reported, and only if online.
Can it run with no network at all?Yes — offline = 1, and TLS can be compiled out entirely.
What does the heartbeat contain?Counts of inferences, frames, stream-seconds and events. No imagery.
What if your licensing server is unreachable?Cameras keep working. Usage spools locally and ships when the link returns.
What if your company disappears?Perpetual tokens keep verifying — the public key is compiled into the firmware and needs no server. Term licences stop at expiry plus grace.
Can you remotely disable our cameras?Revocation stops analytics on an online camera at its next start. It never stops the video path. An offline camera is unaffected.
What is stored on the camera?A licence token, usage counters and a revocation cache, in state_dir.

The fifth and sixth rows are the ones that decide industrial deals, and the honest answer is better than the comfortable one: revocation is real, it is scoped to analytics, and it cannot reach a camera that is not online.

Next#

Commercial software. Use requires a valid XCAICX licence token. Questions an integrator cannot answer from this page belong in an email to [email protected] — and, usually, in a fix to this page.

© 2026 AZMX AI · xcaicx.com