{% extends "curb_base.html" %} {# This machine › Leaks: secrets found, by exposure; scanning; removing one from its file. #} {% block part %}
{% set src = ("Scanned " ~ "{:,}".format(view.files) ~ " files " ~ ago(view.at) ~ ": " ~ "{:,}".format(view.secrets) ~ (" secret" if view.secrets == 1 else " secrets") ~ ", in " ~ "{:,}".format(view.rows | length) ~ (" place" if view.rows | length == 1 else " places") ~ ". Curb never shows the value of a secret.") if view.scanned else ("The first scan is running. Nothing leaves this machine." if job.running else "No scan has run yet. Nothing leaves this machine.") %} {% call k.head("Secrets found in files your agents wrote, or can read.", src) %} {# With no scan yet, the one main button is in the empty state below. #} {% if view.scanned and not job.running and not missing %} {{ k.act("Check which still work…", "validate", "", "", false) }}
{% endif %} {% endcall %} {% if missing %} {% endif %} {% if job.running %}

{% if job.total %}Scanning: {{ "{:,}".format(job.done) }} of {{ "{:,}".format(job.total) }} files read. {% else %}Finding the files to read…{% endif %}

Nothing leaves this machine. You can leave this page: the scan carries on.

{% elif job.state == "failed" %} {% endif %} {% if not view.scanned and not job.running %} {% call empty.state("search", "No scan yet") %}

A scan reads agent transcripts, your shell history and project .env files, and lists the secrets it finds. It takes a few minutes, and nothing leaves this machine.

{% if not missing %}
{% endif %} {% endcall %} {% endif %} {% if view.scanned %}
{% for stat in view.stats %} {{ "{:,}".format(stat.value) }} {{ stat.text | safe }} {{ "Showing" if exposure == stat.key else "Show" }} {% endfor %}
{% if view.no_agent %}
No supported agent was found, so nothing counts as readable by one.
{% endif %}
Places found {{ k.tally() }} {% call k.tools("Search secrets") %} {% endcall %}
{% if not view.live %}

Curb never stores where a secret is, so the places went when flanner restarted. Scan again to see them, and to remove a secret from its file.

{% elif not shown %}

Where each secret is stays hidden. {{ k.ask_names() }} to see the file and line, and to remove a secret from its file.

{% endif %}
SecretExposureProjectStill works?
{% for row in table.rows %}
{{ row.type }} In: {{ row.category }}{% if row.where %} · {{ row.where }}{% endif %} {{ row.exposure_label }} {% if view.live %}{{ k.slot(row.project) }}{% endif %} {{ k.st(row.works_kind, row.works) }} {% if row.removable and shown %}{{ k.act("Remove from file…", "remove", "btn-sm btn-quiet", "&file=" ~ row.file) }}{% endif %}
{% endfor %} {{ k.foot("No secret matches that search.") }}
{% if view.not_checked %}
Not checked: {{ view.not_checked | join(" ") }}
{% endif %} {% endif %} {% call k.explain("What to do with a leaked secret", "Rotate it first. Then remove it from the file.") %}

Rotate it. Make a new one at the service that issued it, and switch the old one off. A secret that was sent to a model provider has left this machine, so removing the file does not help.

Then remove it from the file. Curb replaces the secret with a placeholder of the same length. There is no backup and no undo, because a backup would be another copy of the secret.

Check which still work sends each secret to its own issuer, and nowhere else. It asks you first.

Sent
It is in an agent's transcript, so the model provider received it.
Readable
It is in a file an agent can read, but no agent has sent it.
Blocked
It is on disk, and a setting stops every agent reading it.

The same scan, in a terminal:

{{ k.cmd("flanner curb sweep") }} {% endcall %}
{% endblock %} {% block reviews %} {% call k.review_box("validate", "Check which secrets still work?", "/curb/machine/leaks/scan", {"check": "1"}, "Scan and check", false) %}

Curb scans again. Then it sends each secret it finds to the service that issued it, to ask whether it still works.

{% endcall %} {% if review == "remove" %} {% if removal is defined and removal.secrets is defined %} {% call k.review_box("remove", "Remove " ~ removal.secrets ~ (" secret" if removal.secrets == 1 else " secrets") ~ " from this file?", "/curb/machine/leaks/remove", {"file": removal_file}) %}

{{ removal.path }}

Rotate first. Removing a secret hides it here. It cannot unsend it.

There is no backup and no undo: a backup would be another copy of the secret.

{% endcall %} {% else %}

Curb cannot remove that

{{ removal.said if removal is defined else "Show names and locations first, so you can see which file this is." }}

Close
{% endif %} {% endif %} {% endblock %}