Skip to content

VibeGuard

A security scanner for AI-generated code.

CRITICALAuthentication bypass when DEBUG is enabled[VG-AUTH-001](confidence: medium)

at auth_bypass.py:5:5

why
A debug bypass that ships to production silently disables authentication. AI-assisted code frequently leaves these in.
fix
Remove the bypass entirely, or gate it behind an explicit non-production environment check that fails closed.

Real output. The code is samples/vulnerable/auth_bypass.py in this repository — a fixture that is vulnerable on purpose.

It catches the bugs that "looks fine, ships fine" code tends to hide: missing input checks, hard-coded passwords, skipped login checks, exceptions silently caught, and so on.

It runs in VS Code, in Chrome, and in CI.

What a finding looks like

    1. Before

      proto_merge.js
      function deepMerge(target, source) {
        for (const key in source) {
          if (source[key] && typeof source[key] === "object") {
            target[key] = deepMerge(target[key] || {}, source[key]);
          } else {
            target[key] = source[key];
          }
        }
        return target;
      }
      
      function applyOverride(obj, patch) {
        obj.__proto__.polluted = patch;
        return obj;
      }
      
      module.exports = { deepMerge, applyOverride };
    2. VibeGuard says

      HIGHPrototype-polluting merge[VG-INJ-020](confidence: medium)

      at proto_merge.js:2:3

      why
      Merging untrusted keys without a guard lets an input key of "__proto__", "constructor", or "prototype" mutate Object.prototype, corrupting every object in the process (privilege escalation, DoS, RCE gadgets).
      fix
      Guard every copied key: skip "__proto__"/"constructor"/"prototype", use Object.hasOwn(src, key) before recursing, or build the target with Object.create(null). Prefer a vetted deep-merge library.
    3. After --fix

      proto_merge.jsneeds-review
      function deepMerge(target, source) {
        for (const key in source) {
      +    if (key === "__proto__" || key === "constructor" || key === "prototype") continue;
          if (source[key] && typeof source[key] === "object") {
            target[key] = deepMerge(target[key] || {}, source[key]);
          } else {
            target[key] = source[key];
          }
        }
        return target;
      }
      
      function applyOverride(obj, patch) {
        obj.__proto__.polluted = patch;
        return obj;
      }
      
      module.exports = { deepMerge, applyOverride };

      Skip prototype keys in the merge loop

      Findings still open after --fix: 1

    1. Before

      net_insecure.ino
      #include <WiFiClientSecure.h>
      #include <HTTPClient.h>
      
      WiFiClientSecure client;
      
      void fetch() {
        client.setInsecure();
        HTTPClient http;
        http.begin("http://api.example.com/telemetry");
        http.GET();
      }
    2. VibeGuard says

      MEDIUMCleartext HTTP endpoint from device[VG-EMB-010](confidence: medium)

      at net_insecure.ino:9:14

      why
      Plaintext HTTP on a device has no confidentiality or integrity: credentials, telemetry, and firmware updates can be read and altered on the wire.
      fix
      Use https:// with certificate validation (setCACert / a pinned root). If the endpoint is truly local and trusted, keep it off any routable network.
    3. After --fix

      net_insecure.inoneeds-review
      #include <WiFiClientSecure.h>
      #include <HTTPClient.h>
      
      WiFiClientSecure client;
      
      void fetch() {
        client.setInsecure();
        HTTPClient http;
      +  http.begin("https://api.example.com/telemetry");
        http.GET();
      }

      Use https for the endpoint

      Findings still open after --fix: 1

    1. Before

      debug_remnants.ino
      #define DEBUG 1
      #define BYPASS_AUTH 1
      
      const char* password = "loginpw";
      
      void setup() {
        Serial.begin(115200);
      }
      
      void loop() {
        Serial.println(password);
        // TODO: remove before production
      }
    2. VibeGuard says

      HIGHAuth / security bypass flag[VG-EMB-021](confidence: medium)

      at debug_remnants.ino:2:1

      why
      A shipped bypass flag is a backdoor: whoever knows it (and it is in the firmware) skips authentication or verification entirely.
      fix
      Remove the bypass path. If a test hook is genuinely needed, gate it behind a build type that cannot be selected for release, not a runtime flag.
    3. After --fix

      debug_remnants.inoneeds-review
      +#define DEBUG 0
      +#define BYPASS_AUTH 0
      
      const char* password = "loginpw";
      
      void setup() {
        Serial.begin(115200);
      }
      
      void loop() {
        Serial.println(password);
        // TODO: remove before production
      }

      Turn the bypass flag off

      Findings still open after --fix: 3

Fixers exist for 7 of the 78 rules — 6 labelled needs-review, 1 labelled safe. VibeGuard offers an edit only for those, only when you pass --fix, and an edit it cannot show to be correct is not made: the finding stays instead. Every other rule is reported and left alone. See which rules have a fixer.

On your screen

There is no screenshot of the VS Code extension on this page. The rest of this page shows output the scanner produced; a drawing of the interface would be the only thing on it that nobody can check, so there is no drawing.

VS Code — findings appear inline when you save the file.
The Chrome extension: the Side Panel with a scanned snippet at the top and three findings below it, each showing severity, rule ID, line number and the matching line of code.
Chrome — scan the code on a page you are reading.

News

All releases