flaw

Fast static analysis tool for finding security flaws in Crystal code.
flaw logo

A fast static analysis tool for finding security flaws in Crystal code.

InstallationQuickstartGitHub ActionRulesContributingChangelog


flaw reads your Crystal source and holds it up to the light. Each rule looks for a specific security flaw — hardcoded secrets, command injection sinks, SQL built from interpolation, weak randomness used for tokens, untrusted YAML loads. Findings print with file and line, and can be emitted as JSON or SARIF for CI and GitHub Code Scanning.

Features

Scanning

  • Five built-in rules covering the common high-impact Crystal footguns
  • Per-rule severity override and path ignore via .flaw.yml
  • Fail-on threshold for CI gating (--fail-on high)
  • Recurses any directory of .cr files, skips lib/ and spec/ by default

Output

  • Pretty (colored, grouped by file, with snippet)
  • JSON for pipelines and agents
  • SARIF 2.1.0 for GitHub Code Scanning upload

Integration

  • Single static binary, zero runtime dependencies
  • Reusable GitHub Action (uses: kdairatchi/flaw@v0.1.0)
  • Non-zero exit on finding-at-threshold

Installation

From source

git clone https://github.com/kdairatchi/flaw.git
cd flaw
shards build --release --no-debug --production
./bin/flaw version

Homebrew (coming with v0.1.0 release)

brew install kdairatchi/tap/flaw

Pre-built binaries

Download from the Releases pagelinux-amd64, linux-arm64, macos-arm64.

Quickstart

flaw scan .                              # scan current directory, pretty output
flaw scan src/ --format json             # JSON for agents / pipelines
flaw scan . --format sarif > flaw.sarif
flaw scan . --fail-on high               # CI: exit 1 if any high+ finding
flaw rules                               # list built-in rules, grouped by tag
flaw rules FLAW001                       # show rule detail
flaw lint-rules                          # validate rules/ directory contract
flaw init config                         # drop a .flaw.yml config stub
flaw init rule FLAW011 my-new-rule       # scaffold a new rule folder + detector

GitHub Action

# .github/workflows/flaw.yml
name: flaw
on: [push, pull_request]
jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: kdairatchi/flaw@v0.1.0
        with:
          args: scan . --fail-on high --format sarif > flaw.sarif
      - uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: flaw.sarif

Rules

Security (FLAW0xx)

ID Severity Flaw
FLAW001 critical Command built from string interpolation
FLAW002 high Hardcoded secret literal
FLAW003 high SQL built via interpolation or concatenation
FLAW004 high Weak RNG near security-sensitive identifier
FLAW005 medium YAML parsed from untrusted input
FLAW006 high File access with user-controlled path
FLAW007 medium Redirect to user-supplied URL without allowlist
FLAW008 high Deserialization of untrusted data
FLAW009 high Weak hash (MD5/SHA1) for password or integrity
FLAW010 high TLS certificate verification disabled

AI-slop / hygiene (FLAW1xx)

Detects unedited LLM paste-through — the smell of vibe-coded Claude/ChatGPT output shipped without review. Novel territory: no other linter looks for these.

ID Severity Flaw
FLAW100 low Explanatory narration comment ("This function does X")
FLAW101 medium AI assistant boilerplate leaked into source
FLAW102 medium Placeholder value left in source (your-api-key-here, REPLACE_ME)

Every rule lives in its own folder under rules/ with the detector, a vulnerable fixture (bad.cr), a fixed version (good.cr), metadata (rule.yml), and docs. Add one with flaw init rule FLAW011 my-rule.

Rule validator

flaw lint-rules enforces the rule contract — every folder matches FLAWNNN, has all four required files, the rule.yml parses and has the required keys, the detector file exists, and each bad.cr + good.cr behaves as claimed. Run it in CI as the gatekeeper for rule contributions.

Configuration

.flaw.yml in your repo root:

version: 1
exclude:
  - spec/
  - lib/
  - vendor/
rules:
  FLAW002:
    ignore:
      - "examples/fake-keys.cr"
  FLAW004:
    severity: critical
  FLAW005:
    disabled: true

Roadmap

  • v0.2 — 10 more rules, --fix autofix for trivial cases, better SARIF provenance
  • v0.3 — LSP server (real-time flaws in your editor)
  • v0.4 — Baseline file (gate only on new findings)
  • v0.5 — Custom rule DSL (community rules in YAML)
  • v0.6 — Cross-file taint tracking (sources → sinks)
  • v1.0 — Plugin system, hosted rule docs at flaw.prowlrbot.com, Caido integration

Contributing

flaw is an open-source project built by one person and improved by many. See CONTRIBUTING.md for how to add a rule, report a false positive, or suggest a roadmap item.

Why "flaw"?

In gemology, a flaw is a fracture, inclusion, or imperfection inside a crystal — the thing a trained eye spots by catching the light right. flaw does the same for Crystal code: it holds your program up to the light and shows you the fractures before someone else does.

Security

Report suspected vulnerabilities privately — see SECURITY.md.

License

MIT © kdairatchi

Repository

flaw

Owner
Statistic
  • 1
  • 1
  • 0
  • 0
  • 0
  • about 6 hours ago
  • April 13, 2026
License

MIT License

Links
Synced at

Sun, 19 Apr 2026 00:11:26 GMT

Languages