|
1 | 1 | <p align="center"> |
2 | 2 | <h1 align="center">Inspect</h1> |
3 | 3 | <p align="center"> |
4 | | - <strong>Security vulnerability scanner for code</strong> |
| 4 | + <strong>Live website auditor for accessibility, TLS, cookies, and security headers</strong> |
5 | 5 | </p> |
6 | 6 | <p align="center"> |
7 | | - <a href="https://golang.org/"><img src="https://img.shields.io/badge/Go-1.23+-00ADD8?style=flat-square&logo=go&logoColor=white" alt="Go"></a> |
| 7 | + <a href="https://golang.org/"><img src="https://img.shields.io/badge/Go-1.26+-00ADD8?style=flat-square&logo=go&logoColor=white" alt="Go"></a> |
8 | 8 | <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue?style=flat-square" alt="License"></a> |
9 | 9 | <a href="https://github.com/GrayCodeAI/inspect/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/GrayCodeAI/inspect/ci.yml?style=flat-square&label=tests" alt="CI"></a> |
10 | 10 | </p> |
11 | 11 | </p> |
12 | 12 |
|
13 | 13 | --- |
14 | 14 |
|
15 | | -Inspect scans code for security vulnerabilities, anti-patterns, and potential issues. It provides actionable findings with severity ratings and remediation guidance. |
| 15 | +## What is inspect |
16 | 16 |
|
17 | | -## Features |
| 17 | +inspect is a Go library that crawls live **websites** and audits the pages it |
| 18 | +finds — broken links, security headers, forms, accessibility, performance, SEO, |
| 19 | +TLS, cookies, mixed content, subresource integrity, AI-readiness, and |
| 20 | +reachability. It is part of the [hawk](https://github.com/GrayCodeAI/hawk) ecosystem: |
| 21 | +hawk wires inspect into its own commands, and inspect also ships an MCP server |
| 22 | +so any MCP-compatible agent can run audits. |
18 | 23 |
|
19 | | -- **Multi-language support** - Scans Go, Python, JavaScript, TypeScript, and more |
20 | | -- **OWASP coverage** - Detects common vulnerability patterns |
21 | | -- **Custom rules** - Define project-specific security policies |
22 | | -- **CI/CD integration** - Fails builds on critical issues |
| 24 | +> **inspect is a Go library (and MCP server), not a CLI.** It ships no `inspect` |
| 25 | +> binary of its own — it analyzes running URLs, not source code. Import it |
| 26 | +> directly to embed website auditing in your own Go program, or run the MCP |
| 27 | +> server to expose it to an agent. |
23 | 28 |
|
24 | | -## Quick Start |
| 29 | +It crawls concurrently (with rate limiting, robots.txt support, redirect |
| 30 | +handling, and SSRF protection), runs each check against the discovered pages, |
| 31 | +and returns findings with severity levels. Results can be emitted as SARIF for |
| 32 | +the GitHub Security tab. |
25 | 33 |
|
26 | | -```bash |
27 | | -go get github.com/GrayCodeAI/inspect |
28 | | -``` |
| 34 | +## Quick Start |
29 | 35 |
|
30 | 36 | ```go |
31 | | -import "github.com/GrayCodeAI/inspect" |
| 37 | +import ( |
| 38 | + "context" |
| 39 | + "fmt" |
32 | 40 |
|
33 | | -scanner := inspect.NewScanner( |
34 | | - inspect.WithRules(inspect.DefaultRules), |
| 41 | + "github.com/GrayCodeAI/inspect" |
35 | 42 | ) |
36 | 43 |
|
37 | | -report, err := scanner.Scan(ctx, "./path/to/code") |
| 44 | +// One-shot scan with the Standard preset. |
| 45 | +report, err := inspect.Scan(ctx, "https://example.com", inspect.Standard) |
| 46 | +if err != nil { |
| 47 | + // handle error |
| 48 | +} |
38 | 49 | for _, f := range report.Findings { |
39 | | - fmt.Printf("[%s] %s - %s\n", f.Severity, f.Rule, f.Message) |
| 50 | + fmt.Printf("[%s] %s: %s\n", f.Severity, f.URL, f.Message) |
| 51 | +} |
| 52 | +``` |
| 53 | + |
| 54 | +Requires Go 1.26+. |
| 55 | + |
| 56 | +For repeated or high-throughput scans, reuse a `Scanner` (safe for concurrent use): |
| 57 | + |
| 58 | +```go |
| 59 | +scanner := inspect.NewScanner(inspect.Standard, inspect.WithDepth(3)) |
| 60 | +r1, _ := scanner.Scan(ctx, "https://site-a.com") |
| 61 | +r2, _ := scanner.Scan(ctx, "https://site-b.com") |
| 62 | +``` |
| 63 | + |
| 64 | +## Features |
| 65 | + |
| 66 | +inspect ships nine built-in checks (registered in `check.DefaultRegistry`). The |
| 67 | +six marked **(default)** run in the `Standard`, `Deep`, and `CI` presets; the |
| 68 | +remaining three are opt-in via `WithChecks`. |
| 69 | + |
| 70 | +- **Links** *(default)* — crawls and reports broken/unreachable links |
| 71 | +- **Security headers** *(default)* — detects missing CSP, HSTS, and related |
| 72 | + headers; also audits TLS certificate validity/expiry, cookie `Secure` / |
| 73 | + `HttpOnly` / `SameSite` flags, and mixed content on HTTPS pages |
| 74 | +- **Forms** *(default)* — form validation checks (CSRF, action URLs) |
| 75 | +- **Accessibility (`a11y`)** *(default)* — meta/ARIA checks; optional axe-core |
| 76 | + and color-contrast analysis through the `browser` sub-module (headless |
| 77 | + Chromium via rod) |
| 78 | +- **Performance (`perf`)** *(default)* — resource sizes and render-blocking |
| 79 | + resources |
| 80 | +- **SEO** *(default)* — meta tags, structured data, and metadata checks |
| 81 | +- **SRI** — Subresource Integrity validation |
| 82 | +- **AI-ready (`aiready`)** — checks for agent/LLM-friendly metadata |
| 83 | +- **Reachability** — host/URL reachability checks |
| 84 | +- **Concurrent crawler** — depth limits, rate limiting, robots.txt, redirect |
| 85 | + following, and SSRF protection (private IPs blocked by default) |
| 86 | +- **SARIF output** — `inspect.GenerateSARIF` emits SARIF 2.1.0 for the GitHub |
| 87 | + Security tab |
| 88 | +- **MCP server** — expose `inspect_scan` and `inspect_scan_dir` to any agent |
| 89 | +- **Extensible** — register custom `Checker` implementations or declarative |
| 90 | + `RuleCheck` patterns |
| 91 | + |
| 92 | +## Presets |
| 93 | + |
| 94 | +The default checks are: `links`, `security`, `forms`, `a11y`, `perf`, `seo`. |
| 95 | +Add the opt-in checks (`sri`, `aiready`, `reachability`) with `WithChecks`. |
| 96 | + |
| 97 | +| Preset | Behavior | |
| 98 | +|---|---| |
| 99 | +| `Quick` | Shallow crawl (depth 2), `links` only | |
| 100 | +| `Standard` | Balanced crawl (depth 5), the six default checks | |
| 101 | +| `Deep` | Exhaustive crawl (no depth limit), the six default checks | |
| 102 | +| `SecurityOnly` | Security-related checks only | |
| 103 | +| `CI` | Default checks, fail on high severity | |
| 104 | + |
| 105 | +## MCP Server |
| 106 | + |
| 107 | +inspect ships an MCP server (stdio transport) that exposes website auditing to |
| 108 | +any MCP-compatible agent: |
| 109 | + |
| 110 | +```go |
| 111 | +import inspectmcp "github.com/GrayCodeAI/inspect/mcp" |
| 112 | + |
| 113 | +srv := inspectmcp.New(inspect.Standard) |
| 114 | +if err := srv.ServeStdio(); err != nil { |
| 115 | + // handle error |
40 | 116 | } |
41 | 117 | ``` |
42 | 118 |
|
| 119 | +**Tools:** |
| 120 | + |
| 121 | +- `inspect_scan` — crawl a URL and run the configured checks |
| 122 | +- `inspect_scan_dir` — serve and scan a local directory of HTML files |
| 123 | + |
| 124 | +## Browser-Rendered Analysis |
| 125 | + |
| 126 | +By default inspect analyzes raw HTTP responses. To analyze JavaScript-rendered |
| 127 | +pages and run axe-core accessibility checks, supply a `BrowserEngine` from the |
| 128 | +`browser` sub-module: |
| 129 | + |
| 130 | +```go |
| 131 | +import "github.com/GrayCodeAI/inspect/browser" |
| 132 | + |
| 133 | +engine, err := browser.New() |
| 134 | +if err != nil { |
| 135 | + // handle error |
| 136 | +} |
| 137 | +defer engine.Close() |
| 138 | + |
| 139 | +report, err := inspect.Scan(ctx, "https://example.com", |
| 140 | + inspect.Standard, |
| 141 | + inspect.WithBrowser(engine), |
| 142 | +) |
| 143 | +``` |
| 144 | + |
| 145 | +## Custom Checks |
| 146 | + |
| 147 | +```go |
| 148 | +// Declarative rule — no Go code beyond the struct. |
| 149 | +inspect.RegisterRule(inspect.RuleCheck{ |
| 150 | + RuleName: "x-frame-options", |
| 151 | + RuleSeverity: inspect.SeverityHigh, |
| 152 | + HeaderMissing: []string{"X-Frame-Options"}, |
| 153 | +}) |
| 154 | + |
| 155 | +// Full Checker implementation, scoped to a single Scanner. |
| 156 | +scanner := inspect.NewScanner(inspect.WithCustomChecks(myCheck)) |
| 157 | +``` |
| 158 | + |
43 | 159 | ## Examples |
44 | 160 |
|
45 | 161 | See the [examples/](examples/) directory for runnable code samples. |
46 | 162 |
|
47 | | -## Configuration |
| 163 | +## Architecture |
48 | 164 |
|
49 | | -Create `.inspect.yaml` to customize scanning: |
| 165 | +See [docs/architecture.md](docs/architecture.md) for the package layout and data flow. |
50 | 166 |
|
51 | | -```yaml |
52 | | -rules: |
53 | | - - name: no-hardcoded-secrets |
54 | | - severity: critical |
55 | | - - name: sql-injection |
56 | | - severity: high |
57 | | -ignore: |
58 | | - - vendor/ |
59 | | - - testdata/ |
60 | | -``` |
| 167 | +## Ecosystem |
| 168 | + |
| 169 | +inspect is part of the hawk ecosystem: |
| 170 | + |
| 171 | +| Component | Repository | Purpose | |
| 172 | +|---|---|---| |
| 173 | +| **hawk** | [GrayCodeAI/hawk](https://github.com/GrayCodeAI/hawk) | AI coding agent | |
| 174 | +| **eyrie** | [GrayCodeAI/eyrie](https://github.com/GrayCodeAI/eyrie) | LLM provider runtime | |
| 175 | +| **yaad** | [GrayCodeAI/yaad](https://github.com/GrayCodeAI/yaad) | Graph-based memory | |
| 176 | +| **inspect** | This repo | Website audit library + MCP server | |
61 | 177 |
|
62 | 178 | ## Contributing |
63 | 179 |
|
|
0 commit comments