CI/CD Pipelines
Use shellfirm as a safety gate in continuous integration and deployment pipelines
shellfirm can act as a safety gate in CI/CD pipelines, checking commands before they execute in production environments. Use shellfirm check to validate commands programmatically with clear exit codes.
Exit codes
| Exit code | Meaning |
|---|---|
0 | Command is safe (no patterns matched, or all matches below threshold) |
1 | Command is risky (matches detected at or above threshold) |
Basic usage
shellfirm check --command "kubectl delete namespace production" --test
echo $? # 1 (risky)
shellfirm check --command "kubectl get pods" --test
echo $? # 0 (safe)
The --test flag suppresses interactive prompts and returns only the exit code, which is what you want in CI environments.
For structured output, use --json:
shellfirm check --command "rm -rf /" --json
This returns a JSON risk assessment identical to what the MCP server produces.
GitHub Actions
Pre-deploy safety check
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install shellfirm
run: |
curl -L https://github.com/kaplanelad/shellfirm/releases/latest/download/shellfirm-x86_64-unknown-linux-gnu.tar.gz | tar xz
sudo mv shellfirm /usr/local/bin/
- name: Validate deployment command
run: |
DEPLOY_CMD="kubectl apply -f k8s/production/"
shellfirm check --command "$DEPLOY_CMD" --test
if [ $? -ne 0 ]; then
echo "::error::shellfirm blocked the deployment command"
exit 1
fi
- name: Deploy
run: kubectl apply -f k8s/production/
Check multiple commands
- name: Safety check all deployment commands
run: |
set -e
shellfirm check --command "helm upgrade --install app ./chart --set env=production" --test
shellfirm check --command "kubectl rollout restart deployment/web -n production" --test
Block dangerous flags
- name: Block dangerous git operations
run: |
# Fail the pipeline if any script uses --force or --no-verify
for cmd in \
"git push --force origin main" \
"git push --no-verify" \
"npm publish --force"
do
if ! shellfirm check --command "$cmd" --test; then
echo "::error::Blocked dangerous command: $cmd"
exit 1
fi
done
GitLab CI
deploy:
stage: deploy
before_script:
- curl -L https://github.com/kaplanelad/shellfirm/releases/latest/download/shellfirm-x86_64-unknown-linux-gnu.tar.gz | tar xz
- mv shellfirm /usr/local/bin/
script:
- shellfirm check --command "kubectl apply -f k8s/" --test
- kubectl apply -f k8s/
environment:
name: production
Custom pipeline scripts
For any CI system, the pattern is the same:
#!/bin/bash
set -e
COMMAND="$1"
# Check with shellfirm
if ! shellfirm check --command "$COMMAND" --test; then
echo "ERROR: shellfirm blocked command: $COMMAND"
echo "Run 'shellfirm check --command \"$COMMAND\" --json' for details"
exit 1
fi
# Command is safe, execute it
eval "$COMMAND"
Using JSON output for detailed reporting
In pipelines where you want detailed reporting, use --json:
RESULT=$(shellfirm check --command "$DEPLOY_CMD" --json)
ALLOWED=$(echo "$RESULT" | jq -r '.allowed')
SEVERITY=$(echo "$RESULT" | jq -r '.severity // "none"')
if [ "$ALLOWED" = "false" ]; then
echo "Command blocked by shellfirm"
echo "Severity: $SEVERITY"
echo "$RESULT" | jq '.matched_rules[] | "\(.id): \(.description)"'
exit 1
fi
Environment-specific configuration
CI environments often have different shellfirm configurations than developer machines. Set environment-specific settings:
# In CI, use stricter settings
export SHELLFIRM_CONFIG_PATH=/path/to/ci-settings.yaml
Or use project policies by including a .shellfirm.yaml in your repository root. The CI pipeline will automatically pick it up when running from the repository directory.