https://github.com/sufield/stave
A configuration safety evaluator that detects cloud resources remaining unsafe for too long, using only local config snapshots without using any cloud credentials.
https://github.com/sufield/stave
Last synced: 5 months ago
JSON representation
A configuration safety evaluator that detects cloud resources remaining unsafe for too long, using only local config snapshots without using any cloud credentials.
- Host: GitHub
- URL: https://github.com/sufield/stave
- Owner: sufield
- License: apache-2.0
- Created: 2026-03-06T15:28:41.000Z (5 months ago)
- Default Branch: main
- Last Pushed: 2026-03-06T19:07:47.000Z (5 months ago)
- Last Synced: 2026-03-06T19:26:47.107Z (5 months ago)
- Language: Go
- Size: 4.93 MB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Security: SECURITY.md
Awesome Lists containing this project
README
# Stave
A configuration analysis engine that detects insecure configurations in your cloud environment using only local configuration snapshots — no cloud credentials required.
[Docs](docs/index.md) | [Quickstart](docs/time-to-first-finding.md) | [Releases](https://github.com/sufield/stave/releases) | [Security](SECURITY.md) | [Contributing](CONTRIBUTING.md)
[](https://securityscorecards.dev/viewer/?uri=github.com/sufield/stave)
[](https://goreportcard.com/report/github.com/sufield/stave)
[](https://codecov.io/gh/sufield/stave)
## Why Stave exists
Most existing S3 security tools share a blind spot. They treat Block Public Access as the definitive signal for public exposure. When BPA is enabled, buckets pass — even when legacy ACLs still grant public read or write. AWS Trusted Advisor is the most prominent example.
Stave catches what these tools miss. It evaluates the full configuration surface — ACLs, bucket policies, and BPA settings — against composable predicate logic, not a single-flag heuristic.
It works from local observation snapshots: offline, deterministic, and credential-free. No API calls, no runtime agents, no network access at scan time.
## What Stave does
Stave reads point-in-time configuration snapshots and evaluates them against YAML-defined safety controls:
- **43 built-in S3 controls** — public exposure, ACL escalation, encryption, versioning, lifecycle, object lock, logging, governance, takeover prevention
- **Unsafe duration tracking** — detects how long assets remain misconfigured across multiple snapshots
- **Deterministic output** — same input always produces same findings
- **Enforcement artifacts** — generates fix plans with specific remediation actions
All evaluation runs locally. No cloud credentials. No network access. Air-gapped by design.
## Quick start
### Install
```bash
brew tap sufield/tap && brew install stave
```
Or build from source:
```bash
git clone https://github.com/sufield/stave.git
cd stave && make build
```
### First finding in 60 seconds
```bash
stave demo
cat stave-report.json
```
Expected output:
```
Found 1 violation: CTL.S3.PUBLIC.001
Asset: s3://demo-public-bucket
Evidence: BlockPublicAccess=false, ACL=public-read
Fix: enable account/bucket Block Public Access + deny public principals
```
Compare with a safe configuration:
```bash
stave demo --fixture known-good
```
### Full workflow
```bash
stave init --profile aws-s3
stave validate
stave apply --format json > output/evaluation.json
stave diagnose
```
## How it works
```
Capture → Validate → Apply → Act
1. Capture Export asset configurations as JSON snapshots
2. Validate Check inputs are well-formed and complete
3. Apply Evaluate snapshots against safety controls, produce findings
4. Act Review findings, remediate, re-evaluate
```
Snapshots must conform to the [observation contract](docs/observation-contract.md). You need at least two snapshots (two points in time) for Stave to calculate unsafe duration windows.
## How Stave compares
| Category | Examples | No credentials needed | Offline snapshots | Deterministic | Duration aware | Enforcement |
|----------|----------|:---:|:---:|:---:|:---:|:---:|
| CSPM | AWS Config, Wiz, Prisma, Prowler | ❌ | ❌ | ❌ | ❌ | ⚠️ |
| IaC policy | OPA, Checkov, tfsec | ✅ | ❌ | ✅ | ❌ | ❌ |
| S3 auditors | ScoutSuite, s3audit, CloudMapper | ❌ | ❌ | ❌ | ❌ | ❌ |
| **Stave** | | ✅ | ✅ | ✅ | ✅ | ✅ |
Think of it as:
| Tool type | Analogy |
|-----------|---------|
| CSPM | Runtime cloud scanner |
| IaC policy | Template linter |
| S3 auditor | Exposure enumerator |
| **Stave** | Snapshot safety evaluator |
## Security model
- **Zero network access** — evaluation never contacts external services
- **No credentials** — works on exported snapshots, not live APIs
- **Deterministic output** — `--now` flag pins evaluation time for reproducibility
- **Output sanitization** — `--sanitize` scrubs asset identifiers from findings
- **Signed releases** — SHA256 checksums signed with Sigstore cosign
- **Build provenance** — GitHub-native SLSA attestation on release archives
- **SBOM** — SPDX Software Bill of Materials attached to every release
Details: [Security and Trust](docs/trust/01-security-and-trust.md) | [Threat Model](docs/security/threat-model.md) | [Verify a Release](docs/trust/verify-release.md)
## Built-in controls
Stave ships 43 S3 controls across 15 categories:
| Category | Controls | What they detect |
|----------|:---:|-----------------|
| `public` | 13 | Public read, write, list via policy, ACL, website hosting, prefix exposure |
| `acl` | 3 | ACL escalation (WRITE_ACP), reconnaissance (READ_ACP), FULL_CONTROL grants |
| `access` | 5 | Cross-account access, wildcard actions, external write, authenticated-users access |
| `encrypt` | 4 | Missing encryption at rest, in transit, KMS requirements for PHI |
| `versioning` | 2 | Disabled versioning, missing MFA delete on backups |
| `lock` | 3 | Missing object lock, wrong mode, insufficient retention for PHI |
| `logging` | 1 | Disabled access logging |
| `lifecycle` | 2 | Missing lifecycle rules, PHI retention below HIPAA minimum |
| `network` | 1 | Public-principal policies without IP/VPC conditions |
| `governance` | 1 | Missing data-classification tag |
| `write_scope` | 2 | Prefix-wide uploads, unrestricted content types |
| `tenant` | 1 | Missing prefix-based tenant isolation |
| `takeover` | 2 | Dangling bucket references, dangling CDN origins |
| `artifacts` | 1 | VCS artifacts exposed on public buckets |
| `misc` | 2 | Incomplete data preventing safety proof, completeness checks |
Full control reference: [docs/controls/authoring.md](docs/controls/authoring.md)
## CLI commands
| Command | Purpose |
|---------|---------|
| `demo` | First finding in 60 seconds |
| `quickstart` | Auto-detect snapshots and evaluate |
| `status` | Project state and next steps |
| `doctor` | Environment readiness check |
| `init` | Project scaffolding |
| `validate` | Input correctness |
| `plan` | Readiness gate |
| `apply` | Evaluate controls, produce findings |
| `diagnose` | Explain unexpected results |
| `trace` | Clause-level predicate detail |
| `ingest` | Convert AWS snapshots to observations |
| `controls list` | List available controls |
| `explain` | Show fields a control requires |
| `lint` | Control quality checks |
| `snapshot upcoming` | Next snapshot schedule |
| `snapshot prune` | Bounded snapshot retention |
| `snapshot diff` | Drift triage between snapshots |
| `ci baseline` | Save finding baseline |
| `ci gate` | Fail CI on new violations |
| `ci fix-loop` | Verify remediation in CI |
```
validate → plan → apply → diagnose
↓ ↓ ↓ ↓
Inputs Ready? Findings Insights
OK? Found? Why?
↓
trace
(clause detail)
```
## Concepts
| Term | Definition |
|------|------------|
| **Snapshot** | Point-in-time observation of infrastructure assets (JSON) |
| **Asset** | A single infrastructure component (e.g., S3 bucket) with properties |
| **Control** | A safety rule assets must satisfy (YAML, `ctrl.v1` schema) |
| **Unsafe predicate** | Conditions that mark an asset as unsafe |
| **Finding** | A detected violation with evidence and remediation guidance |
| **Episode** | A contiguous period where an asset remained unsafe |
| **Max unsafe duration** | Maximum time an asset may remain unsafe before violation |
## Data formats
| Format | Schema | Purpose |
|--------|--------|---------|
| Observations | `obs.v0.1` | Normalized snapshots — flat JSON, one file per timestamp |
| Controls | `ctrl.v1` | Safety rules — YAML with `unsafe_predicate` |
| Output | `out.v0.1` | Findings — JSON with `summary` and `findings` array |
Schema references: [ctrl.v1](docs/schema/ctrl.v1.md) | [obs.v0.1](docs/schema/obs.v0.1.md) | [out.v0.1](docs/schema/out.v0.1.md)
## Status
**v0.0.2**
- AWS S3 only
- Configuration snapshots only
- Offline evaluation
### Schema stability
| Schema | Version | Status |
|--------|---------|--------|
| Observations | `obs.v0.1` | Stable |
| Controls | `ctrl.v1` | Stable |
| Output | `out.v0.1` | Stable |
### Exit codes
| Code | Meaning |
|------|---------|
| 0 | Success |
| 2 | Input error |
| 3 | Violations found |
| 4 | Internal error |
| 130 | SIGINT |
## Documentation
- [Start here](docs/start-here.md)
- [Time to first finding](docs/time-to-first-finding.md)
- [Design philosophy](docs/design-philosophy.md)
- [System Invariant as Code](docs/system-invariant-as-code.md)
- [Evaluation semantics](docs/evaluation-semantics.md)
- [Authoring controls](docs/controls/authoring.md)
- [User documentation](docs/user-docs.md)
- [Architecture overview](docs/architecture/overview.md)
- [Full docs index](docs/index.md)
## Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md) for setup, development workflow, and PR guidelines.
- [Bug reproduction guide](docs/contrib/bug-repro-guide.md)
- [Bug template](docs/bug-template.md)
- [CLI style guide](docs/cli-style-guide.md)
## License
[Apache License 2.0](LICENSE)