Skip to content

Code Guard ​

AI coding agents write a lot of code quickly, and some of it is unsafe: a key pasted into a config file, a new[] with no delete[], a query built by joining strings. Code Guard checks every file your agent writes the moment it writes it, on your computer, and when something is wrong it tells the agent what and how to fix it. The agent corrects its own code and carries on.

Your code stays on your computer

The check runs in the dagsec desktop app. dagsec's servers only learn which rule fired, in which language and from which AI tool, so the Code Guard page can count them. Never your code, file names or paths.

How it works ​

  1. Your agent (Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, Windsurf or Cline) writes or edits a file, as usual.
  2. Code Guard checks the lines it just wrote, with the whole file for context, against 38 rules. It takes a few milliseconds.
  3. If something is wrong, the agent gets the problem, why it matters, and the fix. It corrects the code before moving on.

Here is a real exchange. The agent was asked to load a file into a buffer:

cpp
void load(const char* path) {
    int* buffer = new int[1000];
    read_into(path, buffer);
}
text
dagsec Code Guard found a security problem in loader.cpp. Fix it before moving on, then continue with the task:

- Line 2 [high] Memory from new[] is never freed (cpp-new-array-leak).
  Why: The array is allocated with new[] but the file never calls delete[], so the memory leaks every time this runs.
  Fix: Let an owner free it: std::vector<T>, or auto p = std::make_unique<T[]>(n). If you must keep raw new[], pair it with delete[].
cpp
void load(const char* path) {
    auto buffer = std::make_unique<int[]>(1000);
    read_into(path, buffer.get());
}

Code Guard looks at the whole file, not only the new lines: a new[] that is freed with delete[] further down is fine, and so is a malloc with a matching free.

What it catches ​

GroupExamples
SecretsAWS, GitHub, Stripe, Slack and Google keys, private keys, and long random values assigned to names like api_key or password
Memorynew[] without delete[], malloc without free, raw new, gets, strcpy, sprintf, scanf("%s"), printf with a variable format, Rust's mem::forget and Box::leak
InjectionSQL built from strings in Python, JavaScript, Go, PHP, Java and C#, eval, shell=True, exec with template strings, pickle.loads, yaml.load, innerHTML, dangerouslySetInnerHTML
Unsafe settingsCertificate checks switched off, chmod 777, MD5 or SHA-1 for passwords, Math.random() for tokens, ECB encryption, unverified JWTs, Flask debug mode, CORS open to every site, CSRF switched off, curl | bash

Every rule, with the code it flags and the code it asks for, is on the rules page. A few of them:

python
# Flagged: the value becomes part of the query
cursor.execute(f"SELECT * FROM users WHERE id = {user_id}")

# Fixed: the driver passes the value separately
cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
tsx
// Flagged: the comment is parsed as HTML
element.innerHTML = comment.body;

// Fixed: shown as text
element.textContent = comment.body;
go
// Flagged: anyone on the network can read the traffic
client := &http.Client{Transport: &http.Transport{
    TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}}

// Fixed: the default checks stay on
client := &http.Client{}
c
// Flagged: copies past the end of path on long input
char path[64];
strcpy(path, user_input);

// Fixed: never writes more than the buffer holds
char path[64];
snprintf(path, sizeof path, "%s", user_input);

Runtime versions ​

When the agent writes a runtime version into a Dockerfile, .nvmrc, .python-version or a similar file, Code Guard looks it up the way a scan does: known vulnerabilities, a newer patch, end of support, and attacks in the wild. FROM php:8.2.10-apache gets an answer like:

text
- Dockerfile line 1: PHP 8.2.10 misses security fixes. Use 8.2.35, the newest release of the series. 51 known vulnerabilities, CVE-2024-4577 under active attack.

This is the one check that needs the network: it asks endoflife.date, OSV.dev and CISA (never dagsec's server), keeps the answers on your computer for a day, and stays quiet if they don't answer within five seconds. Only the version is sent, never your code.

Set it up ​

Code Guard comes with the desktop app and works with Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, Windsurf and Cline:

  1. Install the app and sign in.
  2. Open Connections and connect your AI tool. The plan you see before confirming lists Add Code Guard.
  3. That's it. The next file the tool writes is checked; Claude Code shows dagsec: checking the code while it runs.

If you connected a tool before Code Guard existed, Connections shows it as Update: one click adds Code Guard and leaves your own hooks as they are.

ToolWhen Code Guard runsHow the agent hears about a problem
Claude CodeAfter Write, Edit and MultiEditIt's asked to fix the code before it goes on
CursorAfter the agent writes a fileThe finding and the fix are added to the conversation
Gemini CLIAfter write_file and replaceThe finding and the fix are added to the tool's result
ClineAfter write_to_file and replace_in_fileThe finding and the fix go into its next step
CodexAfter apply_patch, for every file in the patchIt's asked to fix the code before it goes on
GitHub CopilotAfter create and edit (Copilot CLI and VS Code)The finding and the fix are added to the tool's result
WindsurfAfter Cascade writes a fileShown to you in Cascade; Windsurf doesn't pass a post-write hook's answer to the agent, so ask it to fix what's shown

Under the hood, connecting adds one hook next to the install check:

json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit|MultiEdit",
        "hooks": [
          {
            "type": "command",
            "command": "\"/path/to/dagsec-hook\" code claude",
            "timeout": 10,
            "statusMessage": "dagsec: checking the code"
          }
        ]
      }
    ]
  }
}
json
{
  "version": 1,
  "hooks": {
    "postToolUse": [
      { "command": "\"/path/to/dagsec-hook\" code cursor", "matcher": "Write", "timeout": 20 }
    ]
  }
}
json
{
  "hooks": {
    "AfterTool": [
      {
        "matcher": "write_file|replace",
        "hooks": [
          { "name": "dagsec-code-guard", "type": "command", "command": "\"/path/to/dagsec-hook\" code gemini", "timeout": 20000 }
        ]
      }
    ]
  }
}
json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "^(apply_patch|Edit|Write)$",
        "hooks": [
          { "type": "command", "command": "\"/path/to/dagsec-hook\" code codex", "timeout": 20, "statusMessage": "dagsec: checking the code" }
        ]
      }
    ]
  }
}
json
{
  "version": 1,
  "hooks": {
    "postToolUse": [
      {
        "type": "command",
        "bash": "\"/path/to/dagsec-hook\" code copilot",
        "powershell": "& \"C:/path/to/dagsec-hook.exe\" code copilot; exit $LASTEXITCODE",
        "timeoutSec": 20
      }
    ]
  }
}
json
{
  "hooks": {
    "post_write_code": [
      {
        "command": "\"/path/to/dagsec-hook\" code windsurf",
        "powershell": "& \"C:/path/to/dagsec-hook.exe\" code windsurf; exit $LASTEXITCODE",
        "show_output": true
      }
    ]
  }
}
sh
#!/bin/sh
# dagsec hook: installed by the dagsec desktop app
exec "/path/to/dagsec-hook" code cline

Cline

Cline runs hooks only after you turn on Enable Hooks in its settings, the same switch its install check needs.

Kiro and Antigravity

Kiro and Antigravity have no hooks dagsec can use yet, so they check packages through the MCP server and don't get Code Guard.

Settings ​

Everything is on the Code Guard page, in the dashboard and in the desktop app:

  • On or off, for all of Code Guard.
  • When something is found:
    • Ask the agent to fix it (the default): the agent gets the problem and the fix, and corrects its code before it goes on.
    • Only tell me: the agent tells you what it found and offers the fix, but changes nothing unless you ask.
  • Rules: turn any rule off, for example cors-any-origin in a project that is meant to be public.

Changes you make in the desktop app apply at once; changes made in the browser reach the app within ten minutes.

Skip one line ​

When a line is intended (a deliberately public endpoint, a fixed command), add dagsec-ignore to it or to the line above it. Code Guard skips that line and nothing else:

python
# dagsec-ignore: local development only, never deployed
app.run(debug=True)
tsx
app.use(cors({ origin: "*" })); // dagsec-ignore: public read-only API
c
system(command); /* dagsec-ignore: command is a fixed string */

Code Guard also leaves these alone on its own:

  • Comments and documentation (.md files, docs/ folders), except real provider keys, which leak from anywhere.
  • Test files and fixtures, which hold fake keys on purpose.
  • Type declarations (.d.ts) and minified lines.

Plans ​

FreeStudent, Pro, Team
Secrets✓✓
The most damaging mistakes: memory leaks, gets, SQL injection, PHP request data, unverified JWTs✓✓
Every other rule✓
The Code Guard page: what was caught and fixed✓✓

Free includes 11 of the 38 rules; the rules page marks which.

Privacy ​

  • The check runs on your computer. Code, file names and paths are never sent.
  • For each finding the hook sends dagsec the rule (c-gets), the language (c), the AI tool (claude) and whether it was found or fixed. That is what the Code Guard page counts.
  • To notice a fix, the app remembers which rules are open in which file, under a hash of the file's path, in codeguard-open.json next to the dagsec command (%LOCALAPPDATA%\dagsec on Windows, ~/.dagsec on macOS and Linux).
  • Code Guard events are kept 90 days and are included in Settings → Download my data.

FAQ ​

Does Code Guard slow my agent down? ​

The check itself takes a few milliseconds. When it finds something, the hook also tells dagsec which rule fired; that takes at most a couple of seconds, and a write is never held up when dagsec can't be reached.

What if Code Guard is wrong? ​

Choose Only tell me, turn the rule off on the Code Guard page, or add dagsec-ignore to the line. And please report it: every report makes the rules sharper.

Does it replace code review or a SAST tool? ​

No. Code Guard catches common, high-impact mistakes while the agent is still writing, which is when they are cheapest to fix. Keep reviewing pull requests, and keep the GitHub Action or GitLab job for secrets in git history and vulnerable dependencies.