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 it finds
- InjectionSQL, command, eval, deserialization, template20 rules
- Hardcoded secretsAWS keys, PEM blocks, GitHub tokens, API keys5 rules
- Auth & access controlDebug bypasses, placeholder tokens, role checks by string literal14 rules
- Weak crypto & cleartextMD5/SHA1, Math.random, http:// endpoints3 rules
- Framework misconfigDjango DEBUG, Flask debug=True, CORS wildcard4 rules
- Memory safety (C/C++)gets, strcpy, memcpy sized from strlen, same-block use-after-free6 rules
- AI leftoversStub implementations, placeholder emails, "for now" comments, near-miss imports12 rules
- Embedded & RTOSHard-coded Wi-Fi creds, setInsecure(), #define DEBUG 1, ISR-unsafe calls14 rules
What a finding looks like
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 };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.
After
--fixproto_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
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(); }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.
After
--fixnet_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
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 }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.
After
--fixdebug_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.
