Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
5fdbba0
feat: add pattern matching for sensitive keys, emails, home paths
bakerboy448 Feb 28, 2026
aa2a958
feat: implement core compose redaction logic
bakerboy448 Feb 28, 2026
2373efb
feat: add noise stripping for generated compose output
bakerboy448 Feb 28, 2026
e0057a7
feat: detect media volume mounts and show hardlinks advisory
bakerboy448 Feb 28, 2026
02f0bcd
feat: extract YAML from pasted console output
bakerboy448 Feb 28, 2026
cd77909
feat: configurable redaction patterns with localStorage persistence
bakerboy448 Feb 28, 2026
2fc52a2
feat: strip autocompose noise — default fields, internal env vars, em…
bakerboy448 Feb 28, 2026
cd58419
feat: clipboard copy and paste service redirect
bakerboy448 Feb 28, 2026
2f4e57c
feat: assemble UI with sanitize pipeline, settings, and disclaimers
bakerboy448 Feb 28, 2026
fee28f1
ci: auto pre-release on main push, manual stable release
bakerboy448 Feb 28, 2026
8d604f1
chore: add Renovate, CodeRabbit config, branch protection
bakerboy448 Feb 28, 2026
5607c4d
chore: add issue and PR templates
bakerboy448 Feb 28, 2026
b60241a
chore: optimize issue templates for compose sanitizer domain
bakerboy448 Feb 28, 2026
6a448b9
fix: thread custom config through sanitize pipeline
bakerboy448 Feb 28, 2026
115b817
refactor: deduplicate isRecord into patterns.ts, add long-form volume…
bakerboy448 Feb 28, 2026
c05ebaa
fix: handle invalid regex in compileConfig, harden CSP
bakerboy448 Feb 28, 2026
1f9dfd6
docs: improve README with features, architecture, and privacy sections
bakerboy448 Feb 28, 2026
dff1ce1
fix: allow inline scripts in CSP for singlefile build, add input size…
bakerboy448 Feb 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .coderabbit.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
language: en-US
reviews:
profile: assertive
request_changes_workflow: true
high_level_summary: true
poem: false
review_status: true
collapse_walkthrough: false
path_instructions:
- path: "src/**"
instructions: |
Review for XSS vulnerabilities — never use innerHTML, always textContent.
Check for immutability violations — never mutate input objects.
Verify regex patterns are not susceptible to ReDoS.
- path: "tests/**"
instructions: |
Verify tests cover edge cases and error paths.
Check test isolation — no shared mutable state.
- path: ".github/workflows/**"
instructions: |
Check for command injection via untrusted GitHub context variables.
Verify secrets are not exposed in logs.
chat:
auto_reply: true
64 changes: 64 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
name: Bug Report
description: Report a bug in the compose sanitizer
labels: [bug]
body:
- type: markdown
attributes:
value: |
**This tracker is for bugs only.** Not for general Docker/compose support.
- type: dropdown
id: category
attributes:
label: Category
options:
- Redaction (sensitive value not caught or safe value wrongly redacted)
- Noise stripping (field not removed or wrong field removed)
- Advisory (false positive or missed detection)
- Input extraction (YAML not parsed from pasted output)
- UI / display issue
- Build / deployment
- Other
validations:
required: true
- type: textarea
id: description
attributes:
label: Description
description: What happened?
validations:
required: true
- type: textarea
id: expected
attributes:
label: Expected behavior
description: What should have happened?
validations:
required: true
- type: dropdown
id: input-type
attributes:
label: Input type
options:
- docker-autocompose output
- docker compose config output
- Raw docker-compose.yml
- Other
validations:
required: true
- type: textarea
id: input
attributes:
label: Input YAML (sanitized)
description: Paste a minimal example that reproduces the issue. Redact any real secrets first.
render: yaml
- type: textarea
id: output
attributes:
label: Actual output
description: What the sanitizer produced
render: yaml
- type: input
id: browser
attributes:
label: Browser
description: e.g., Chrome 120, Firefox 121, Safari 17
2 changes: 2 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
blank_issues_enabled: false
contact_links: []
36 changes: 36 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Feature Request
description: Suggest an improvement to the compose sanitizer
labels: [enhancement]
body:
- type: markdown
attributes:
value: |
**This tracker is for feature requests only.** Not for general Docker/compose support.
- type: dropdown
id: category
attributes:
label: Category
options:
- New redaction pattern (detect additional sensitive values)
- New noise filter (strip additional generated fields)
- New advisory (detect additional misconfigurations)
- Input format support (new input types)
- Output / sharing (clipboard, export options)
- UI / UX improvement
- Other
validations:
required: true
- type: textarea
id: description
attributes:
label: Description
description: What would you like to see added or changed?
validations:
required: true
- type: textarea
id: use-case
attributes:
label: Use case
description: Why is this needed? Include example YAML if relevant.
validations:
required: true
15 changes: 15 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
## Summary

<!-- Brief description of changes -->

## Changes

<!-- Bullet list of what changed -->

## Test plan

<!-- How to verify this works -->

- [ ] Tests pass (`npm test`)
- [ ] TypeScript compiles (`npx tsc --noEmit`)
- [ ] Build succeeds (`npm run build`)
59 changes: 59 additions & 0 deletions .github/workflows/prerelease.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: Pre-release

on:
push:
branches: [main]

permissions:
contents: write

jobs:
prerelease:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm

- name: Get current version
id: version
run: |
VERSION=$(node -p "require('./package.json').version")
echo "version=$VERSION" >> "$GITHUB_OUTPUT"

- name: Get next pre-release number
id: prerelease
env:
BASE_VERSION: ${{ steps.version.outputs.version }}
run: |
LATEST=$(git tag -l "v${BASE_VERSION}-pre.*" --sort=-version:refname | head -n1)
if [ -z "$LATEST" ]; then
NUM=1
else
NUM=$(echo "$LATEST" | sed "s/v${BASE_VERSION}-pre\.\([0-9]*\)/\1/")
NUM=$((NUM + 1))
fi
TAG="v${BASE_VERSION}-pre.${NUM}"
echo "tag=$TAG" >> "$GITHUB_OUTPUT"

- run: npm ci
- run: npm run build
- run: cp dist/index.html compose-sanitizer.html

- name: Create pre-release tag
env:
TAG: ${{ steps.prerelease.outputs.tag }}
run: |
git tag "$TAG"
git push origin "$TAG"

- uses: softprops/action-gh-release@v2
with:
tag_name: ${{ steps.prerelease.outputs.tag }}
files: compose-sanitizer.html
generate_release_notes: true
prerelease: true
1 change: 1 addition & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ jobs:
with:
files: compose-sanitizer.html
generate_release_notes: true
prerelease: ${{ contains(github.ref, '-') }}
69 changes: 69 additions & 0 deletions .github/workflows/stable-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
name: Stable Release

on:
workflow_dispatch:
inputs:
version:
description: 'Release version (e.g., 0.2.0). Will be tagged as v0.2.0'
required: true
type: string

permissions:
contents: write

jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm

- name: Validate version format
env:
VERSION: ${{ inputs.version }}
run: |
if ! echo "$VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+$'; then
echo "::error::Invalid version format. Use semver (e.g., 1.2.3)"
exit 1
fi

- name: Check tag does not exist
env:
VERSION: ${{ inputs.version }}
run: |
if git rev-parse "v${VERSION}" >/dev/null 2>&1; then
echo "::error::Tag v${VERSION} already exists"
exit 1
fi

- name: Update package.json version
env:
VERSION: ${{ inputs.version }}
run: npm version "$VERSION" --no-git-tag-version

- run: npm ci
- run: npx tsc --noEmit
- run: npx vitest run --passWithNoTests
- run: npm run build
- run: cp dist/index.html compose-sanitizer.html

- name: Commit version bump and tag
env:
VERSION: ${{ inputs.version }}
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add package.json package-lock.json
git commit -m "chore: release v${VERSION}"
git tag "v${VERSION}"
git push origin main --follow-tags

- uses: softprops/action-gh-release@v2
with:
tag_name: v${{ inputs.version }}
files: compose-sanitizer.html
generate_release_notes: true
prerelease: false
87 changes: 74 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,93 @@ Browser-based tool that redacts sensitive values from Docker Compose YAML while

**Live:** [bakerboy448.github.io/compose-sanitizer](https://bakerboy448.github.io/compose-sanitizer/)

## What Gets Redacted
## Features

- **Sensitive env var values** matching password, secret, token, api_key, auth, credential patterns
- **Email addresses** detected in any value
- **Home directory paths** in volume mounts (`/home/user/...` becomes `~/...`)
### Redaction

## What Gets Kept
| What | Example | Result |
|------|---------|--------|
| Sensitive env values | `MYSQL_PASSWORD: supersecret` | `MYSQL_PASSWORD: **REDACTED**` |
| Email addresses | `NOTIFY: user@example.com` | `NOTIFY: **REDACTED**` |
| Home directory paths | `/home/john/media:/tv` | `~/media:/tv` |

- Container names, images, labels, networks, ports
- Volume mounts (with anonymized home paths)
- Environment variable **names** (only values redacted)
- PUID, PGID, TZ, UMASK values (explicitly safelisted)
Detected patterns: `password`, `secret`, `token`, `api_key`, `auth`, `credential`, `private_key`, `vpn_user`, and more.

Safe-listed keys (kept as-is): `PUID`, `PGID`, `TZ`, `UMASK`, `LOG_LEVEL`, `WEBUI_PORT`, etc.

### Noise Stripping

Removes auto-generated fields that clutter compose output:

- `com.docker.compose.*` labels
- S6-overlay env vars (`S6_*`)
- Default runtime values (`ipc: private`, `entrypoint: /init`)
- Locale/path env vars (`PATH`, `LANG`, `XDG_*`)
- Empty maps and arrays

### Advisories

Detects common misconfigurations and shows warnings with links to documentation:

- **Hardlinks advisory**: Warns when separate `/tv`, `/movies`, etc. mounts prevent hardlinks and instant moves

### Input Handling

Accepts multiple input formats:

- Raw `docker-compose.yml` content
- Output from `docker compose config`
- Output from [`docker-autocompose`](https://github.com/Red5d/docker-autocompose) (strips shell prompts and non-YAML lines)

### Customizable Patterns

The Settings panel allows custom sensitive patterns (regex) and safe key lists. Configuration persists in `localStorage`.

## Self-Hosting

Download `compose-sanitizer.html` from the [latest release](https://github.com/bakerboy448/compose-sanitizer/releases) and open it in any browser. Everything runs client-side — no server required.
Download `compose-sanitizer.html` from the [latest release](https://github.com/bakerboy448/compose-sanitizer/releases/latest) and open it in any browser. Everything runs client-side in a single HTML file — no server, no network requests, no data leaves your browser.

## Development

```bash
npm install
npm run dev # Start dev server
npm run test # Run tests
npm run build # Build single-file output
npm run dev # Start Vite dev server
npm test # Run tests (vitest)
npm run build # Build single-file dist/index.html
```

### Architecture

Single-page app built with Vite + vanilla TypeScript. The build produces one self-contained HTML file via `vite-plugin-singlefile`.

```
src/
patterns.ts # Shared type guards, regex patterns, utility functions
extract.ts # Extracts YAML from mixed console output
redact.ts # Redacts sensitive values, anonymizes paths
noise.ts # Strips auto-generated noise fields
advisories.ts # Detects misconfigurations (hardlinks, etc.)
config.ts # Customizable patterns, localStorage persistence
clipboard.ts # Copy, PrivateBin, and Gist sharing
disclaimer.ts # PII warnings and legal disclaimers
main.ts # UI assembly and event wiring
```

### Testing

104 tests across 7 test files with >93% statement coverage:

```bash
npm test # Run tests
npx vitest run --coverage # Run with coverage report
```

## Privacy

- All processing happens in your browser — no data is sent anywhere
- No analytics, tracking, or external requests
- The "Open PrivateBin" and "Open GitHub Gist" buttons copy to clipboard and open a new tab — you paste manually

## License

MIT
Loading