FiberAudit
FiberAudit audits Ruby and Rails code for operations that can block the thread running a Fiber scheduler. Version 0.1.0 performs static analysis only.
Static-only disclaimer: This is a static-only audit. PASS cannot be granted without runtime coverage.
Requirements and installation
FiberAudit v0.1.0 supports Ruby 3.3 and 3.4.
gem install fiber_audit
Or add it to a bundle and run bundle install:
gem "fiber_audit", require: false
Quick start
Run from a project directory or any directory beneath it:
fiber-audit static
FiberAudit walks upward to find the nearest Gemfile, gems.rb, or
config/application.rb. It loads .fiber-audit.yml from that root when the
file exists.
fiber-audit static [--format text|json] [--config PATH] [--out PATH]
[--min-severity LEVEL] [--no-color]
fiber-audit list-rules
fiber-audit explain FA1001
fiber-audit version
Output defaults to text on a TTY and JSON when piped. --out PATH defaults to
JSON, writes only the report to that file, and prints a one-line confirmation.
Explicit --format always wins.
Shipped rules
| ID | Detects | Default severity |
|---|---|---|
| FA1001 | Blocking subprocess operations | high |
| FA1002 | Thread#join and Thread#value |
high |
| FA1003 | Thread-oriented synchronization | medium |
| FA1004 | Thread-local state access | high/medium |
| FA1005 | Explicit IO.select/Kernel.select |
medium |
| FA1006 | Direct socket construction | medium |
| FA1007 | Synchronous HTTP in request-like contexts | high |
Use fiber-audit explain <RULE_ID> for exact targets and remediation.
Configuration
Copy .fiber-audit.example.yml to .fiber-audit.yml in the project root.
Paths and globs are rooted at the detected project. An explicit --config
path is resolved from the directory where the command was invoked.
static:
include:
- app/**/*.rb
- lib/**/*.rb
- config/**/*.rb
exclude:
- vendor/**/*
- tmp/**/*
- db/schema.rb
suppressions_path: .fiber-audit-suppressions.yml
rules:
FA1007:
enabled: false
FA1003:
severity: low
report:
formats: [text, json]
min_severity: low
--min-severity overrides report.min_severity for one run. Severity ordering
is critical, high, medium, low, info; findings below the threshold
are omitted and do not affect the exit code. The default low threshold keeps
informational findings silent.
Suppressions
Every suppression requires a non-empty reason. Directive-looking text inside strings, heredocs, or regular expressions is ignored.
Suppress one line:
system(command) # fiber-audit:disable FA1001 -- trusted maintenance command
Suppress a block:
# fiber-audit:disable FA1003 -- protected legacy boundary
mutex.synchronize { update_record }
# fiber-audit:enable FA1003
A separate YAML file can suppress by rule and optionally by symbol or
operation. Point static.suppressions_path at the file:
suppressions:
- rule: FA1001
symbol: Reports::Generator#call
operation: Open3.capture3
reason: isolated worker process with an external timeout
Missing reasons and invalid configuration return exit code 2.
Static statuses
FAIL— at least one critical or high finding.REVIEW— a medium finding, or a non-informational low/unknown-confidence finding.PASS_WITH_WARNINGS— only low or informational findings.NO_FINDINGS— no findings at the configured threshold.
FiberAudit never emits unconditional PASS in v0.1.0.
Exit codes
| Code | Meaning |
|---|---|
| 0 | No active finding at or above the configured threshold |
| 1 | One or more active findings at or above the threshold |
| 2 | Invalid options, configuration, analysis, or report output |
| 3 | Reserved; never emitted by v0.1.0 |
Source parse errors are included in report data while analysis continues on other files.
See ARCHITECTURE.md for implementation boundaries and the future runtime-analysis architecture.