{"id":46110013,"url":"https://github.com/jostled-org/pedant","last_synced_at":"2026-04-25T20:04:53.885Z","repository":{"id":341458407,"uuid":"1170175516","full_name":"jostled-org/pedant","owner":"jostled-org","description":"Rust static analyzer that combines style enforcement, capability detection, and security rules.","archived":false,"fork":false,"pushed_at":"2026-04-20T04:29:44.000Z","size":666,"stargazers_count":6,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-20T06:36:55.691Z","etag":null,"topics":["clippy","code-quality","developer-tools","linter","rust","rust-analyzer","static-analysis"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jostled-org.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-01T20:08:40.000Z","updated_at":"2026-04-20T04:28:24.000Z","dependencies_parsed_at":"2026-04-02T03:07:54.378Z","dependency_job_id":null,"html_url":"https://github.com/jostled-org/pedant","commit_stats":null,"previous_names":["jostled-org/pedant"],"tags_count":75,"template":false,"template_full_name":null,"purl":"pkg:github/jostled-org/pedant","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jostled-org%2Fpedant","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jostled-org%2Fpedant/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jostled-org%2Fpedant/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jostled-org%2Fpedant/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jostled-org","download_url":"https://codeload.github.com/jostled-org/pedant/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jostled-org%2Fpedant/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32163853,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-23T02:19:40.750Z","status":"ssl_error","status_checked_at":"2026-04-23T02:17:55.737Z","response_time":53,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["clippy","code-quality","developer-tools","linter","rust","rust-analyzer","static-analysis"],"created_at":"2026-03-01T22:11:48.016Z","updated_at":"2026-04-25T20:04:53.879Z","avatar_url":"https://github.com/jostled-org.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![crates.io](https://img.shields.io/crates/v/pedant)](https://crates.io/crates/pedant)\n[![docs.rs](https://img.shields.io/docsrs/pedant-core)](https://docs.rs/pedant-core)\n[![CI](https://github.com/jostled-org/pedant/actions/workflows/ci.yml/badge.svg)](https://github.com/jostled-org/pedant/actions/workflows/ci.yml)\n[![license](https://img.shields.io/crates/l/pedant)](LICENSE-MIT)\n\n**pedant** maps what code can do — network access, filesystem operations, crypto, process execution — across Rust, Python, JavaScript/TypeScript, Go, and Bash. It hashes dependency source on every build and alerts when capabilities change. A supply chain attack that adds `file_read` or `env_access` to a library is caught before the compromised code runs.\n\n## What it catches\n\nA dependency update adds environment variable exfiltration to a library that previously only did HTTP:\n\n```\n$ pedant diff baseline.json current.json\n{\n  \"added\": [\n    {\"capability\": \"env_access\", \"evidence\": \"std::env::var\"},\n    {\"capability\": \"file_read\", \"evidence\": \"std::fs::read_to_string\"}\n  ],\n  \"new_capabilities\": [\"env_access\", \"file_read\"]\n}\n```\n\nA build script phones home during compilation:\n\n```\n$ pedant gate build.rs\n::error:: build-script-network: build script has network access (deny)\n::error:: build-script-download-exec: build script downloads and executes (deny)\n```\n\nNesting three levels deep in a match arm:\n\n```\n$ pedant check -d 2 src/lib.rs\nsrc/lib.rs:5:17: if-in-match: if inside match arm, consider match guard\nsrc/lib.rs:5:17: max-depth: nesting depth 3 exceeds limit of 2\n```\n\n## Quick start\n\n```bash\n# Install\ncargo install pedant\n\n# Scan a project for capabilities\npedant capabilities src/**/*.rs scripts/*.py\n\n# Check for suspicious patterns\npedant gate src/**/*.rs\n\n# Set up CI supply chain monitoring (see examples/supply-chain-check.md)\n```\n\nMigrating from the old flat flag CLI? See [docs/migrating-from-flat-cli.md](docs/migrating-from-flat-cli.md).\n\n## CI Supply Chain Check\n\nThe included GitHub Action hashes every dependency's source and compares against stored baselines on every build. It detects:\n\n- **Tag-swap attacks** — same version number, different content (hash mismatch)\n- **Capability drift** — new capabilities appearing in a dependency update\n- **New unaudited dependencies** — dependencies with no existing baseline\n\n```yaml\n# .github/workflows/ci.yml\njobs:\n  supply-chain:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2\n      - uses: dtolnay/rust-toolchain@a54c7afe936fefeb4456b2dd8068152669aa8211 # stable\n      - uses: jostled-org/pedant/.github/actions/supply-chain-check@\u003ccommit\u003e # pin to commit\n        with:\n          baseline-path: .pedant/baselines\n          fail-on: hash-mismatch\n```\n\nPedant is built from the same pinned commit as the action — no registry fetch, one trust boundary. See [examples/supply-chain-check.md](examples/supply-chain-check.md) for setup, baseline management, and configuration.\n\n## Capability Detection\n\n```bash\n# Rust, Python, JS/TS, Go, Bash — language detected automatically\npedant capabilities src/**/*.rs scripts/*.py deploy/*.sh\n\n# Attestation: capability profile + SHA-256 source hash + crate identity\npedant attestation --crate-name my-crate --crate-version 0.1.0 src/**/*.rs\n\n# Diff two profiles or attestations\npedant diff old.json new.json\n```\n\n| Capability | What triggers it |\n|---|---|\n| `network` | `std::net`, `reqwest`, `curl`, `fetch()`, `net/http`, URL literals |\n| `file_read` | `std::fs`, `open()`, `os.Open()` |\n| `file_write` | `std::fs::write`, `cp`, `mv`, `rm` |\n| `process_exec` | `std::process`, `subprocess`, `exec`, `bash -c` |\n| `env_access` | `std::env::var`, `process.env`, `os.Getenv`, `export` |\n| `unsafe_code` | `unsafe` blocks, `unsafe fn`, `unsafe impl` |\n| `ffi` | `extern` blocks, `ctypes`, `import \"C\"` |\n| `crypto` | `ring`, `openssl`, PEM blocks, hex keys, credential prefixes |\n| `system_time` | `SystemTime`, `chrono`, `time` |\n| `proc_macro` | `#[proc_macro]`, `#[proc_macro_derive]` |\n\nGate rules evaluate per language group by default. Use `--cross-language` to merge all findings for combined evaluation.\n\nSee [examples/capability-detection.md](examples/capability-detection.md) for the full guide: output format, all 24 gate rules, multi-language details, string literal analysis, attestation, and diffing.\n\n## Style Checks (Rust)\n\n23 checks across five categories. Nesting checks run by default; everything else requires a `.pedant.toml` config.\n\n```bash\npedant check src/**/*.rs            # check files\npedant check -d 2 src/lib.rs        # custom depth limit\npedant list-checks                  # see all checks\npedant explain max-depth            # detailed rationale\n```\n\n| Category | Checks |\n|----------|--------|\n| Nesting | `max-depth`, `nested-if`, `if-in-match`, `nested-match`, `match-in-if`, `else-chain` |\n| Forbidden patterns | `forbidden-attribute`, `forbidden-type`, `forbidden-call`, `forbidden-macro`, `forbidden-else`, `forbidden-unsafe` |\n| Performance \u0026 dispatch | `dyn-return`, `dyn-param`, `vec-box-dyn`, `dyn-field`, `clone-in-loop`, `default-hasher` |\n| Structure | `mixed-concerns`, `inline-tests`, `let-underscore-result`, `high-param-count` |\n| Naming | `generic-naming` |\n\nTo run pedant as a [Claude Code hook](examples/pedant-claude-code-hook.md) that blocks AI-generated code on every edit:\n\n```json\n{\n  \"hooks\": {\n    \"PostToolUse\": [\n      {\n        \"matcher\": \"Write|Edit\",\n        \"hooks\": [{ \"type\": \"command\", \"command\": \"~/.claude/hooks/pedant-check.sh\" }]\n      }\n    ]\n  }\n}\n```\n\n## Semantic Analysis (Rust)\n\nWith the `semantic` feature, pedant resolves types through aliases using rust-analyzer and enables data flow analysis: taint tracking (environment variables flowing to network sinks), quality checks (dead stores, discarded results), performance checks (unnecessary clones, allocation in loops), and concurrency checks (lock guards across await points).\n\n```bash\ncargo install pedant --features semantic\npedant gate --semantic src/**/*.rs\n```\n\n## MCP Server\n\n`pedant-mcp` exposes analysis as MCP tools for AI agents.\n\n```bash\ncargo install pedant-mcp\nclaude mcp add --transport stdio --scope user pedant -- pedant-mcp\n```\n\nTools: `query_capabilities`, `query_gate_verdicts`, `query_violations`, `search_by_capability`, `explain_finding`, `audit_crate`, `find_structural_duplicates`.\n\n## Configuration\n\n```toml\n# .pedant.toml\nmax_depth = 2\nforbid_else = true\ncheck_clone_in_loop = true\n\n[forbid_calls]\nenabled = true\npatterns = [\".unwrap()\", \".expect(*)\"]\n\n[gate]\nbuild-script-exec = false          # disable a rule\nenv-access-network = \"warn\"        # override severity\n\n[overrides.\"tests/**\"]\nmax_depth = 5\n\n[overrides.\"tests/**\".forbid_calls]\nenabled = false\n```\n\nConfig loads from `.pedant.toml` (project) or `~/.config/pedant/config.toml` (global). Project wins. See [examples/](examples/) for full configs.\n\n## License\n\n[MIT](LICENSE-MIT) or [Apache-2.0](LICENSE-APACHE), at your option.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjostled-org%2Fpedant","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjostled-org%2Fpedant","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjostled-org%2Fpedant/lists"}