A tiny Flask app for unpacking, editing, and rebuilding Cribl pack files (.crbl).
Drop a .crbl in the browser, replace any changeme placeholders via a form, rename the pack, and download a clean rebuilt archive — no macOS metadata (._*, .DS_Store, __MACOSX), no stray .git artifacts, no shell quoting headaches.
When you build a REST collector in Cribl and try to export it to another environment — or package it up for the Dispensary — certain header values get redacted on export even though they aren't actually sensitive. Things like Content-Type: application/json or Accept: application/json come back out the other side as changeme, and you have to hand-edit them back in before the pack will work.
Doing that by hand means unpacking the .crbl (a gzipped tarball), finding every changeme across default/, fixing each one with the right quoting, then repacking it — without dragging in macOS metadata (._*, .DS_Store, __MACOSX) or stray .git files that packs.cribl.io will reject.
A standalone Flask app: drop a .crbl in the browser, rename the pack, fill in real values for every changeme the app found, and download a clean rebuilt archive. No more remembering the tar/gzip syntax to unpackage and repackage, no more shell-quoting headaches for values that contain single quotes or backticks.
- Python 3.9+
- Flask 3+
cd crbl-repacker
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt.venv/bin/python app.pyThen open http://127.0.0.1:5050.
-
Upload — drag a
.crblonto the drop zone. The server extracts it into a per-session temp directory under$TMPDIR/crbl-repacker/<uuid>/pack. If the archive had a single top-level directory, it's flattened so the pack root is at the top level. -
Detect — the app reads
package.jsonto pre-fill the pack name, then walksdefault/looking for every line containingchangeme. Each match is shown with its file path, line number, and the line above it for context. -
Edit — known keys (
clientSecretParamValue,username,password) are pre-filled with Cribl's standard placeholder syntax. Anything else is left blank for you to fill in.Key Default clientSecretParamValue< Enter Secret | Enter Secret >username< Enter Username | Enter Username >password< Enter Password | Enter Password > -
Rebuild — submit the form. The app rewrites each
changemeline (preserving leading whitespace and any prefix beforechangeme), then tars the pack with gzip compression, excluding:*.crbl.DS_Store.git,.gitignore._*(macOS resource forks)__MACOSX/
The rebuilt
.crblis streamed back as a download named<pack_name>.crbl.
crbl-repacker/
├── app.py # Flask app — upload, extract, scan, rebuild
├── requirements.txt
└── templates/
├── index.html # Drop-zone upload page
└── edit.html # Form with detected changeme fields
- Each upload gets a fresh session UUID under the system temp dir. Sessions are not cleaned up automatically — the OS will reclaim them on the normal
/tmpcycle. - Max upload size is 200 MB (
MAX_CONTENT_LENGTHinapp.py). - Extraction uses tarfile's
datafilter on Python 3.12+ to block path-traversal in malicious archives. - The server listens on
127.0.0.1:5050only. Do not expose it publicly — it runs Flask's dev server and does no auth.



