Security · threat detection

Threat detection with Code Delta — the mini guide

Written for security reviewers and auditors. CodeDelta runs five threat-detection layers in one scan, and every finding is a file-and-line fact you can verify yourself. This page covers how to run each layer, how to read what comes back, and how to make the results block a merge.

The idea in one sentence

Everything dangerous that hides in a repository — an implant, a rogue agent, a leaked key — leaves hard, checkable evidence, and CodeDelta has five instruments that each look for one kind of it, all running in a single scan, all reporting file-and-line facts rather than opinions. Nothing here uses machine learning and nothing leaves your infrastructure: every detector is a readable rule table an auditor can inspect, and every finding names the file and line so you can check it yourself. Findings are pointers for review, never verdicts of malice.

Layer 1 — the build-file change alert

The question it answers: did anything change about how this software builds? When you scan two versions, it lists every build, CI and packaging file that changed — because that is where the xz-utils backdoor hid: change how software builds and you change what ships, without touching source anyone reviews. Two kinds of file ride the top of the alert, always shown in full: files with install hooks (code that runs the moment someone installs the package — a package.json postinstall, a setup.py cmdclass), and files that fetch remote content at build time, because editing one download URL redirects the whole supply chain. For a changed fetcher the alert goes further and prints the URL delta itself — + github.com/oneapi-src/… − github.com/01org/… — a reviewer’s decision made in one glance. Detection is a filename rule table plus a byte comparison; the fetch sniff is a fixed list of download constructs (file(DOWNLOAD, ExternalProject_Add, curl, wget…). CI pipeline files are deliberately exempt from the fetch tier — CI fetches by nature, and flagging every workflow would bury the signal.

Where you see it: the GUI’s Churn Results box, the agent report, the CLI’s [build] lines, and the pull-request comment. It appears on every scan that compares two versions, in every mode.

Layer 2 — the build & deployment surface inventory

The question it answers: what build machinery exists in this tree at all? The same detection, run over everything present — changed or not. On OpenCV that is 301 files, 14 of them fetchers, on one page. The point is the standing map: a new download source or install hook appearing anywhere is visible on every scan, and an auditor sees the whole attack surface without reading a single Makefile. Every agent report opens with it; a tree with nothing to show says so explicitly, because an empty section must never look like a broken feature.

Layer 3 — Agent Scan

The question it answers: is there an AI inside this software, and what can it reach? Agent Scan finds the code that calls AI at runtime: agent-SDK imports and model calls by name across 43 languages, raw model endpoints (a bare POST to api.deepseek.com needs no SDK), and the rogue pattern — model output flowing into exec, eval, a shell or an outbound request, which is the mechanism that turns prompt injection into code execution. It also inventories the artifacts agents leave in a tree — instruction files, agent workspaces, and tier-3 residue such as a committed gateway token. Every hit carries the file, the line, and the signature that fired.

Honest limits, stated up front: the endpoint list is a maintained table, so an unknown or deliberately obfuscated endpoint can evade it; detection is of initiation signatures, not intent. Pointers, not verdicts — the technical paper documents the method and its limits in full.

Committed credentials — part of the Agent Scan layer

The question it answers: is there a key sitting in this repository? A committed credential — an API key, an access token, a private key — is readable by everyone with repository access, in every clone, backup and CI runner, and git history preserves it after deletion. They end up committed through ordinary accidents: a pasted test key, an unignored .env file. CodeDelta detects them with a fixed table of documented key formats — AWS AKIA…, GitHub ghp_…, OpenAI, Anthropic, Google, Hugging Face, Slack, Stripe live keys, PEM private-key blocks. No entropy guessing, no scoring: a string either matches a vendor’s published format or it is not flagged. Verified against OpenCV’s full clean tree: zero false alarms.

Redaction, everywhere: findings show the first eight characters and the length, never the value — and the report’s embedded source viewer is scrubbed the same way, because reports travel: they get attached to CI runs and emailed to managers. The correct response to any finding is rotate the key first, then remove it from the tree — removal without rotation leaves the key valid in git history.

CodeDelta committed-credentials section — three redacted findings and the gate-off notice naming the policy switch
The credentials section, from a live scan. Three findings, redacted to a prefix and a length, each at file and line — and the gate notice naming the exact policy switch that turns detection into a failed build.

Layer 4 — the AI Bill of Materials

The question it answers: where does our software touch AI, on the record? Everything the layers above find, condensed into a document: every provider your code calls, its hosting jurisdiction, whether data leaves to somewhere sensitive (sovereignty_risk: true against CN / RU / KP / IR), cost-risk call sites, agent artifacts, committed-credential counts — each with the files named. Emitted as native JSON or CycloneDX (--bom --bom-format cyclonedx) so it drops into existing compliance tooling. Regulators are beginning to expect exactly this record; the EU AI Act is the one your auditors will name.

Layer 5 — the merge gate

Where detection stops being advice. Two mechanisms, both in the GitHub Action and the CLI:

MechanismWhat it does
--fail-on-newBlocks a pull request that introduces new findings against your recorded baseline (--write-baseline on a trusted commit first). Exit code 3 fails the check.
--gateFails the build on policy, regardless of baseline: the rogue pattern and egress to denied jurisdictions are on by default.

Three further switches ship OFF by default — deliberately, so a deliberate test fixture can never break a stranger’s build uninvited — and turning them on is one line in your --gate-policy file:

{ "deny_jurisdictions": ["CN", "RU", "KP", "IR"], "deny_flags": ["rogue_pattern"], "fail_on_committed_credentials": true, "fail_on_new_install_hook": true, "fail_on_new_fetcher": true }

fail_on_committed_credentials fails any build with a key-format match in the tree. fail_on_new_install_hook and fail_on_new_fetcher fail a diff in which that behaviour appears — new is computed honestly against the old side, so a project that has always fetched does not suddenly fail; only the diff where fetching started does.

CodeDelta merge gate failing a build — three committed-credential violations, exit code 3
The gate, failing a build. Policy switched on, three itemised violations (still redacted), exit code 3 — the merge is blocked before a human has to notice anything.

Running it

Every layer runs in one scan. From the GUI: Churn + Agent Scan on two versions gives you all five surfaces. Headless, the same thing is:

./codedelta-gui scan release-1.1/ release-1.0/ --mode churn_agent --bom --gate --gate-policy policy.json --fail-on-new

What comes back on the terminal: [build] ALERT: with per-file status lines, ** install hook ** / ** fetches remote content at build time ** markers and the +/ URL delta beneath a changed fetcher; [agent] tier counts, artifact and ALERT: N committed credential(s) lines (values redacted), then the gate-off notice naming the exact policy key to flip; [bom] summary; [gate] pass or an itemised violation list. Exit code 0 clean, 3 on a --fail-on-new regression or a gate failure — the exit code is what blocks the merge in CI. The agent report and the AI-BOM are written alongside for the humans.

On every pull request, the GitHub Action runs the same scan inside your own runner and posts the evidence as a comment — nothing about your code leaves your infrastructure, which is usually the security reviewer’s first question.

Limits

None of this claims to detect malice. Every instrument is a pointer that puts a reviewer in front of the right file with the right question, before the merge instead of after the incident. The methods and their limits are documented in full in the repository-threats paper and the agent-detection paper. To run all of it on your own tree, download Code Delta.

CodeDelta · codedelta.app