Pipeline Sentinel
July 31, 2025 ยท View on GitHub
A lightweight, eBPF-powered security monitor for CI/CD build pipelines.
Pipeline Sentinel provides real-time visibility into the build phase of CI/CD pipelines, detecting and blocking suspicious process executions to protect against supply chain attacks.
The Problem: The CI/CD Blind Spot
Modern CI/CD pipelines are a prime target for attackers. The build step often pulls and executes code from dozens of third-party dependencies, creating a significant but often unmonitored attack surface. Malicious packages or compromised build tools can execute arbitrary commands inside your trusted environment to steal secrets, inject backdoors, or pivot to other internal systems.
Traditional security tools like SAST and artifact scanning analyze your code before or after the build, leaving the build phase itself a critical blind spot.
The Solution: Real-time Behavioral Monitoring
Pipeline Sentinel addresses this gap by monitoring the build environment in real-time. It uses modern kernel technology to watch every process as it's created, matching its behavior against a flexible rule set to identify threats.
Key Features
- Kernel-Level Visibility via eBPF: Uses eBPF to safely and efficiently monitor all new process executions (
execvesyscall) with near-zero performance overhead. - Intelligent Analysis in Go: A high-performance Go agent enriches kernel events with full command-line arguments and applies custom detection logic.
- Flexible YAML Rule Engine: Detections are driven by a simple
rules.yamlfile, allowing users to easily define suspicious patterns, from single commands to complex, multi-part command strings. - CI/CD Integration: Fully containerized with Docker and designed to run as a service container in pipelines like GitHub Actions, with the ability to automatically fail a build when a critical threat is found.
Architecture
The tool is composed of two main components:
- eBPF Probe (C): A minimal, safe program that runs in the Linux kernel to capture process events.
- User-space Agent (Go): A concurrent Go application that receives events from the kernel, reads the full command line from
/proc, matches events against the rule set, and generates alerts.
flowchart LR
subgraph subGraph0["Docker Container"]
direction TB
C["Start Pipeline Sentinel"]
D[/"rules.yaml"/]
E["Execute Build Command"]
F{"Process Spawned?"}
G["Analyze Process Against Rule Set"]
H{"Violation?"}
I{"Critical Issue?"}
L["Log Violation & Add to Report"]
J["Allow Process"]
K["Block Process & Fail Build"]
end
C -- Loads --> D
C --> E
E -- Triggers --> F
F -- Yes --> G
F -- No ----> E
G --> H
H -- No --> J
J -- Build Continues --> E
H -- Yes --> I
I -- Yes --> K
I -- No --> L
L -- then --> J
Getting Started
Prerequisites
- Go (1.23+)
- Docker
- clang, llvm, libbpf-dev, make, bpftool
Local Build & Run
- Build the application:
make build - Build the Docker image:
docker build -t pipeline-sentinel-app . - Run the container: This command runs the sentinel and mounts your local rules.yaml and a reports directory into the container.
# Create the reports directory first
mkdir -p reports
# Run the container
sudo docker run -it --rm \
--name sentinel-container \
--cap-add=SYS_ADMIN \
--pid=host \
-v /sys/kernel/debug:/sys/kernel/debug:ro \
-v ${PWD}/rules.yaml:/app/rules.yaml:ro \
-v ${PWD}/reports:/app/reports \
pipeline-sentinel-app
Configuration (rules.yaml)
The detection logic is controlled by the rules.yaml file. The engine uses "smart" matching based on the number of items in the match_all list.
- Single-Item List: Triggers a precise "whole word" match. Ideal for single commands.
- Multi-Item List: Triggers a "contains all substrings" match. Ideal for complex patterns.
# rules.yaml
# This rule uses "whole word" matching and will trigger on 'whoami'
# but not on commands that simply contain the substring 'whoami'.
- id: recon_whoami
description: "Detects 'whoami' used for user discovery"
severity: "medium"
match_all:
- "whoami"
# This rule uses "contains all" matching and will trigger on any
# command that contains "curl", "|", and "bash".
- id: curl_remote_script_execution
description: "Detects downloading a remote script and executing it with a shell"
severity: "critical"
match_all:
- "curl"
- "|"
- "bash"
Usage in GitHub Actions
Pipeline Sentinel is designed to run as a service container in a CI/CD pipeline. The following is a two-job workflow that builds the tool and then uses it to monitor a test script.
Place this file in '''.github/workflows/sentinel-test.yml''':
name: Pipeline Sentinel CI
on: [push]
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Check out repository
uses: actions/checkout@v4
- name: Log in to the GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Docker image
run: |
IMAGE_ID=ghcr.io/${{ github.repository }}:${{ github.sha }}
docker build -t $IMAGE_ID .
docker push $IMAGE_ID
test-with-sentinel:
needs: build
runs-on: ubuntu-latest
services:
sentinel:
id: sentinel
image: ghcr.io/${{ github.repository }}:${{ github.sha }}
credentials:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
options: >-
--pid=host
--cap-add=SYS_ADMIN
-v /sys/kernel/debug:/sys/kernel/debug:ro
steps:
- name: Check out repository
uses: actions/checkout@v4
- name: Run Fake Build Script for Testing
run: |
chmod +x ./fake_build_script.sh
./fake_build_script.sh || true
- name: Check Sentinel Logs and Finalize
if: always()
run: |
echo "--- Final Sentinel Logs ---"
docker logs sentinel > sentinel-log.txt 2>&1
cat sentinel-log.txt
echo "--- Checking for Critical Alerts ---"
if grep -q "CRITICAL" sentinel-log.txt; then
echo "Build FAILED due to critical alert found in logs."
exit 1
else
echo "Build successful. No critical alerts found."
fi
- name: Upload Sentinel Log as Artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: sentinel-log-report
path: sentinel-log.txt
Future Work
- Output alerts in structured JSON format for easier machine parsing.
- Expand eBPF probes to monitor other syscalls (e.g., connect for network, open for files).
- Enhance the rule engine to support more advanced context (e.g., parent process matching).
- Add a main configuration file for the tool itself.
Contributing
Contributions are welcome! Please feel free to open an issue or submit a pull request.
License
This project is licensed under the MIT License.