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.
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.rsappears in a TLS library’s error message; from v1.0.59,http://localhostis the OpenTelemetry exporter’s default collector address,localhost:4318, used only when you enable metrics export without naming an endpoint):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.rsOne 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 fromstatic.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:
updateanddropload your app’s code and run it (dropreverts the target states the app created, then clears its state).lsandshowinspect the state store. Given an app target, they import your app’s module, andlsalso starts its environment, which runs your lifespan code;ls --db PATHonly reads the database.initscaffolds 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
| Destination | When | What it receives |
|---|---|---|
| Your sources and targets — databases, object stores, queues, code hosts, SaaS APIs | When your pipeline reads or writes them | Your data, under credentials you supply |
| Your Postgres state store, if you use one | Throughout a run | Engine state (what it holds) |
| Your OpenTelemetry collector or metrics backend, if you configure one | Periodically 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 providers | Only when your code calls LiteLLMEmbedder, LiteLLMTranscriber, or LlmPairResolver, or gives a Chonkie semantic chunker a hosted embedding model | The 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 loads | No pipeline data: model files and metadata (details below) |
github.com (tree-sitter grammars) | When ChonkieCodeChunker is built without its grammars cached | No pipeline data: grammar downloads |
raw.githubusercontent.com (litellm metadata) | When litellm is imported, and for some Claude requests | No pipeline data |
api.keygen.sh | At 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.comandgitlab.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 onhuggingface.co. - Metrics export: off by default. You choose the endpoint and its
credentials with the standard OpenTelemetry variables, and
OTEL_SDK_DISABLED=trueturns 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_grouptitles 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 asus.aws.cdn.hf.coandcas.xethub.hf.co— or checks a cached copy for updates. Two other requests:- For a model published only as
.binweights, 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=1turns this off. - huggingface_hub 1.27 fetches a list of AI-agent tools from
huggingface.coat most once a day, to label its requests.HF_HUB_DISABLE_TELEMETRY=1turns this off.
HF_HUB_OFFLINE=1stops all of these. The exception is chonkie 1.7’s tokenizer loader, used for a Hugging Face tokenizer name, which ignoresHF_HOMEandHF_HUB_OFFLINEand reads only~/.cache/huggingface/hub. Pre-stage the models in that directory. - For a model published only as
-
tree-sitter grammars:
ChonkieCodeChunkerdownloads grammars, as native libraries, from the tree-sitter-language-pack project’s GitHub releases (served fromrelease-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=TrueandLITELLM_LOCAL_ANTHROPIC_BETA_HEADERS=Trueto 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-keywith the body{"meta":{"key":"<your license key>"}}and JSONContent-Type/Acceptheaders. 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=0where 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, andNO_PROXYenvironment variables (not OS proxy settings), so a TLS-inspecting proxy must exemptapi.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.jsonunder$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 cocoindexfails until Keygen is reachable again.
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, orHF_HOME), when a local model is used. - tree-sitter-language-pack’s grammar cache, when
ChonkieCodeChunkeris 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:
sslmode | Encrypted | Certificate chain verified | Hostname verified |
|---|---|---|---|
disable | no | — | — |
allow, prefer (the default) | if the server offers TLS | no | no |
require | yes | no | no |
verify-ca | yes | yes | no |
verify-full | yes | yes | yes |
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-fullmatches 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 --dbis 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, andtype),pathlibpaths,uuid.UUID,datetimevalues, NumPy arrays, and the types you register with@coco.serialize_by_pickleor@coco.unpickle_safe(see Serialization). That blocks the usual pickle attack — a payload that names an arbitrary function such asos.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_LOGsets the filter; the default isinfo. - Python logs go through Python’s
loggingundercocoindex.*logger names, so your application’s logging configuration applies. The CLI configures it fromCOCOINDEX_LOG_LEVEL(defaultWARNING) 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
ERRORwith 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 lsalways, andupdateanddropunless you pass--quiet. In v1.0.53 that’s the full Postgres DSN, password included, so don’t let CLI output from a password-bearingCOCOINDEX_DBreach 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:
| Operation | Where it runs | What leaves the process |
|---|---|---|
LiteLLMEmbedder (LiteLLM) | Your chosen provider | The texts you embed, in batches — plus, the first time an embedder needs its vector dimension, the probe text "hello" |
LiteLLMTranscriber | Your chosen provider | The audio you transcribe, with its file name |
LlmPairResolver (entity resolution) | Your chosen provider | Per 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) | Locally | Nothing; 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 model | Nothing; 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 chunker | Locally | Nothing; the default character tokenizer is built in, while a Hugging Face tokenizer name downloads that tokenizer |
| Chonkie code chunker | Locally | Nothing; 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 engine | Nothing |
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
-
License: ask for an offline-entitled license.
-
Packages: mirror the
cocoindex-pluswheels (from our Keygen index) and their dependencies (from PyPI) into an index inside your network (supply chain). -
Local models and tokenizers: download each one on a connected machine, then copy the result to the service account’s
~/.cache/huggingface/hubon the target hosts. Use that default location rather than settingHF_HOME(orXDG_CACHE_HOME), because chonkie 1.7’s tokenizer loader reads only it. Then run in offline mode:# 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=1Set
HF_HUB_OFFLINE=1even when everything is cached: without it, the Hugging Face client keeps trying to reachhuggingface.cobefore 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. -
Code grammars (for
ChonkieCodeChunker): grammars are native libraries, so download them on a machine with the same OS, architecture, andtree-sitter-language-packversion as your hosts — or while building your image — then copy the directory thatcache_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.python - <<'EOF' import tree_sitter_language_pack as t t.download_all() # about 500 MB print(t.cache_dir()) EOF -
Model endpoints: point the LiteLLM-based operations at endpoints inside your network, and set
LITELLM_LOCAL_MODEL_COST_MAP=TrueandLITELLM_LOCAL_ANTHROPIC_BETA_HEADERS=True. -
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 PostgresCOCOINDEX_DBwith a password is a secret too; on v1.0.53, pass--quiettoupdateanddropin automation. - State store: a dedicated database or schema and role,
verify-fullTLS, 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_componentsorCOCOINDEX_MAX_INFLIGHT_COMPONENTS; see Concurrency control). The Postgres state store opens up to 65 connections per environment (pool_max_sizeof 64, plus one); keep that within your server’smax_connections. An LMDB directory holds at mostmax_dbsapps (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.shfor 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_codeoff unless you trust the model repository’s code. Where Hugging Face access stays on, considerDISABLE_SAFETENSORS_CONVERSION=1andHF_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:
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 cocoindexfails after it.
CocoIndex:
-
Fixes vulnerabilities in shipped versions within these windows, from triage to a released fix or documented mitigation:
Severity Window Critical, or actively exploited assessed within 24 hours; fixed or mitigated within 14 days High 30 days Medium 90 days Low 180 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.