Skip to content

Conalh/Skunky

Repository files navigation

Skunky - a defiant cartoon skunk in red, black, and white

Skunky

Local-first compartmentalized LLM work.
Hand bounded, sanitized work to untrusted LLM workers without handing them your secrets.

CI License: MIT Python 3.11+

Quick start | Beginner tutorial | Commands | Trust caveats | Architecture | Security


Skunky is a local-first compartmentalized LLM work system. It gives an operator a private broker workspace for handing bounded, sanitized work to untrusted LLM workers without exposing the project, identifiers, local paths, or raw files behind that work.

Skunky is built around one practical rule:

Sanitized packets go out. Hostile artifacts come back. Every disclosure gets checked, logged, and budgeted.

What It Protects

Risk Skunky control
A worker sees raw project files Sources are parsed locally, encrypted, sanitized, and served only through packet-local handles.
A prompt injection in a source file becomes instructions Source content crosses a subprocess parse boundary and is treated as data, not commands.
Real names, paths, URLs, or internal terms leak into packets Sanitizers and validators scan worker-visible surfaces before use.
A handle gets reused or shared too broadly Broker reads use packet-local, single-use, expiring handles.
Worker output smuggles active content or secrets back in Submitted artifacts are treated as hostile data and scanned before sealing or quarantine.
"One small release" becomes cumulative disclosure Releases are scored against a disclosure ledger and per-audience budgets.
Local records are edited after the fact Audit logs are hash-chained, Ed25519-signed, and replayed by skunky verify.

Start Here

If you want to... Start with...
Try Skunky for the first time Quick Start
Onboard real project data Beginner tutorial
Understand the security model Threat Model and Architecture
Check every CLI command Commands
Review known limitations Trust Caveats

Threat Model

Skunky assumes the worker is hostile. A worker may be an LLM, script, model tool, or any untrusted process that tries to exfiltrate identifiers, obey instructions hidden in source content, or return unsafe artifacts.

Skunky trusts the operator boundary: the local machine, the skunky.local/ workspace, and the local keystore. Its job is to keep worker-visible material bounded and sanitized, fail closed when checks do not pass, and leave a verifiable record of what crossed the boundary.

For the complete model, see IMPLEMENTATION_SPEC.md and docs/ARCHITECTURE.md.

Installation

Requires Python 3.11+.

pip install -e .          # from a clone
pip install -e .[dev]     # with test dependencies

Quick Start

For a local demo workspace:

skunky init
skunky mission create --name "Local demo"
skunky status

For real project data, start with a passphrase-wrapped keystore:

export SKUNKY_KEYSTORE_PASSPHRASE="replace-this-with-5-plus-random-words"
skunky init --wrap-keystore

On Windows PowerShell:

$env:SKUNKY_KEYSTORE_PASSPHRASE = "replace-this-with-5-plus-random-words"
skunky init --wrap-keystore

Do not copy the placeholder passphrase above. Skunky rejects short passphrases, obvious placeholders, and common weak values.

The typical workflow is:

  1. Create a mission and compartment.
  2. Add sensitive terms to the gazetteer.
  3. Add one source file.
  4. Create a worker packet.
  5. Let the worker read only assigned handles.
  6. Submit worker output as an artifact.
  7. Request and approve only reviewed releases.
  8. Run skunky verify.

For a command-by-command walkthrough with PowerShell examples, use docs/BEGINNER_TUTORIAL.md.

Commands

Workspace

Command Purpose
skunky init Create the labeled skunky.local/ workspace.
skunky init --wrap-keystore Create a workspace with a passphrase-wrapped local keystore.
skunky status Show workspace summary.
skunky keys wrap Passphrase-wrap an existing plaintext local keystore.
skunky keys rotate Install a new root key and re-encrypt every local artifact.
skunky verify Run deterministic acceptance gates and write reports under skunky.local/ci/reports/.

Onboarding

Command Purpose
skunky mission create Create a broker-private mission record.
skunky compartment create Create a broker-private compartment.
skunky gazetteer add Store a keyed HMAC fingerprint for a sensitive term; plaintext is never stored.
skunky source add Encrypt a raw source, sanitize it, and write a sanitization manifest.

Worker Exchange

Command Purpose
skunky packet create Emit a worker-visible packet plus broker-private handle map and policy.
skunky packet validate Re-validate an existing packet against schema, scanners, and forbidden terms.
skunky broker read Resolve a packet-local single-use handle through policy and serve sanitized content.
skunky artifact submit Ingest worker output as hostile data into encrypted storage.

Release

Command Purpose
skunky release request Create a declassification request.
skunky release approve Approve a reviewed request and update the disclosure ledger.
skunky release ledger Show a decrypted ledger summary for the operator.

Enforced Controls

Control What it does
Parser boundary Parses source files in a subprocess before anything is persisted.
Deterministic sanitization Uses gazetteer HMAC matching, regex scanners, and residual-risk stages, then re-scans sanitized output.
Single-use handles Binds worker reads to one packet, one run, and one successful claim.
Fail-closed broker reads Denies reads when a sanitized blob is missing, corrupt, expired, or unauthorized.
Disclosure ledger Scores releases by granularity, timing precision, and linkage risk against per-audience budgets.
Audit replay Replays hash chains, Ed25519 signatures, handle maps, policies, manifests, and ledger anchors.
Root-key rotation Keeps retired root keys decrypt-only until all encrypted artifacts are rewritten.

Trust Caveats

The MVP uses a local file keystore under skunky.local/keystore_refs/. Plaintext key manifest mode is development-only. Do not use plaintext manifest mode for real project data.

The only shipped keystore backend today is the local-file backend. OS keyring or hardware-backed storage should be added later as optional backends, not as half-wired dependencies in the current MVP.

Passphrase wrapping helps with:

  • A copied key manifest alone is not enough to unlock the workspace.
  • Existing plaintext workspaces can be migrated with skunky keys wrap.
  • Skunky rejects short passphrases, obvious placeholders, and common weak values before wrapping or unlocking a keystore.

Passphrase wrapping does not solve:

  • A weak or stolen passphrase.
  • A process that is already unlocked.
  • Broad local machine compromise.
  • OS keyring or hardware-backed storage. Those are roadmap backends, not implemented dependencies yet.

Never copy skunky.local/ into worker packets, provider prompts, logs, or shared artifacts, and never commit it to version control. The shipped .gitignore excludes it for this repo.

See SECURITY.md for the full list of limitations and how to report vulnerabilities.

Documentation

License

MIT


Built local-first. Fails closed. Keeps receipts.

About

No description, website, or topics provided.

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages