Skip to content

Commit 29d2547

Browse files
committed
feat: add LICENSE, release workflow, README
1 parent 5afe923 commit 29d2547

File tree

3 files changed

+300
-0
lines changed

3 files changed

+300
-0
lines changed

.github/workflows/release.yml

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*.*.*'
7+
8+
env:
9+
CARGO_TERM_COLOR: always
10+
11+
jobs:
12+
build:
13+
name: Build ${{ matrix.target }}
14+
runs-on: ${{ matrix.os }}
15+
strategy:
16+
matrix:
17+
include:
18+
# Linux
19+
- target: x86_64-unknown-linux-musl
20+
os: ubuntu-latest
21+
name: bashtion-linux-x86_64.tar.gz
22+
- target: aarch64-unknown-linux-musl
23+
os: ubuntu-latest
24+
name: bashtion-linux-aarch64.tar.gz
25+
26+
# macOS
27+
- target: x86_64-apple-darwin
28+
os: macos-latest
29+
name: bashtion-macos-x86_64.tar.gz
30+
- target: aarch64-apple-darwin
31+
os: macos-latest
32+
name: bashtion-macos-aarch64.tar.gz
33+
34+
35+
steps:
36+
- name: Checkout
37+
uses: actions/checkout@v4
38+
39+
- name: Install Rust
40+
uses: dtolnay/rust-toolchain@stable
41+
with:
42+
targets: ${{ matrix.target }}
43+
44+
- name: Install cross for musl targets
45+
if: contains(matrix.target, 'linux-musl')
46+
run: cargo install cross --git https://github.com/cross-rs/cross
47+
48+
- name: Cache cargo
49+
uses: actions/cache@v4
50+
with:
51+
path: |
52+
~/.cargo/registry/index/
53+
~/.cargo/registry/cache/
54+
~/.cargo/git/db/
55+
target/
56+
key: ${{ runner.os }}-cargo-${{ matrix.target }}-${{ hashFiles('**/Cargo.lock') }}
57+
58+
- name: Build binary (cross for musl)
59+
if: contains(matrix.target, 'linux-musl')
60+
run: cross build --release --target ${{ matrix.target }}
61+
62+
- name: Build binary (cargo for others)
63+
if: "!contains(matrix.target, 'linux-musl')"
64+
run: cargo build --release --target ${{ matrix.target }}
65+
66+
- name: Strip binary (unix)
67+
if: "!contains(matrix.target, 'linux-musl')"
68+
run: strip target/${{ matrix.target }}/release/bashtion
69+
70+
- name: Create archive
71+
run: |
72+
cd target/${{ matrix.target }}/release
73+
tar czf ../../../${{ matrix.name }} bashtion
74+
cd -
75+
76+
- name: Generate SHA256 checksum
77+
run: |
78+
shasum -a 256 ${{ matrix.name }} > ${{ matrix.name }}.sha256
79+
shell: bash
80+
81+
- name: Upload artifact
82+
uses: actions/upload-artifact@v4
83+
with:
84+
name: ${{ matrix.name }}
85+
path: |
86+
${{ matrix.name }}
87+
${{ matrix.name }}.sha256
88+
89+
release:
90+
name: Create Release
91+
needs: build
92+
runs-on: ubuntu-latest
93+
steps:
94+
- name: Checkout
95+
uses: actions/checkout@v4
96+
97+
- name: Download artifacts
98+
uses: actions/download-artifact@v4
99+
with:
100+
merge-multiple: true
101+
102+
- name: Extract version from tag
103+
id: version
104+
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
105+
106+
- name: Create Release
107+
uses: softprops/action-gh-release@v2
108+
with:
109+
tag_name: ${{ github.ref_name }}
110+
name: Bashtion v${{ steps.version.outputs.VERSION }}
111+
body: |
112+
# Bashtion v${{ steps.version.outputs.VERSION }}
113+
114+
Bashtion inspects shell scripts before they reach your interpreter. Pipelines like `curl ... | bashtion` give you AI and static analysis plus a manual confirmation prompt.
115+
116+
## 🚀 Quick Install
117+
118+
```bash
119+
curl -fsSL https://raw.githubusercontent.com/chriswessels/bashtion/${{ github.ref_name }}/install.sh | bash
120+
```
121+
122+
Or download a platform archive below:
123+
124+
- `bashtion-linux-x86_64.tar.gz`
125+
- `bashtion-linux-aarch64.tar.gz`
126+
- `bashtion-macos-x86_64.tar.gz`
127+
- `bashtion-macos-aarch64.tar.gz`
128+
129+
Each archive contains a single `bashtion` (or `bashtion.exe`) binary. Extract, move it into your `$PATH`, and run `bashtion --help`.
130+
131+
## 📋 Assets
132+
133+
All binaries are built with `cargo build --release` (musl for Linux). SHA256 checksums are included for verification.
134+
135+
## 🔄 Changes
136+
137+
See the [commit history](https://github.com/chriswessels/bashtion/commits/${{ github.ref_name }}) for detailed changes in this release.
138+
files: |
139+
bashtion-*.tar.gz
140+
*.sha256
141+
draft: false
142+
prerelease: false

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025 Chris Wessels
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
# Bashtion 🛡️
2+
3+
Bashtion intercepts shell scripts before they hit your interpreter. It captures the script, runs static and AI-powered safety analysis, shows you the findings, and only executes after you explicitly confirm. Think of it as "curl | bash" with a security checkpoint.
4+
5+
[![Rust](https://img.shields.io/badge/rust-1.83+-orange.svg)](https://www.rust-lang.org)
6+
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
7+
[![CI](https://github.com/chriswessels/bashtion/workflows/CI/badge.svg)](https://github.com/chriswessels/bashtion/actions)
8+
[![Release](https://img.shields.io/github/v/release/chriswessels/bashtion)](https://github.com/chriswessels/bashtion/releases)
9+
10+
## ✨ Features
11+
12+
- **🛡️ Double Analysis**: Tree-sitter-based static checks plus LLM intent/risk summaries on every script
13+
- **🔍 Full Transparency**: Shows exact code snippets for each finding, logs overall risk, and requires your confirmation
14+
- **💻 Shell-Agnostic**: Supports any `stdin` source (`curl ... | bashtion`) and runs in whatever shell you configure
15+
- **⚙️ Structured Reports**: Colorized terminal output, structured JSON verdicts, and manual review prompt by default
16+
- **🧪 Manual Test Scripts**: Sample scripts (`scripts/manual/*.sh`) exercise different detections for easy regression testing
17+
- **🔌 Configurable Backend**: Works with OpenAI-compatible endpoints (override base URL, key, model, timeouts) and falls back gracefully when AI is unavailable
18+
- **📦 Installer**: Single `install.sh` fetches the correct binary for macOS/Linux and keeps the repo overrideable via env vars
19+
20+
## 🚀 Quick Start
21+
22+
### Installation
23+
24+
#### 📦 Pre-built Binaries
25+
26+
```bash
27+
curl -fsSL https://raw.githubusercontent.com/chriswessels/bashtion/main/install.sh | bash
28+
```
29+
30+
Manual downloads: grab the latest tarball for your platform from the [releases page](https://github.com/chriswessels/bashtion/releases/latest).
31+
32+
#### 🔧 From Source (Rust 1.83+)
33+
34+
```bash
35+
git clone https://github.com/chriswessels/bashtion
36+
cd bashtion
37+
cargo install --path .
38+
```
39+
40+
#### 📋 Verify Installation
41+
42+
```bash
43+
bashtion --version
44+
```
45+
46+
### Basic Usage
47+
48+
```bash
49+
# Inspect a remote installer before execution
50+
curl https://example.com/install.sh | bashtion
51+
52+
# Capture stdin but skip execution (print script to stdout)
53+
curl https://example.com/install.sh | bashtion --no-exec
54+
55+
# Use a custom OpenAI-compatible endpoint
56+
BASHTION_OPENAI_BASE_URL=https://llm.example.com/v1 \
57+
BASHTION_OPENAI_API_KEY=sk-... \
58+
curl https://example.com/install.sh | bashtion
59+
60+
# Force a different shell to execute the approved script
61+
BASHTION_EXEC_SHELL=/bin/zsh curl https://example.com/install.sh | bashtion
62+
63+
# Analyze a local script non-interactively
64+
bashtion < scripts/manual/static_eval.sh
65+
```
66+
67+
During each run Bashtion:
68+
1. Reads stdin into a bounded buffer (default 500 KB)
69+
2. Runs static analysis and AI analysis (if configured)
70+
3. Presents findings + summary
71+
4. Prompts “[y/N]” before actually executing the script via your shell (unless `--no-exec`)
72+
73+
## ⚙️ Configuration
74+
75+
All settings can be controlled via CLI flags or `BASHTION_*` env vars:
76+
77+
| Flag / Env | Description | Default |
78+
|------------|-------------|---------|
79+
| `--no-exec` / `BASHTION_AUTO_EXEC=false` | Skip shell execution; print script instead | auto-exec on |
80+
| `--exec-shell` / `BASHTION_EXEC_SHELL` | Shell command used to run approved scripts | `/bin/bash` |
81+
| `--timeout-secs` / `BASHTION_TIMEOUT_SECS` | HTTP timeout for AI calls | 30s |
82+
| `--buffer-limit` / `BASHTION_BUFFER_LIMIT` | Max bytes read from stdin | 512 KB |
83+
| `BASHTION_OPENAI_BASE_URL` | OpenAI-compatible endpoint base URL | unset (AI disabled) |
84+
| `BASHTION_OPENAI_API_KEY` | API key for the endpoint | unset |
85+
| `BASHTION_OPENAI_MODEL` | Model name sent to the endpoint | `gpt-4o` |
86+
87+
Example:
88+
```bash
89+
BASHTION_OPENAI_BASE_URL=http://localhost:8080/v1 \
90+
BASHTION_OPENAI_API_KEY=dev-secret \
91+
BASHTION_OPENAI_MODEL=local-mixtral \
92+
curl https://example.com/install.sh | bashtion
93+
```
94+
95+
## 🧪 Manual Test Scripts
96+
97+
Use the bundled scripts to validate detections:
98+
99+
```bash
100+
# Triggers the eval static rule
101+
cat scripts/manual/static_eval.sh | bashtion --no-exec
102+
103+
# Shows curl|bash caution
104+
cat scripts/manual/static_curl_pipe.sh | bashtion --no-exec
105+
106+
# Benign download (AI low risk)
107+
cat scripts/manual/semantic_download.sh | bashtion --no-exec
108+
109+
# Reverse shell (AI + static high risk)
110+
cat scripts/manual/semantic_reverse_shell.sh | bashtion --no-exec
111+
```
112+
113+
## 🤖 AI Backend
114+
115+
- Bashtion sends the captured script to `POST {base_url}/chat/completions` with a structured-output prompt.
116+
- The model must respond with JSON: `{ "intent": ..., "risk": "low|medium|high", "findings": [...] }`.
117+
- Responses are retried up to 3 times with exponential backoff, and malformed JSON is auto-repaired with [`llm_json`](https://crates.io/crates/llm_json).
118+
- If no base URL is configured, AI analysis is skipped (only static findings are shown).
119+
120+
## 📦 Release Artifacts
121+
122+
`install.sh` and the GitHub release workflow publish four archives:
123+
124+
- `bashtion-linux-x86_64.tar.gz`
125+
- `bashtion-linux-aarch64.tar.gz`
126+
- `bashtion-macos-x86_64.tar.gz`
127+
- `bashtion-macos-aarch64.tar.gz`
128+
129+
Each contains a single `bashtion` binary. SHA256 files are provided for integrity checks.
130+
131+
## 📄 License
132+
133+
Bashtion is MIT-licensed. See [LICENSE](LICENSE) for details.
134+
135+
## 🙏 Acknowledgments
136+
137+
Inspired by projects like Nomnom and LIGMA that focus on safe, AI-friendly tooling for developers.

0 commit comments

Comments
 (0)