Skip to content

Security and trust

This page is the technical companion to nodrik.dev/security — written for whoever has to sign off on granting Nodrik access, and for the assistant helping them check it.

RoleReadsVerbs
roles/logging.viewerlog entries — what the service actually said, and the Admin Activity audit log: who changed what, and whenentries.list
roles/monitoring.viewermetrics, what else is firing, and the notification channel — whether the symptom matches the timelinetimeSeries.list · alerts.list · alertPolicies.list · notificationChannels.list
roles/errorreporting.viewererror groups — what is failing, and since whengroupStats.list
roles/run.viewerCloud Run revisions and their configuration — what changed in a deployrevisions.list

The verbs matter more than the role names: they are the level at which “read-only” is either true or marketing. Full detail on how the roles are applied: Connect a Google Cloud project.

Optional: one more role per service, only if you give it

Section titled “Optional: one more role per service, only if you give it”

The four roles read telemetry. When an investigation needs a service’s settings as well — was it configuration or load — Nodrik can read them with one more read-only role for that service, and only that service. Each is a custom role defined in your project holding exactly the permissions the tool behind it calls, granted by the same three paths, deleted by the revoke script, and never asked for in advance.

ServiceRoleVerbs
Cloud SQL — instance settings and database flagsnodrikManagedSqlConfigViewercloudsql.instances.get · cloudsql.instances.list
Memorystore — Redis, Valkey and Memcached instance settingsnodrikCacheConfigViewerredis.instances.get · redis.instances.list · memorystore.instances.get · memorystore.instances.list · memcache.instances.get · memcache.instances.list
GKE — cluster and node-pool settings from the GKE API, never the clusternodrikKubernetesConfigViewercontainer.clusters.get · container.clusters.list
Compute Engine — instance, managed instance group and autoscaler settingsnodrikComputeConfigViewercompute.instances.get · compute.instances.list · compute.instanceGroupManagers.list · compute.autoscalers.list · compute.zoneOperations.list
Load balancing — backend health and configurationnodrikNetworkingConfigViewercompute.backendServices.get · compute.backendServices.list · compute.regionBackendServices.get · compute.regionBackendServices.list · compute.urlMaps.list · compute.regionUrlMaps.list · compute.healthChecks.get · compute.regionHealthChecks.get

For GKE, plainly: Nodrik reads the GKE API and Cloud Logging and never connects to your cluster — see Optional: a configuration role per service.

logging.viewer includes your Admin Activity audit log

Section titled “logging.viewer includes your Admin Activity audit log”

Worth stating plainly rather than leaving you to discover it. One of Nodrik’s tools reads the Admin Activity audit log — the same entries.list call, filtered to cloudaudit.googleapis.com/activity — because an incident is often caused by a change that never appears as a commit: an IAM binding, a config update, a deploy. “Nothing changed” is frequently wrong, and this is where the evidence that says so lives.

Those entries name the person who made the change. That is what an audit log is for, and Nodrik cannot ask for a version without it.

What happens to that name: it is replaced with [redacted-email] the moment the entry arrives, before the model is given it and before anything is written down. Redaction runs where the tool result enters the investigation, not at save time, so no address reaches the model, the report Nodrik posts, or the stored transcript. Nodrik can tell you a change was made at 10:15 and what it was — never who made it, which is neither told to you nor stored. One deliberate exception: a Google service-account address (…@…gserviceaccount.com) is left readable, because “your deploy pipeline made this change” is the answer, not personal data.

roles/run.viewer returns environment-variable values

Section titled “roles/run.viewer returns environment-variable values”

The same kind of sentence, and arguably the bigger one. The revisions.list call this role permits returns each revision’s full spec, and that includes the literal value of every environment variable set on it. Nodrik reads the variable names and discards the values — the schema it parses the response with has no value field, and a test asserts none reaches the model or the transcript — but the permission allows reading them. If you keep secrets in plain environment variables rather than Secret Manager references, know that before you grant it.

If that is not acceptable for your organisation, the answer is not a narrower role — it is not granting roles/logging.viewer, which also removes Nodrik’s ability to read your ordinary logs, and with it most of what it does. Say so and we will tell you honestly whether the rest is worth it to you.

  • Against your Google Cloud, Nodrik makes no write, update, create, delete or patch call.
  • No IAM changes, no policy edits, no secret access.
  • No deploys, rollbacks, scaling or traffic changes.
  • No customer telemetry is stored — reads are transient, at investigation time.
  • Tools you connect yourself are yours: Nodrik calls them and cannot verify what they do.

This is not a policy Nodrik follows; it is a property of the code. The identity Nodrik holds inside your project — the service account created for your workspace — carries the four viewer roles above and, per service you name, one more read-only role only if you choose to give it. Nothing else, and nothing that expands itself. Where a write is genuinely useful (the console’s grant wizard applying IAM bindings), it runs with the signed-in user’s own transient credentials, under their own authority, and the token is discarded once the grant is applied. Nodrik’s own identity never holds write access to your infrastructure, at any point.

Every customer gets a dedicated service account, created for that workspace and used for nothing else. This is the confused-deputy defence: a bug, or a prompt injection carried in a log line, in one customer’s investigation is structurally unable to touch another customer’s project — there is no shared credential that spans a boundary for it to cross.

Nodrik is a reach-in product: telemetry is read at investigation time, through your own APIs, to answer one question, and then discarded. What persists, in Firestore in europe-west1:

  • The investigation report Nodrik posted, and the transcript that produced it — both redacted before they are written.
  • Your workspace configuration: which projects to watch, your Slack channel, your GitHub installation id, and the tool sources you declared.
  • Your workspace’s audit log, for 396 days — see below.

Your telemetry — logs, metrics, error groups, source code — is never copied out, never indexed, and never stored. Read the exact wording: the honest privacy claim.

Every change anybody makes inside your workspace is recorded: who did it, which sign-in identity they used, the role they held at the time, what they changed, and when. Invites, role changes, projects added and removed, connectors, tool sources, plan and add-on changes, and the automatic changes Nodrik makes to your subscription all appear — the last of those attributed to Nodrik rather than to a person, because a charge nobody pressed a button for is exactly the entry a disputed invoice needs.

Every member can read it, not only admins. A history only the powerful can see invites the suspicion it exists to answer.

It records what changed, never the material: no request bodies, no tokens, no secrets, no card details. A plan change records the two tiers, not the payment method.

It is kept for 396 days — a full billing year plus the period before it, because the change that caused a charge somebody is querying usually happened in the period before the one they are looking at. It is deleted with your workspace when you leave, including the entry recording that.

Where to read it: Team ▸ History in the console. See Your team.

If you connect your own tools, the credential you issue is stored encrypted in Google Secret Manager, in a container scoped to your workspace alone and separate from the container holding your workspace’s Google Cloud credentials. It is sent only to the address you gave, never shown again after you save it, and never written into a report, a log line, a Slack message or an API response. Configuring a tool source is an admin action, deliberately not an ordinary configuration one: it stores a credential of yours and adds an outbound call from Nodrik to an address somebody typed.

A free trial is one per estate, not one per email address — see Sign up. Checking that requires remembering something about estates that have already trialled, and what we remember is deliberately not the estate:

  • We store a one-way hash of each of three things — your Google organisation id, your monitored project ids, and Stripe’s fingerprint of the card used — alongside which kind it was and when it was claimed.
  • We never store the organisation id, the project ids, or any card detail themselves. A hash answers “have we seen this before” and nothing else; it cannot be read back into the value it came from.
  • These hashes outlive your workspace on purpose. Deleting a tenant would otherwise reset the trial, which is the whole thing the check exists to prevent.
  • If you have a legitimate reason for a second trial on the same estate, ask us and we will release the claim.

The privacy policy states this as a row in its own table, which is the version you are entitled to rely on.

Nodrik’s services run on Google Cloud in europe-west1, and its Firestore database is there. Not everything Google holds for us is: your connection credentials sit in Secret Manager under Google’s automatic replication, and sign-in identities in Firebase Authentication, which Google operates from the United States. Model inference uses Vertex AI’s global endpoint, so the redacted telemetry excerpt in every model request may be processed outside the EEA; it is not stored there and is not used to train models. The service-by-service statement you are entitled to rely on is the data processing agreement, clause 7.

During an investigation Nodrik may also send a short search query to Google’s documentation search API (the Developer Knowledge API, a Google Cloud API), and open one of the pages that search returned, to check an error message or a command against Google’s current Google Cloud documentation — never the open web. After the report is written, the claims its suggested fix makes are checked the same way. The query is derived from the already-redacted investigation, and nothing is stored there.

Nodrik is not SOC 2 certified. Audit logging, least-privilege access, keyless CI and PR-gated change control run from day one, and certification follows a customer whose procurement process requires it — stated plainly rather than with a badge that means nothing yet.

The sub-processor list is maintained in exactly one place — the data processing agreement — with 30 days’ notice before any addition or replacement. It is not repeated here, so this page cannot quietly fall out of step with the list you are actually entitled to rely on.

Revoking is symmetrical to granting: remove the role bindings — the four, and any optional configuration role — and Nodrik goes blind, immediately — see the removal instructions on whichever connection path you used. If you granted an optional configuration role, the revoke script and terraform destroy delete its definition too, so nothing of ours is left in your project. You do not have to run that yourself for your data to be deleted: Nodrik’s own side of the teardown — the service account, stored credentials, investigation history — runs on our schedule and does not wait for yours, within the 30-day bound the DPA sets.

Anything at all, including “why do you need this role”: support@nodrik.dev.