CocoIndex Plus security & data flow

For security and platform teams reviewing CocoIndex Plus, the Enterprise Edition: what runs where, every network destination and what it receives, what the engine stores, and how to verify, harden, and air-gap a deployment.

Version
v 1.0.62

CocoIndex Plus — the CocoIndex Enterprise Edition, distributed as the cocoindex-plus package — is software you run yourself. This page states what it does on the network and on disk, in terms you can check against your own deployment. It was checked against v1.0.53 (released 2026-10-15).

Architecture & trust model

CocoIndex Plus is a Python library with a compiled Rust engine. It runs inside your own process — your application, a job you schedule, or the cocoindex CLI — with that process’s identity and permissions.

  • It isn’t a service. It opens no network listener (no HTTP server, admin console, or port) and has no user accounts, SSO, or authentication of its own. Your OS, container platform, or scheduler decides who can run a pipeline; the credentials you give a pipeline decide what it can reach.

  • CocoIndex operates nothing in the data path and receives none of your data. There’s no telemetry, usage analytics, crash reporting, or update check: the anonymous usage telemetry of the open-source edition is compiled out of the Plus build. Metrics export (v1.0.59 and later) is not telemetry to us: it is off unless you configure it, and it sends only to the OpenTelemetry endpoint you name. The one connection to a service we designate is license validation, and an offline-entitled license doesn’t make it. You can check the compiled engine yourself — the only service URL in it is Keygen’s (docs.rs appears in a TLS library’s error message; from v1.0.59, http://localhost is the OpenTelemetry exporter’s default collector address, localhost:4318, used only when you enable metrics export without naming an endpoint):

    sh
    unzip -p cocoindex_plus-*.whl 'cocoindex/_internal/core*.so' \
      | strings | grep -oE 'https?://[A-Za-z0-9.-]+' | sort -u
    # http://localhost        (v1.0.59 and later)
    # https://api.keygen.sh
    # https://docs.rs

    One item in the package isn’t code: the v1.0.53 package description (the wheel’s METADATA, copied from the open-source README) embeds a 1×1 tracking image from static.scarf.sh. Nothing in CocoIndex Plus loads it, but a package browser or index mirror that renders the description as HTML would. Releases after v1.0.53 replace that description with a Plus-specific one without the image.

  • Your data stays in systems you choose. Sources, targets, the engine’s state store, and model endpoints are all yours to configure. Network egress lists every destination.

The cocoindex CLI has five commands:

  • update and drop load your app’s code and run it (drop reverts the target states the app created, then clears its state).
  • ls and show inspect the state store. Given an app target, they import your app’s module, and ls also starts its environment, which runs your lifespan code; ls --db PATH only reads the database.
  • init scaffolds a project.

The CLI reads environment variables from --env-file, or else from a .env file in the current directory or the nearest parent directory that has one — run it from a directory you trust. litellm, once imported, also loads a .env file, the first one found walking up from its install directory, unless LITELLM_MODE is set to something other than DEV. Neither overrides variables that are already set (litellm does with LITELLM_DEV_ENV_HOT_RELOAD=True).

Network egress — the complete list

DestinationWhenWhat it receives
Your sources and targets — databases, object stores, queues, code hosts, SaaS APIsWhen your pipeline reads or writes themYour data, under credentials you supply
Your Postgres state store, if you use oneThroughout a runEngine state (what it holds)
Your OpenTelemetry collector or metrics backend, if you configure onePeriodically and at shutdown, only when OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_METRICS_ENDPOINT or OTEL_METRICS_EXPORTER=otlp is set (v1.0.59 and later)Pipeline metrics, no pipeline data (what the labels contain)
Your model providersOnly when your code calls LiteLLMEmbedder, LiteLLMTranscriber, or LlmPairResolver, or gives a Chonkie semantic chunker a hosted embedding modelThe text or audio you pass in (per operation)
Hugging Face (huggingface.co and file hosts under hf.co)Each time a Hugging Face model or tokenizer loadsNo pipeline data: model files and metadata (details below)
github.com (tree-sitter grammars)When ChonkieCodeChunker is built without its grammars cachedNo pipeline data: grammar downloads
raw.githubusercontent.com (litellm metadata)When litellm is imported, and for some Claude requestsNo pipeline data
api.keygen.shAt most once per process start, standard licenses only: at the first start after the cached validation is 24 hours old (details)The license key — nothing else

That’s the complete list. How you control each destination:

  • Sources, targets, and the state store: you choose every endpoint and credential. The GitHub and GitLab connectors default to api.github.com and gitlab.com; point them at your own instance to keep traffic internal. For the state store, choose its TLS mode.
  • Model providers: you name the model, and the endpoint and API key are yours. There’s no CocoIndex default endpoint, and a self-hosted endpoint works. Some providers make their own metadata calls — litellm’s huggingface/ embedding provider, for one, looks the model up on huggingface.co.
  • Metrics export: off by default. You choose the endpoint and its credentials with the standard OpenTelemetry variables, and OTEL_SDK_DISABLED=true turns it off whatever else is set.
  • License validation: an offline-entitled license sends nothing.

Metrics export

Exported metrics are counts and durations; the values never include your data. The labels on them name parts of your deployment, so treat a metrics backend as you would your logs:

  • the environment name and app name;
  • coco.stats_group titles and processor (function) names;
  • target provider names and container keys, such as a table name or an output directory;
  • target action sink names, which are your connector callbacks’ qualified names;
  • exception type names, such as ValueError — never exception messages;
  • the names and values of counters your code adds with coco.metrics.

Component paths, row and file keys, and exception messages are not exported. See the metrics reference for every metric and label.

Third-party library requests

The other rows come from libraries your pipeline loads, and happen only when it uses the operations that load them. We checked them in huggingface_hub 0.36 and 1.27, transformers 4.57 and 5.15, chonkie 1.6 and 1.7, tree-sitter-language-pack 1.8 and 1.14, and litellm 1.96–1.105:

  • Hugging Face: SentenceTransformerEmbedder, the Chonkie semantic and neural chunkers, and a Hugging Face tokenizer name each load a model or tokenizer, which downloads it — files come from hosts such as us.aws.cdn.hf.co and cas.xethub.hf.co — or checks a cached copy for updates. Two other requests:

    • For a model published only as .bin weights, transformers asks Hugging Face’s conversion service (safetensors-convert.hf.space) to convert it, sending the model’s name and your Hugging Face token, if one is set. DISABLE_SAFETENSORS_CONVERSION=1 turns this off.
    • huggingface_hub 1.27 fetches a list of AI-agent tools from huggingface.co at most once a day, to label its requests. HF_HUB_DISABLE_TELEMETRY=1 turns this off.

    HF_HUB_OFFLINE=1 stops all of these. The exception is chonkie 1.7’s tokenizer loader, used for a Hugging Face tokenizer name, which ignores HF_HOME and HF_HUB_OFFLINE and reads only ~/.cache/huggingface/hub. Pre-stage the models in that directory.

  • tree-sitter grammars: ChonkieCodeChunker downloads grammars, as native libraries, from the tree-sitter-language-pack project’s GitHub releases (served from release-assets.githubusercontent.com). Under chonkie 1.7, building the first chunker downloads all of them, about 500 MB. Pre-download them.

  • litellm metadata: litellm fetches its model cost map when it’s imported, and a beta-headers config for Claude requests that carry beta headers. Set LITELLM_LOCAL_MODEL_COST_MAP=True and LITELLM_LOCAL_ANTHROPIC_BETA_HEADERS=True to use the copies bundled with litellm.

License validation

The engine validates the license key in COCOINDEX_PLUS_LICENSE_KEY during import cocoindex, before anything else runs; if validation fails, the import fails. A license change never stops a running process: validation happens only at start. Which of two lanes a key takes is fixed when we issue the license.

Offline-entitled license — no network request. The key is a signed license: the engine checks its Ed25519 signature against a public key compiled into CocoIndex Plus, confirms it was issued under our offline policy and for our account, and enforces the expiry embedded in it. That expiry can’t be extended, and nothing can revoke the key remotely — renewal means we issue a new key.

Standard license — at most one HTTPS request per process start. A start within 24 hours of the last successful validation (the default COCOINDEX_PLUS_LICENSE_REVALIDATE_AFTER, in seconds; 0 validates at every start, values above one week count as one week) uses the cached answer and sends nothing; the first start after that validates online:

  • The request: POST https://api.keygen.sh/v1/accounts/<CocoIndex account ID>/licenses/actions/validate-key with the body {"meta":{"key":"<your license key>"}} and JSON
    Content-Type/Accept headers. No hostname, machine fingerprint, usage data, or pipeline data is sent. Keygen, as the receiving service, sees the source IP address and time, and records the license’s last validation.
  • The answer must be signed. The response has to carry a valid Ed25519 signature from the same compiled-in key, so a forged or altered answer can’t validate the license.
  • Five-second limit. If Keygen can’t be reached, doesn’t answer within 5 seconds, or answers without a signature, the engine falls back to its cached answer.
  • Revocation latency. A license we suspend, revoke, or let expire keeps working on a machine that validated it for at most the revalidation interval. Set COCOINDEX_PLUS_LICENSE_REVALIDATE_AFTER=0 where every start must check.
  • TLS: the engine connects with rustls against a compiled-in set of public CA roots, not your operating system’s trust store. It honors the HTTPS_PROXY, ALL_PROXY, and NO_PROXY environment variables (not OS proxy settings), so a TLS-inspecting proxy must exempt api.keygen.sh.

The cached answer lets a standard license ride out a Keygen outage — it is not an offline mode:

  • Only a fresh answer saying the license is valid is cached, in license_info.json under $XDG_STATE_HOME/cocoindexplus/ (default ~/.local/state/cocoindexplus/) on Linux, or ~/Library/Application Support/io.cocoindex.CocoIndexPlus/ on macOS.
  • It’s used only for the key it was issued for (the record carries a SHA-256 digest of that key), and its signature is checked again every time it’s read. Within the revalidation interval it stands in for the request; after that, only when no signed answer arrives, and only while Keygen’s answer is at most one week old. Past that, import cocoindex fails until Keygen is reachable again.
The license cache contains the license key

The cache stores Keygen’s signed response verbatim — the signature covers the whole body, so it can’t be trimmed — and that response includes the license record, key included. In v1.0.53, the file gets your process’s default permissions (0644 under the common umask 022): keep the service account’s home directory private, or chmod 600 the file. Releases after v1.0.53 create the file readable by its owner only (mode 0600) and rewrite it at every process start that validates online, so after an upgrade, the first such start replaces the copy an earlier release wrote.

We recommend offline-entitled licenses for production and for locked-down evaluations: nothing leaves your network for licensing, and starting a process never waits on Keygen. Ask us for one. The installation guide covers setting either kind.

What CocoIndex Plus stores

Everything below lives on infrastructure you control. Retention is yours.

The state store is where the engine keeps what it needs for incremental updates. It’s an LMDB directory by default, or a Postgres database when the path given by COCOINDEX_DB (or Settings.db_path) is a postgres:// or postgresql:// URL — see State storage. It holds:

  • Component paths, built from the keys your code passes — typically source identifiers such as file paths or record keys.
  • For each target state, its key (a row’s primary key, a file name) and the connector’s tracking record. The built-in connectors track rows, files, and messages by a fingerprint of the value, not the value itself, and track tables, collections, and indexes by their declared schema. The Postgres connector’s SQL-command attachments record their setup and teardown SQL verbatim, so keep secrets out of that SQL.
  • Memoized results of @coco.fn(memo=True) functions and memoized components — whatever they return (chunk text, embeddings, model output), along with fingerprints of their inputs and code, and the state that decides whether a memo is still valid (for a file, its modification time and a content fingerprint).
  • Values your code persists with coco.use_state.

So the state store can hold copies of, and values derived from, your source data: protect it like the source.

Encryption at rest comes from your storage: CocoIndex Plus doesn’t encrypt the state store itself, so use disk or volume encryption for LMDB and your database’s encryption for Postgres. LMDB’s data files are created readable by their owner only (mode 0600); the directory around them follows your umask.

Other local files:

  • The license cache, for standard licenses.
  • The Hugging Face model cache (~/.cache/huggingface, or HF_HOME), when a local model is used.
  • tree-sitter-language-pack’s grammar cache, when ChonkieCodeChunker is used.

Removal: cocoindex drop (or App.drop()) reverts the target states an app created — dropping tables, deleting rows — then clears the app’s state. On Postgres, that drops the app’s tables. On LMDB, it empties the app’s sub-database without shrinking or scrubbing the file, so freed pages can keep old bytes until they’re reused; to destroy LMDB state, delete its directory.

Securing the state store

Postgres state store

The sslmode values are libpq’s, with these meanings:

sslmodeEncryptedCertificate chain verifiedHostname verified
disableno——
allow, prefer (the default)if the server offers TLSnono
requireyesnono
verify-cayesyesno
verify-fullyesyesyes

The default, prefer, neither requires nor verifies TLS. Use sslmode=verify-full. The verifying modes trust your operating system’s CA store, and sslrootcert=/path/to/ca.pem adds your private CA to it rather than replacing it (unlike libpq). So don’t rely on verify-ca: since it skips the name check, it accepts any certificate a public CA has issued, for any name. sslrootcert is rejected unless the mode verifies. Two limits of the TLS stack:

  • The server certificate must be signed by a separate CA certificate; a self-signed server certificate can’t be verified, even through sslrootcert.
  • verify-full matches names against the certificate’s subject alternative names only, not its common name.

Only the DSN configures the connection: libpq’s environment variables (PGSSLMODE, PGPASSWORD, …), ~/.pgpass, and ~/.postgresql/root.crt aren’t read. Client-certificate authentication (sslcert/sslkey) isn’t supported, so a password, if the server needs one, goes in the DSN — treat COCOINDEX_DB as a secret, and note that the v1.0.53 CLI prints it (Logging). Give CocoIndex its own role and, ideally, its own schema (PgSettings(schema=...) or COCOINDEX_PG_SCHEMA); State storage lists the privileges the role needs.

Who can read and write it

  • Read access exposes what the state store holds: component paths, target-state keys, recorded SQL, and memoized results. cocoindex ls --db is just a reader.
  • Write access amounts to control over your pipeline’s outputs. A memoized value is decoded with msgpack, or, for types that need it, with a restricted unpickler that resolves only an allow-list of types: Python’s basic built-ins (numbers, strings, bytes, lists, tuples, dicts, sets, None, and type), pathlib paths, uuid.UUID, datetime values, NumPy arrays, and the types you register with @coco.serialize_by_pickle or @coco.unpickle_safe (see Serialization). That blocks the usual pickle attack — a payload that names an arbitrary function such as os.system — but it doesn’t make a forged entry harmless. Whoever can write the state store chooses the memoized values your pipeline reads back, which flow into your targets as if your code had produced them, and allow-listed types are constructed from the stored data. A forged tracking record can also make the next run delete data in your targets: the engine removes target states it believes it created but your code no longer declares. And because a Postgres SQL-command attachment runs its recorded teardown SQL when it changes or goes away, a forged record there runs arbitrary SQL with the pipeline’s database role.

Treat write access to the state store like write access to your targets — and, where you use SQL-command attachments, like the ability to run SQL as the pipeline. Grant it only to the pipeline’s own service identity.

Logging & audit

  • Engine logs (Rust tracing) go to standard output. RUST_LOG sets the filter; the default is info.
  • Python logs go through Python’s logging under cocoindex.* logger names, so your application’s logging configuration applies. The CLI configures it from COCOINDEX_LOG_LEVEL (default WARNING) and writes to standard error.
  • What appears in logs: engine messages can include component paths and target-state paths, and a failed component is logged at ERROR with its exception and traceback — so messages raised by your code or a connector, which may contain data values, can reach your logs. Apply your usual log retention and access controls.
  • The CLI prints the state store’s location: cocoindex ls always, and update and drop unless you pass --quiet. In v1.0.53 that’s the full Postgres DSN, password included, so don’t let CLI output from a password-bearing COCOINDEX_DB reach shared logs. Releases after v1.0.53 mask the password.
  • Metrics (v1.0.59 and later) go only to an OpenTelemetry endpoint you configure, and only when you configure one; see Metrics export for what their labels contain.
  • No audit log. CocoIndex Plus has no users of its own to audit. Use your platform’s controls for who runs pipelines, and your databases’ audit features for the state store and targets. Logs go only to your process’s standard output and standard error, or wherever your Python logging configuration sends them.

AI/ML data handling

CocoIndex trains no models and never trains on customer data — it receives none. Model calls happen only where your pipeline code invokes an AI operation, and go only to the model and endpoint you configure, under your keys. The operations, and what each one sends:

OperationWhere it runsWhat leaves the process
LiteLLMEmbedder (LiteLLM)Your chosen providerThe texts you embed, in batches — plus, the first time an embedder needs its vector dimension, the probe text "hello"
LiteLLMTranscriberYour chosen providerThe audio you transcribe, with its file name
LlmPairResolver (entity resolution)Your chosen providerPer call: the new entity’s name, the candidate names it may match, a fixed instruction prompt, your entity_type / extra_guidance, and the JSON schema of the expected answer; an answer that names no candidate is retried, up to retries (default 2) more calls
SentenceTransformerEmbedder (sentence transformers)LocallyNothing; the model is downloaded from Hugging Face unless you pass a local path, and trust_remote_code stays off unless you turn it on
Chonkie semantic and neural chunkers (Chonkie)Locally, with a local modelNothing; their default models, minishlab/potion-base-32M and mirth/chonky_modernbert_base_1, download when a chunker is constructed. A hosted embedding model for the semantic chunker (OpenAI’s text-embedding-*, Cohere’s embed-*, Jina’s, …) sends it the text being chunked
Chonkie recursive chunkerLocallyNothing; the default character tokenizer is built in, while a Hugging Face tokenizer name downloads that tokenizer
Chonkie code chunkerLocallyNothing; the first chunker downloads tree-sitter grammars unless they’re cached
Text splitting, code chunking, and symbol extraction (text ops, code elements)Locally, in the Rust engineNothing

For the LiteLLM-based operations, the model string you pass selects the provider. LiteLLMEmbedder and LiteLLMTranscriber take api_base and api_key arguments; all three also read LiteLLM’s standard provider environment variables (such as OPENAI_BASE_URL or OLLAMA_API_BASE), so each can use an endpoint you host. Results you memoize — embeddings, model output, entity-resolution decisions — are stored in your state store.

Air-gapped deployment

  1. License: ask for an offline-entitled license.

  2. Packages: mirror the cocoindex-plus wheels (from our Keygen index) and their dependencies (from PyPI) into an index inside your network (supply chain).

  3. Local models and tokenizers: download each one on a connected machine, then copy the result to the service account’s ~/.cache/huggingface/hub on the target hosts. Use that default location rather than setting HF_HOME (or XDG_CACHE_HOME), because chonkie 1.7’s tokenizer loader reads only it. Then run in offline mode:

    sh
    # On a connected machine: stage into /tmp/hf-stage/hub
    HF_HOME=/tmp/hf-stage hf download minishlab/potion-base-32M
    # On each air-gapped host, after copying /tmp/hf-stage/hub
    # to ~/.cache/huggingface/hub for the service account
    export HF_HUB_OFFLINE=1

    Set HF_HUB_OFFLINE=1 even when everything is cached: without it, the Hugging Face client keeps trying to reach huggingface.co before it falls back to the cache. In our tests with the network blocked, loading three cached models took 2–7 minutes without the flag, depending on library versions, and about 5 seconds with it.

  4. Code grammars (for ChonkieCodeChunker): grammars are native libraries, so download them on a machine with the same OS, architecture, and tree-sitter-language-pack version as your hosts — or while building your image — then copy the directory that cache_dir() prints to the same path for the service account. Download all of them: chonkie 1.7 fetches the full set whenever fewer than 20 are cached.

    sh
    python - <<'EOF'
    import tree_sitter_language_pack as t
    t.download_all()  # about 500 MB
    print(t.cache_dir())
    EOF
  5. Model endpoints: point the LiteLLM-based operations at endpoints inside your network, and set LITELLM_LOCAL_MODEL_COST_MAP=True and LITELLM_LOCAL_ANTHROPIC_BETA_HEADERS=True.

  6. Everything else — sources, targets, the state store — is already yours to place inside the network.

Deployment hardening checklist

  • Installation: make our index the only source of cocoindex-plus — never --extra-index-url — and install from hashes (supply chain).
  • Identity: run pipelines as a dedicated, non-root service account. Keep its home directory (which holds the license cache) and the LMDB directory readable by that account only.
  • Secrets: supply the license key, DSNs, and provider keys as environment variables from your secret manager. The license key must be in the environment before import cocoindex; the CLI can’t load it from .env. A Postgres COCOINDEX_DB with a password is a secret too; on v1.0.53, pass --quiet to update and drop in automation.
  • State store: a dedicated database or schema and role, verify-full TLS, write access for the pipeline identity only, and backups.
  • One process per state database. Neither backend supports several processes sharing one state database yet, and nothing enforces this — make it a deployment rule (for example, one replica).
  • Capacity: up to 1,024 processing components run concurrently per app by default (max_inflight_components or COCOINDEX_MAX_INFLIGHT_COMPONENTS; see Concurrency control). The Postgres state store opens up to 65 connections per environment (pool_max_size of 64, plus one); keep that within your server’s max_connections. An LMDB directory holds at most max_dbs apps (default 1,024; COCOINDEX_LMDB_MAX_DBS) — a hard cap.
  • Network: no inbound access is needed. Outbound: your sources, targets, state database, and model endpoints, and your OpenTelemetry endpoint if you export metrics — plus api.keygen.sh for a standard license, and the third-party hosts for any models, grammars, and litellm metadata you haven’t staged or switched to local copies.
  • Model code: leave trust_remote_code off unless you trust the model repository’s code. Where Hugging Face access stays on, consider DISABLE_SAFETENSORS_CONVERSION=1 and HF_HUB_DISABLE_TELEMETRY=1.

Supply-chain verification

Distribution. CocoIndex Plus ships as binary wheels only — there’s no source distribution — from a private package index at Keygen. Fetching a package requires your install token; an anonymous request is refused. Wheels exist for Linux x86_64 and aarch64 (manylinux_2_28, glibc 2.28+) and macOS arm64 (11.0+), for CPython 3.11+ (abi3) and free-threaded CPython 3.14.

Package name. We publish cocoindex-plus to our index only. The cocoindex-plus project on PyPI is a placeholder we hold so no one else can claim the name there; installing it fails with a pointer to the installation guide. A cocoindex-plus from any other index isn’t CocoIndex Plus, and installing it would run someone else’s code in your build and at import cocoindex. The placeholder covers only PyPI, so make our index the only one your installer asks for cocoindex-plus, as the installation guide shows for each installer. Don’t add our index next to another as an equal or a fallback — pip’s --extra-index-url or PIP_EXTRA_INDEX_URL, uv’s unsafe-best-match strategy, or the equivalent in other tools — because a same-named package on the other index can then win, and if our index rejects your install token, those setups install from the other index alone, with a warning at most. Pinning the version doesn’t close the gap: for an equal version, pip can prefer the other index’s file. A hash check does — pip install --require-hashes, or uv’s lockfile.

As pip’s only index, ours answers every lookup and redirects names it doesn’t host to PyPI, so it receives the name of each package you install. uv asks an explicit index only for the packages pinned to it.

SBOM and notices. Each wheel embeds two records of the Rust crates compiled into the engine: a CycloneDX SBOM — 364 components in v1.0.53 — at cocoindex_plus-<version>.dist-info/sboms/cocoindex_py.cyclonedx.json, the location PEP 770 defines, and their license attribution, THIRD_PARTY_NOTICES.html. Neither covers the Python dependencies, which your installer resolves; generate their SBOM from your environment.

Build. Wheels are built on GitHub-hosted runners. The release job runs only for tags, in a deployment environment that admits only v* tags, and uploads to the index the same files it attests.

Build provenance. Every wheel has a SLSA v1 build-provenance attestation, signed through GitHub’s Sigstore instance with the identity of our release workflow. Our source repository is private, so GitHub serves these attestations only to accounts that can read it; ask us for the attestation bundle (a .jsonl file) for the release you install, then verify each wheel against it — no GitHub credentials needed:

sh
gh attestation verify \
  cocoindex_plus-1.0.53-cp311-abi3-manylinux_2_28_x86_64.whl \
  --bundle <bundle>.jsonl \
  --repo cocoindex-io/cocoindex-plus \
  --signer-workflow cocoindex-io/cocoindex-plus/.github/workflows/release.yml \
  --source-ref refs/tags/v1.0.53

The command exits non-zero if the wheel was modified, or was built from another tag, repository, or workflow.

Recommended: mirror the wheels into your own package index, verify them there, and install with pinned versions and hashes. If that index also proxies PyPI, have it serve cocoindex-plus only from the mirrored wheels — for example, by excluding the name from the PyPI proxy. The Rust crates compiled into the engine are pinned by our lockfile; the Python dependencies are version ranges that your installer resolves, so lock them on your side too. On ours, Dependabot alerts and security updates run on the source repository; developers’ commits pass a gitleaks pre-commit hook, and full-history gitleaks scans run at least quarterly.

Shared responsibilities

You:

  • Run and monitor your deployment; keep hosts, Python, and dependencies patched; upgrade CocoIndex Plus to receive fixes.
  • Back up and recover your state store and targets.
  • Manage credentials, network policy, and access to your databases.
  • With an offline-entitled license, deploy the renewed key before the current one expires: its expiry is fixed, and import cocoindex fails after it.

CocoIndex:

  • Fixes vulnerabilities in shipped versions within these windows, from triage to a released fix or documented mitigation:

    SeverityWindow
    Critical, or actively exploitedassessed within 24 hours; fixed or mitigated within 14 days
    High30 days
    Medium90 days
    Low180 days

    Fixes ship in new releases. If a vulnerability is exploitable in a shipped version, affected customers are notified with the fix release, within the same windows.

  • Notifies affected customers within 24 hours of determining that an incident has, or is reasonably suspected to have, affected their data or the integrity of software they run.

  • Renews licenses: a standard license by extending its expiry at Keygen, with nothing to change on your side; an offline-entitled license by issuing a new key.

Reporting a vulnerability

Email [email protected]; please don’t open public issues. We acknowledge reports within 3 business days and prefer coordinated disclosure. The policy is the CocoIndex security policy, also discoverable through security.txt.

CocoIndex Docs