AI security · Find

A scanner tells you a line is wrong.
It cannot tell you who wrote it.

RepoOps does not rebuild a static analyzer. It runs the one you already trust over the diff the agent just produced, checks the packages it reached for, catches a secret the moment it is written, and reads the screenshots too. Then it does the part that was missing: it joins each finding to the session behind it and to what that session cost.

Local scans on your machine · the diff rather than the whole repository · a scan that could not run says so instead of reporting a clean tree

What it does

The parts, and the module behind each one.

Four scans over what an agent produces, and one join that turns a finding into something you can act on.

Semgrep over the agent's own diff

Scanning the whole repository buries what changed under everything that was already there. RepoOps scopes the scan to the agent working-tree diff against your main branch and shells out to Semgrep OSS, so you get the upstream rule set and its maintenance. With Semgrep absent, a built-in pass runs a handful of high-signal rules over the same diff and the surface names which engine produced the result.

lib/agent-diff-scan.mjs

A package name the model invented

Every dependency an agent adds is checked against the registry before anyone installs it, so a hallucinated or squatted name is named as one. A registry RepoOps cannot reach degrades the row to unverified. It never degrades to safe.

lib/dependency-provenance.mjs

A secret caught at write time

The gate runs the content of a generated file through the same pattern table the redactor uses, so there is no second list to drift out of step. A blocked event keeps the match types, the counts, a fingerprint and a redacted preview, and hands back the secret-free view of the write.

lib/secret-gate.mjslib/redact.mjs

The screenshot is a text channel

An agent that pastes a terminal or a dashboard screenshot moves a secret into a channel no text detector watches. The image is read with the bundled OCR and the extracted text goes through the detectors that already ship, rather than a second set written for images.

lib/multimodal-secret-scan.mjs

The session and the dollars beside the finding

Each finding carries the session that produced the diff and what that run cost. The uncommitted diff is one change, so the match is on recency across the whole scan and the surface says so rather than implying a per-line trace. An unpriced model reports as unpriced instead of borrowing another model's rate.

lib/security-cost-fusion.mjs

A rollup a team lead can read

The three local scans over what agents write publish a redacted snapshot, so someone who is not sitting at the machine can see the shape of what is being found without the code that was found in. The scanning still happens locally; only the summary moves.

lib/agent-code-findings-snapshot-publisher.mjs

Where it lands

What the platform gets, and what you get.

How it helps the platform

Finding is where the security layer stops being about sessions and starts being about code.

  • It gives the causal chain a code anchorA finding names a file and a line, which is what the security attribution leg needs to walk back to a commit and a developer. A signal with no code anchor can be triaged. It cannot be traced.
  • It supplies the input the fix loop builds againstA finding at or above your build floor is what the remediation loop scopes a brief from. The quality of the brief comes straight from the specificity of the finding, which is why the diff scope matters more than the rule count.
  • It keeps one pattern table across the productThe write-time gate, the redactor, the key inventory and the screenshot pass all read the same secret-shape corpus. One list means a new pattern lands everywhere at once and no surface quietly falls behind the others.

How it helps you

You review the work of the run that just finished, while you still remember what you asked for.

  • Findings you can act on todayA repository-wide scan hands you a backlog. A diff-scoped scan hands you the set of problems the agent created in the last hour, which is the only set anyone actually fixes.
  • A price tag on the bad runSeeing that a session produced four high-severity findings and cost real money is a different conversation from seeing either fact alone. It answers whether this was a run you would have paid for if you had known.
  • No false comfort from a scan that never ranAn empty result from a scanner that failed to start looks exactly like a clean codebase. RepoOps separates the two: did not run reads as did not run, with the reason and the install command.

In practice

Three days this changes.

Each one runs on the modules above. The situation, what RepoOps does with it, and what you are left holding.

  1. 01

    The package that does not exist

    The situation
    An agent confidently adds an import for a helper library it invented, and the name is close enough to a real one that nobody reading the diff blinks.
    What RepoOps does
    Dependency provenance checks the name against the registry as part of the scan and flags it before an install command is ever run.
    What you get
    You catch a hallucinated dependency at review time rather than discovering that someone else registered the name and shipped code inside it.
  2. 02

    A credential written into a config file

    The situation
    An agent scaffolds a deployment config and helpfully fills the auth field with the real key it found in the environment.
    What RepoOps does
    The write-time gate matches the secret shape as the file is generated, blocks the write, and records the match types, counts and a fingerprint without keeping the value.
    What you get
    The key never reaches the working tree, so there is no commit to rewrite and no history to purge. The record of the catch is safe to share.
  3. 03

    An expensive run that also wrote bad code

    The situation
    A long agent session burns through a noticeable amount of budget and lands a diff nobody has read closely.
    What RepoOps does
    The scan runs over that diff, and every finding arrives carrying the session and the metered cost of the run that produced it.
    What you get
    One row that answers both questions your manager will ask: what did it get wrong, and what did it cost to get it wrong.

The limits

What this does not do.

Stated here rather than found out later. The long version, with the module behind each boundary, is on the proof page.

The session join is a correlation

The uncommitted diff is one change, so every finding in a scan carries the same session, the most recent one in the window, with that session's whole cost. It is not a per-line trace, and each finding says so on its face.

Semgrep is an external tool

RepoOps shells out to Semgrep OSS rather than bundling a scanner. Without it installed you get the built-in high-signal pass over the same diff, clearly labelled, and the install command for the full rule set.

It finds. It does not block

These scans report. Stopping a tool call before it happens is the enforcement gate on the Contain page, and that gate ships all-advisory with its hook unregistered.

A clean scan is not a proof of safety

A rule set catches the classes it describes. RepoOps reports what the scanner found over the diff it read, and nothing on this page claims that a repository with no findings has no vulnerabilities.

Read further

Where this is documented in full.

Scan the diff your agent just wrote.

One developer, no account, nothing leaving the machine. Arm a control when you want one.