Skip to content

Trust & security

The whole integration is built so you can verify Venturi’s claims rather than trust them. This page is what to tell your security reviewer.

Read-only, enforced at three layers

Venturi reads from customer environments and never writes into them. Three layers enforce that boundary:

  1. The runtime identity uses the narrowest read permissions. Setup creates the integration identity and role bindings. Cloud identities receive only allowlisted read actions. External provider credentials use their native read permissions where supported, and every connector restricts requests to its approved read-endpoint allowlist. A cloud IAM deny cannot restrict an external provider bearer key; see the provider credential matrix.
  2. A platform gate blocks violations from shipping. The permission gate scripts/check_permissions.py runs in the CI gate stack of Venturi’s platform repository. It rejects source-system write operations, unnecessary native management grants, and a broader reporting credential without independently certified read-only egress. Cloud IAM grants remain read-only. The platform repository is private; the third layer is the check you run yourself.
  3. You prove it yourself. Automated credential validation runs positive reads and proves write refusal with policy simulation or an isolated provider test fixture. Never attempt an administrative write against production data. Each cloud also has a customer-run check with an exact pass rule:

    • AWS, where the role trusts only the Venturi principal: a listing of every policy on the role, plus an IAM policy simulator spot check of writes.
    • Google Cloud: the module’s scripts/verify.sh. Its project-scope role: lines must be exactly roles/monitoring.viewer, roles/logging.viewer, and roles/serviceusage.serviceUsageConsumer, the roles the module grants there. Any other role: line, including roles/bigquery.dataViewer, roles/iam.serviceAccountTokenCreator, or roles/iam.workloadIdentityUser, is a security finding even when the script prints it as OK, because the script’s allowlist also accepts those roles.
    • Azure: the module’s scripts/verify.sh plus az role assignment list --assignee "$OBJECT_ID" --all, which must show only Reader, Cost Management Reader, and Monitoring Reader on the subscription, plus Log Analytics Reader on the named workspace and Azure Event Hubs Data Receiver on the named namespace when you enable those grants. The script’s allowlist alone is not the proof: it also accepts write-capable roles such as Reader and Data Access, which grants read and write access to all data in a storage account through the account keys.

    Any successful write is a security finding. See Verify & confirm.

No long-lived cloud credentials by default

Cloud Default auth Secret exposure
AWS Cross-account AssumeRole, scoped by a per-customer external_id; Venturi requests 15-minute sessions, and the role’s maximum session duration is 1 hour, the lowest value IAM accepts No static credentials; nothing exported
Google Cloud Workload Identity Federation No service-account key is created or exported
Azure Federated credential (OIDC) No secret by default; the optional client-secret fallback has a 90-day TTL and is never exposed as an output, but its value is stored in Terraform state

The AWS external_id is a confused-deputy mitigation: Venturi can only assume the role when presenting the exact per-customer string, so a leaked role ARN alone is not enough to assume it.

This default covers cloud onboarding. Three credential types sit outside it:

  • Azure client-secret fallback. The secret expires after 90 days. Terraform state holds its value even though the module never outputs it, so keep that state in an encrypted backend with restricted access, and hand the secret to Venturi only through the encrypted channel described in Rotate & offboard.
  • Venturi API keys. A key stays valid until it reaches its optional expiry or you rotate or revoke it. Give each key the narrowest scopes it needs, set an expiry within your tenant’s maximum, and rotate it on your schedule; see API keys.
  • SaaS connector credentials. Connectors that authenticate with a vendor token or client secret store it as an encrypted credential reference inside your tenant boundary. Rotate it according to that vendor’s policy.

Least privilege

Each module grants read-only access for attribution, and you can narrow the defaults noted below. The onboarding guide for each cloud is the exact list:

  • AWS: Cost Explorer, the pricing catalog, the named CUR bucket and prefix (that bucket only), IAM and Organizations inventory, and, by default, Bedrock model metadata with CloudWatch metrics, CloudWatch Logs, and CloudTrail reads. The CloudWatch Logs reads cover every log group in the region unless you set bedrock_log_group to the one log group Venturi needs. See the AWS access boundary.
  • Google Cloud: roles/bigquery.dataViewer on the billing-export dataset only when you set billing_dataset_id and billing_dataset_only = true (otherwise the module also grants it on the whole project), roles/monitoring.viewer, roles/logging.viewer, and roles/serviceusage.serviceUsageConsumer. See the Google Cloud access boundary.
  • Azure: Reader, Cost Management Reader, and Monitoring Reader at subscription scope. API Management (Log Analytics Reader) and Event Hubs (Azure Event Hubs Data Receiver) reads are off unless you enable them; each is scoped to the Log Analytics workspace or Event Hubs namespace you name, or to the whole subscription when you name none. See the Azure access boundary.

No content capture

The core pipeline never stores prompt or completion text. Content can reach Venturi-operated code by two paths, so the boundary is drawn at what Venturi keeps:

  • The drop-in proxy. When you route calls through the drop-in proxy, request and response content passes through the proxy in memory only while it is forwarded and is never written to access logs, error logs, traces, queues, or exception payloads, including on error and timeout paths.
  • Content-bearing cloud logs. The default read grants (CloudWatch Logs on AWS, roles/logging.viewer on Google Cloud, Reader and Monitoring Reader on Azure) can reach content-bearing logs, as described next.

Content-bearing logs. Read access to a log source is not storage of its content. Most of these log sources carry prompts or completions only after you enable the provider feature that writes them; Vertex AI container logging is on by default for models deployed through the v1 service endpoint:

  • AWS: CloudWatch Logs read access can reach Amazon Bedrock model-invocation logs, which contain prompts and completions when invocation logging is enabled.
  • Google Cloud: roles/logging.viewer can read Vertex AI container logs, which hold whatever your serving containers write to standard output and standard error and are enabled by default on the v1 service endpoint. A project-wide roles/bigquery.dataViewer grant, which the module creates only when BigQuery is not pinned to the billing-export dataset, can read the BigQuery table that Vertex AI request-response logging writes, which contains sampled prompts and responses when you enable that logging.
  • Azure: Reader and Monitoring Reader can query Log Analytics workspace tables at the default (General) protection level. When API Management language-model message logging is enabled, the ApiManagementGatewayLlmLog table in that workspace contains prompts and completions. Event Hubs diagnostic streams can also carry request or response detail when that diagnostic category is enabled.

Scope each grant to the source that supplies metadata. On AWS, set bedrock_log_group to the named log group. On Google Cloud, where roles/logging.viewer reads only the _Required bucket and the _Default view of the _Default bucket, route Vertex AI container logs to a user-defined log bucket, and keep BigQuery read pinned to the billing-export dataset (see the Google Cloud access boundary). On Azure, scope the added grants to the named Log Analytics workspace and Event Hubs namespace; because Reader and Monitoring Reader apply to the whole subscription, set a content-bearing table such as ApiManagementGatewayLlmLog to the Protected level (an Azure Monitor preview feature) so those roles cannot query it. For any record that still contains content, the collector applies a field allowlist in memory, discards prompt and completion fields before a record is materialized, and never persists, logs, retries, or exports them. The normalized InvocationEvent schema has no field for prompt or completion text.

The allowlist keeps only identity, resource, model, token, cost, timing, and correlation metadata; request and response bodies and content-shaped keys are discarded in memory and are never persisted. Raw provider responses and error payloads are never written to application logs, audit logs, retry queues, or dead-letter storage.

Fail-open

A slow, degraded, or unavailable Venturi dependency cannot block your traffic. The decision-time interceptor works to a 50 ms P99 end-to-end latency budget, with a cooperative timeout against a cumulative deadline, and forwards requests unmodified when a dependency behind it fails. The one deliberate rejection is the drop-in proxy’s tenant admission: a provider key that is not registered to your tenant is rejected before anything is forwarded (see Tenant admission). Fail-open does not cover the reachability of the drop-in proxy endpoint itself, which is on your request path when you use it; the Drop-in proxy page explains how to fail over to the provider’s direct base URL. See the fail-open boundary.

You stay in control

References

  • Trust-boundary source document: shared with your security reviewers during onboarding and diligence
  • Security policy & vulnerability reporting: Trust center or security@venturi.systems
  • Permission gate: scripts/check_permissions.py in Venturi’s private platform repository
Give feedback on this page

Sign in to send feedback. Opens in a new tab.

Copy page details
Docs feedback: Trust & security
Page: https://docs.venturi.systems/concepts/trust-and-security/