Detecting Compromised CLI Tools in Ci/cd Pipelines

Practical steps to detect and mitigate compromised CLI tools like Bitwarden in production pipelines using integrity checks.

JR

3 minute read

Practical steps to detect and mitigate compromised CLI tools like Bitwarden in production pipelines using integrity checks, audit trails, and access controls.

Diagnosis: What to Monitor

  1. Unexpected network activity:

    • Monitor for outbound connections from CI/CD runners to unknown IPs/domains.
    • Use tools like tcpdump, netstat, or cloud network monitoring (e.g., AWS VPC Flow Logs).
    • Example: kubectl exec -it <runner-pod> -- tcpdump -i eth0 host <suspicious-ip>
  2. Artifact integrity anomalies:

    • Check for unexpected changes in pipeline output (e.g., binaries with mismatched hashes).
    • Validate artifacts against pre-signed hashes:
      sha256sum <artifact> | diff - <expected-hash>  
      
  3. Audit logs:

    • Enable detailed logging for CLI tool execution (e.g., BW CLI --log-level debug).
    • Use centralized logging (e.g., Elasticsearch, Loki) to flag suspicious commands like bw export.
  4. Runtime behavior:

    • Deploy runtime security tools (e.g., Falco, Tracee) to detect shell spawns or credential accesses:
      # Falco rule snippet  
      - rule: Unexpected CLI Activity  
        desc: Detect unauthorized CLI tool usage  
        condition: container.id exists and proc.name = "bw"  
        output: "Unauthorized CLI tool execution (user=%user.name)"  
      

Repair: Immediate Actions

  1. Isolate affected systems:

    • Cordon Kubernetes nodes or pause CI/CD runners:
      kubectl cordon <node>  
      
  2. Revoke compromised credentials:

    • Rotate Bitwarden API keys and service account tokens.
    • Example for Kubernetes secrets:
      kubectl delete secret bitwarden-cli-secret  
      kubectl create secret generic bitwarden-cli-secret --from-literal=API_KEY=<new-key>  
      
  3. Scan for persistence:

    • Search for backdoors in runner images or pipelines:
      docker inspect <runner-image> | grep -i "backdoor"  
      

Prevention: Policy and Hardening

  1. Enforce image provenance:

    • Require signed images in CI/CD pipelines using Notary or cosign:
      cosign verify --key cosign.pub <runner-image>  
      
  2. Restrict CLI tool permissions:

    • Use least-privilege service accounts (e.g., OpenShift’s serviceaccount with minimal roles).
    • Example policy (Kyverno):
      apiVersion: kyverno.io/v1  
      kind: ClusterPolicy  
      metadata:  
        name: restrict-cli-tools  
      spec:  
        validationFailureAction: enforce  
        rules:  
          - name: check-cli-permissions  
            match:  
              resources:  
                kinds: ["Pod"]  
            validate:  
              pattern:  
                spec:  
                  containers:  
                    - name: "*-runner"  
                      securityContext:  
                        runAsNonRoot: true  
                        allowPrivilegeEscalation: false  
      
  3. Runtime protection:

    • Use read-only volumes for CLI tools to prevent tampering:
      volumes:  
        - name: bitwarden-data  
          emptyDir: {}  
      containers:  
        - name: bitwarden-cli  
          volumeMounts:  
            - name: bitwarden-data  
              mountPath: /data  
              readOnly: true  
      

Tooling

  • Detection: Falco, Osquery, Sysdig Secure
  • Prevention: Kyverno, OPA Gatekeeper, Notary
  • Audit: Loki, Grafana, Auditd

Tradeoffs

  • False positives: Overly strict policies may block legitimate workflows (e.g., image signing failures during emergencies).
  • Overhead: Runtime monitoring adds latency; balance with pipeline performance requirements.

Troubleshooting

  • Missing logs: Ensure logging agents (e.g., Fluentd) are running and have sufficient permissions.
  • Permission denied: Validate service accounts have logs and nodes access in Kubernetes RBAC.
  • False negatives: Update detection rules regularly to cover new attack vectors (e.g., novel CLI command patterns).

Validation

  • Test detection rules with known bad behavior:
    # Simulate a compromise  
    kubectl exec -it <runner-pod> -- bw export --format json > /tmp/creds.json  
    # Verify alert in Falco/monitoring  
    
  • Validate policy enforcement by deploying non-compliant pods and confirming denials.

Source thread: bitwarden CLI was compromised for ~90 min. what in your pipeline would detect that?

comments powered by Disqus