AST-aware static checks for silent-failure bug classes that AI-generated code reintroduces. MIT.
Find a file
Empire OSS d263032a52 Cross-link tradehouse-mcp-quickstart (EAS open-source funnel)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 22:30:05 +00:00
.github/workflows bugclass-detectors v0.1.0 — five silent-failure bug-class checks (MIT) 2026-06-12 01:29:50 -07:00
bugclass_detectors bugclass-detectors v0.1.0 — five silent-failure bug-class checks (MIT) 2026-06-12 01:29:50 -07:00
examples bugclass-detectors v0.1.0 — five silent-failure bug-class checks (MIT) 2026-06-12 01:29:50 -07:00
tests bugclass-detectors v0.1.0 — five silent-failure bug-class checks (MIT) 2026-06-12 01:29:50 -07:00
.gitignore bugclass-detectors v0.1.0 — five silent-failure bug-class checks (MIT) 2026-06-12 01:29:50 -07:00
LICENSE bugclass-detectors v0.1.0 — five silent-failure bug-class checks (MIT) 2026-06-12 01:29:50 -07:00
pyproject.toml bugclass-detectors v0.1.0 — five silent-failure bug-class checks (MIT) 2026-06-12 01:29:50 -07:00
README.md Cross-link tradehouse-mcp-quickstart (EAS open-source funnel) 2026-06-12 22:30:05 +00:00

bugclass-detectors

AST-aware static checks for the silent-failure bug classes that AI-generated and fast-moving code keeps reintroducing.

These are not style nits. They are the bugs that pass code review, pass your tests, keep the process green — and silently lose data, fail open, or crash on the one unlucky path. They are exactly the classes an AI coding assistant reintroduces because each instance looks locally reasonable.

bugclass-detectors finds them with a real parser (not grep), in pure-stdlib Python, with zero config.

pip install bugclass-detectors          # or: pipx run bugclass-detectors .
bugclass-detectors src/                  # human report
bugclass-detectors src/ --lint           # exit 1 on any HIGH finding (CI gate)
bugclass-detectors src/ --json           # machine-readable

The five bug classes

ID Class What it catches Why it bites
C1 SWALLOWED_EXCEPTION_AROUND_WRITE A bare/catch-all except that swallows an exception wrapping a write (DB / cache / file) with no log and no re-raise. The producer stays alive, the heartbeat is green, the data is gone, and nothing logs. The single most dangerous silent-failure shape there is.
C2 UNDEFINED_NAME Use of a name never bound in its scope and not a builtin/import/param/closure var. A NameError that only fires on the code path you didn't test. (pyflakes F821 class, no pyflakes dependency.)
C3 HARDCODED_SECRET_LITERAL A password/token/key assigned to an inline string literal (in code or a systemd Environment=). Diverges silently the moment the real secret rotates → an outage with no obvious cause. Secrets are masked in output.
C4 FAIL_OPEN_FLAG A safety / kill / arming / feature gate read from a store repointable by one env var, with no presence assertion. If the flag is absent on the repointed store it reads falsy → the gate fails open instead of closed.
C5 ROTATED_SECRET_CAPTURED_ONCE A long-lived consumer (while True, a daemon) that captures a secret once at module scope. When the secret rotates the process keeps the stale value and silently 401/403s forever.

Every check is AST/tokenizer-aware (so it doesn't fire on the word in a comment or a string), read-only, and emits a uniform finding:

{ "check": "C1_SWALLOWED_WRITE", "severity": "HIGH",
  "file": "src/recorder.py", "lineno": 88,
  "snippet": "except Exception:",
  "why": "catch-all/bare except SILENTLY SWALLOWS a db/cache write `hset` — ..." }

Disable any check with BUGCLASS_DISABLE=C1,C4 or --checks C2,C3.


Quick start

git clone https://git.eliteaiempire.com/eas-oss/bugclass-detectors
cd bugclass-detectors
python -m bugclass_detectors examples/buggy_sample.py   # see all five fire
python tests/test_detectors.py                          # smoke tests

As a CI gate (GitHub Actions)

- name: bug-class lint
  run: pipx run bugclass-detectors . --lint --min-sev HIGH

--lint returns a non-zero exit on any HIGH finding, so a swallowed write or an undefined name fails the build.

As a library

from bugclass_detectors import run
for f in run(["./src"], checks=["C1", "C4"], min_sev="HIGH"):
    print(f["file"], f["lineno"], f["why"])

Why these five (and why a parser, not grep)

This pack started as the in-house lint that runs against a continuously-operating multi-service production estate. Each class on this list earned its place by causing a real silent outage in production — a recorder whose only output was swallowed for weeks behind a bare except, a feature gate that failed open when its flag-store was repointed, a credential captured once that 403'd silently after a rotation. The fix in every case was one line; the cost of not catching it was days.

Grep can't catch these without drowning you in false positives — except and password and kill appear constantly in comments, strings, and legitimate code. These checks parse the AST and tokenize the source, so they fire on the shape of the bug, not the word.


Limitations (honest)

  • Python only (today). The classes are language-agnostic; ports welcome.
  • C1/C4/C5 are heuristic — tuned to favor precision over recall (few false positives, will miss exotic phrasings). C2 is conservative (only flags provably-unbound names).
  • This is a focused tool, not a replacement for a full linter, type-checker, or SAST suite. Run it alongside them.

Want this run continuously, across every repo, with triage and auto-fix?

This open-source pack is the engine. Running it well at scale — across many repos and languages, with severity triage, suppression management, auto-fix PRs, dashboards, and a human in the loop — is an operations problem.

  • Elite Agentic Solutions runs this and a larger battery of production-hardened checks as a continuous code-health / audit-as-a-service for teams shipping AI-assisted code. We operate the gate so your pipeline doesn't regress.
  • CloudHostAI offers it as a one-click hosted scanner tile for your repos.

The library is, and will stay, free under MIT. The hosted operation is the paid product.


Contributing

Issues and PRs welcome — especially new bug classes that have caused you a real silent outage, and ports to other languages. Keep each check AST-aware, read-only, and dependency-free.

License

MIT © Elite Agentic Solutions. See LICENSE.

More from Elite Agentic Solutions (open source)