Most security teams do not get to choose how many build systems their organization runs. One business unit standardized on GitHub Actions years ago. An acquired team brought GitLab CI with it. The platform group still runs Jenkins for everything that touches infrastructure, and a regulated division never moved off Azure DevOps. Somewhere there is a Bamboo plan nobody wants to migrate and a Bitbucket Pipelines workspace that quietly ships production code. This is not a hypothetical. It is the normal state of a large engineering organization.
The problem is not that these tools exist. The problem is that each one speaks a different webhook dialect, signs its payloads differently, and reports build state in its own vocabulary. If you want a single security gate across all of them, you are usually told to build six integrations, maintain six verification routines, and reconcile six event formats by hand. That work never finishes, because every vendor ships breaking changes on its own schedule.
PMAP takes a different position. It treats GitHub, GitLab, Jenkins, Azure DevOps, Bamboo and Bitbucket as six entry points into one normalized event model and one security gate. This article walks through how that normalization works, how each vendor proves a webhook is authentic, and how the gate decides whether a pull request passes or fails. If you want the step-by-step setup for triggering scans from a pipeline, that lives in the operational guide on pipeline-triggered scanning. Here the focus is the vendor layer and the gate strategy that sits on top of it.
This piece is part of the broader security integration layer pillar, which covers how PMAP connects to scanners, ticketing systems and pipelines across categories.
Six Pipelines, Six Webhook Formats, One Problem
A CI/CD webhook is, on the surface, a simple thing. Something happens in a repository or a build, the vendor posts a JSON payload to a URL you configured, and your system reacts. The difficulty is that almost nothing about that contract is shared across vendors.
GitHub sends a push or pull_request event and signs the body with an HMAC header. GitLab sends a push, merge request or pipeline event and proves authenticity with a static token in a header. Jenkins, depending on plugin, posts a build-completed notification. Azure DevOps fires a service hook with a Bearer token. Bamboo and Bitbucket each have their own shape again. The branch name lives in a different field in every one. The commit SHA lives in a different field. The pull request identifier, when there is one, is named differently each time.
If you wire these up individually, you end up with six parallel code paths that all try to answer the same three questions. Is this webhook real. What branch and commit does it concern. What action, if any, should follow. Six answers to three questions is the root of the maintenance burden, and it is exactly the duplication PMAP collapses.
The downstream cost compounds. A security gate that only understands GitHub cannot block a risky merge request in GitLab. A scan trigger wired to Jenkins does nothing when an Azure DevOps pipeline runs the same code. Coverage becomes a function of which integration someone had time to finish, not of where your risk actually lives. The OWASP CI/CD Security Top 10 frames this as an insufficient flow control problem, and fragmented per-vendor wiring is one of the most common ways it shows up.
The Six CI/CD Vendors PMAP Normalizes
PMAP supports six CI/CD vendor types as first-class connectors. In the platform’s vendor catalog they appear under the CI/CD category as jenkins, github, gitlab, azure_devops, bamboo and bitbucket. That list is fixed and explicit. PMAP does not claim partial or experimental support for build systems outside it.
All six share one connector archetype. PMAP classifies them as AssetSourceConnector types, which means each one can enumerate repositories and pipelines and fan out CI events into the rest of the platform. This is the same archetype that lets PMAP read the structure of your source estate, so the CI/CD connectors do double duty. They are both the inbound webhook surface and the outbound enumeration surface for the repositories behind them.
Because the archetype is shared, the platform code that reacts to a CI event does not branch on vendor. Vendor packages self-register through an internal registry, and the orchestrator resolves the right connector by type without a hardcoded switch statement in the core. Adding behavior to the gate or the orchestrator therefore applies to all six vendors at once, rather than requiring six separate edits. That is the structural reason a single standard is maintainable rather than aspirational.
It is worth being precise about scope. PMAP normalizes the event and gate layer across these six. It does not pretend that GitHub and Jenkins are the same product. The credentials you store, the URLs you register, and the vendor-side configuration still differ per system. What is unified is everything downstream of the webhook arriving: the event shape, the security verification model, and the gate decision.
One CIEvent Model From Every Vendor
When any of the six vendors posts a webhook, PMAP receives it at a vendor-specific endpoint. The inbound CI receivers live under POST /webhooks/ci/{vendor}/{integrationId}, with a dedicated handler for each of GitHub, GitLab, Jenkins, Azure DevOps, Bamboo and Bitbucket. So far this looks like six separate doors. The important part is what happens immediately after the door.
Each receiver parses its vendor’s native payload and translates it into a single internal structure called a CIEvent. After that translation, the rest of PMAP no longer knows or cares which vendor sent the webhook. A GitHub push and a GitLab push become the same kind of object, carrying the same normalized fields: the event type, the repository, the branch, the commit, the pull request reference where one exists, and the action that was taken.
This normalization is the keystone of the whole design. Once an event is a CIEvent, every piece of logic that follows is written once. The branch filter is written once. The fan-out to scans is written once. The gate is written once. The audit log is written once. None of them carry vendor-specific conditionals, because the vendor differences were resolved at the receiver boundary and never travel further in.
The practical payoff is consistency you can rely on. A pull request opened in Bitbucket flows through the exact same gate logic as a merge request opened in GitLab, which flows through the same logic as a pull request in Azure DevOps. There is no second-class vendor, no integration that supports a subset of gate features. If PMAP can block a merge, it can block it everywhere, because the block is decided on the normalized event rather than on the raw payload.
Signed Webhooks: One Verification Standard Per Vendor
A webhook endpoint that accepts any POST is an open invitation. Anyone who learns the URL can forge build events, trigger scans, or attempt to manipulate a gate result. PMAP treats inbound CI webhook verification as a non-negotiable security control, and it implements the correct verification method for each vendor rather than settling for a lowest common denominator.
The phrase “one webhook standard” does not mean one cryptographic mechanism. It means one consistent expectation: every vendor must prove the webhook is authentic, using the strongest method that vendor offers, before PMAP acts on it. The standard is the guarantee, not the algorithm.
GitHub HMAC, GitLab Token, Azure Bearer and More
Each vendor gets the verification method that matches what it natively supports.
GitHub signs the raw request body and sends the result in an X-Hub-Signature-256 header, computed as HMAC-SHA256 over the payload using the shared secret. PMAP recomputes the signature on its side and compares. Because the signature covers the body, an attacker cannot tamper with the payload without invalidating the signature. This is the strongest of the available methods, and the deeper mechanics of HMAC verification get their own treatment in the HMAC webhook security article.
GitLab proves authenticity with the X-Gitlab-Token header, compared in constant time against the configured secret. Azure DevOps authenticates with a Bearer token, also compared in constant time. Jenkins, Bamboo and Bitbucket each present a token-style credential, an X-Api-Token, a UUID, or a Bitbucket signature, verified in constant time as well.
The constant-time comparison detail matters more than it looks. A naive string comparison can leak information about how many leading characters matched through timing differences, which is a known avenue for guessing a secret incrementally. By comparing in constant time, PMAP closes that side channel uniformly across the token-based vendors. The choice of method per vendor is pragmatic. The rigor applied to each method is not.
Rejecting Unsigned Hooks in Production
Verification is only as good as its enforcement. A common failure mode in CI security is a webhook receiver that verifies a signature when one is present but silently accepts the request when the secret was never configured. That turns the whole control into theater.
PMAP closes this gap with an explicit production posture. On a production instance, a missing secret causes every inbound hook for that integration to be rejected. There is no quiet pass-through. The only way to accept unsigned hooks is to deliberately set CI_WEBHOOK_ALLOW_UNSIGNED to true, which is an explicit, auditable decision a team has to make on purpose. Absent that flag, an integration without a configured secret does not process webhooks at all.
This default is the correct one for an enterprise. It means the safe configuration is the one you get by doing nothing special, and the unsafe configuration requires you to type out an opt-out whose name tells you exactly what you are giving up. Reviewers can grep for the flag. Auditors can ask why it is set. The control fails closed.
The Auto-Scan Orchestrator: From Event to Scan
A verified, normalized CIEvent is the input to the orchestrator. This is the component that decides what should happen now that a real event has arrived from a trusted pipeline.
The first decision is relevance. The orchestrator applies a branch filter, so events on branches you do not care about do not consume scan capacity or generate noise. A team that only wants to gate its main and release branches configures exactly that, and a push to a throwaway feature branch passes through without triggering downstream work.
For events that survive the filter, the orchestrator fans out. It can trigger pipeline-level scans, and it can fan out to the SAST and SCA integrations you have configured, so a code change can drive static analysis and dependency analysis automatically. This is how a single push or pull request becomes a coordinated security scan across the tools that matter for that codebase, without a human kicking off each one. The operational mechanics of wiring those triggers, including which scans to attach and how to configure targets, are covered in the dedicated pipeline-triggered scanning guide and in the wiring CI/CD pipelines for pipeline-triggered scans walkthrough. This article stays on the vendor and gate strategy rather than the click-by-click setup.
The orchestrator is deliberately written against the normalized event, not the vendor payload. That is why the same fan-out behavior applies whether the triggering event came from Jenkins or from GitHub. You configure the auto-scan behavior once, and it governs all six pipelines.
The Security Gate: Block on New Critical or High
The gate is where security policy meets the developer’s pull request. PMAP’s gate evaluates new findings against severity thresholds you define and turns that evaluation into a pass or fail signal the pipeline can act on.
The gate reads two severity lists from the integration’s auto-scan configuration: BlockOnNew and WarnOnNew. The distinction between them is the whole strategy in two settings. When a CI event produces new findings at a severity that appears in BlockOnNew, PMAP reports the commit check status as failure. When the new findings fall under the warn list instead, PMAP reports the status as pending. Block means stop. Warn means flag without stopping.
The word “new” is doing real work here. The gate is concerned with findings that this change introduced, not with the entire historical backlog of the repository. That distinction is what makes a gate usable. A gate that failed every pull request because the codebase already had open criticals would be turned off within a week. By gating on what is new, PMAP holds developers accountable for the risk their change adds, which is the behavior a shift-left program actually wants. The broader shift-left context, including how this fits a DevSecOps operating model, is covered in DevSecOps vulnerability management.
PR Comments and Commit Check Status
The gate decision reaches developers through two surfaces, and they serve different purposes.
The first is the commit check status. PMAP posts a status to the commit through POST /{id}/ci/pr-status, reporting pass, fail or pending with the threshold gate applied. This is the machine-readable signal. A branch protection rule on the vendor side can require that check to pass before a merge is allowed, which is how a failure status actually prevents risky code from landing rather than merely annotating it.
The second is the human-readable summary. PMAP posts a security-summary comment to the pull request or merge request through POST /{id}/ci/pr-comment. This is where the developer sees what was found and why their merge is blocked or flagged, in the place where they are already working. The status tells the pipeline what to do. The comment tells the person what happened. Together they make the gate both enforceable and explainable, which matters because a gate developers do not understand is a gate they will route around.
Always Emit a Runbook Trigger
There is a subtle but important guarantee in how PMAP handles every CI event, and it is easy to miss because it concerns the cases where auto-scan is off.
Regardless of whether auto-scan is enabled, and regardless of the branch filter outcome for scanning, the orchestrator always emits a runbook trigger event for the CI event. The scanning fan-out is conditional. The runbook signal is not.
This separation is valuable in practice. It means your automation layer always sees the pipeline activity, even when you have decided not to run scans on that event. A team can keep auto-scan narrowly scoped to a few branches while still driving notifications, custom workflows, or downstream automation from every relevant CI event through runbooks. The platform never makes scanning the only reason to care about a build, so you do not lose visibility just because you chose to be conservative about when scans fire.
Auditing Every CI Event
A gate you cannot inspect is a gate you cannot trust. When a developer asks why their merge was blocked, or a security reviewer asks whether a webhook was genuinely signed, you need a record.
PMAP keeps one. The CI event audit endpoint, GET /{id}/ci/events, returns the last 200 CI webhook events for an integration. Each entry records the event type, the repository, the branch, the commit, the pull request, the action that was taken, and crucially the signature validity. That last field is the one auditors care about most. It is a per-event answer to the question of whether the webhook proved itself authentic.
Two hundred events is a working window, not an archive. It is enough to investigate a recent incident, confirm that a vendor’s webhooks are arriving and verifying correctly after a configuration change, or spot a sudden run of invalid signatures that would indicate a misconfigured secret or a tampering attempt. The signature-validity column turns the audit log from a simple activity feed into a security control surface in its own right.
Choosing How Strict Your Gate Should Be
The gate gives you a spectrum, and where you sit on it is a real decision rather than a default you should accept blindly.
At the strict end, you put critical and high severities in BlockOnNew. New findings at those levels set the commit status to failure, and with branch protection in place, the merge cannot proceed until the issue is addressed or explicitly accepted. This is the right posture for a regulated codebase or a service where a new critical genuinely should not ship.
At the softer end, you put severities in WarnOnNew instead. New findings produce a pending status, which surfaces the risk on the pull request without hard-blocking the merge. This is appropriate when you are rolling a gate out for the first time and want developers to build the habit of reading security feedback before you start failing their builds. A common and sensible path is to start most severities in warn, watch the volume and the false-positive rate for a few weeks, then promote critical and high to block once the team trusts the signal.
The point is that the strictness is yours to set, per integration, and it can differ across your six pipelines if your risk profile differs. A new internal tool and a customer-facing payment service do not need the same gate. PMAP lets each integration carry its own block and warn lists so the policy matches the asset rather than forcing one global setting across an entire organization. For teams thinking about how this gate fits the day-to-day operational flow of pipeline scanning rather than vendor strategy, the pipeline-triggered scanning guide covers that operational angle.
How PMAP Unifies Six CI/CD Vendors
Pulling the threads together, the design rests on a small number of decisions that reinforce each other.
Six vendors enter through six receivers, and every receiver translates its native payload into one CIEvent. Every vendor proves authenticity through the strongest method it offers, and on a production instance a missing secret fails closed rather than passing through. The orchestrator reads the normalized event, applies a branch filter, fans out to scans where configured, and always emits a runbook trigger. The gate evaluates new findings against block and warn lists, reports a commit status the pipeline can enforce, and posts a human-readable summary to the pull request. Every event lands in an audit log that records, among other things, whether its signature was valid.
The result is a single security gate that behaves identically across GitHub, GitLab, Jenkins, Azure DevOps, Bamboo and Bitbucket, configured once and enforced everywhere. The vendor sprawl that usually fragments coverage becomes a non-issue, because the fragmentation is resolved at the receiver and never propagates into your policy. You stop maintaining six integrations and start maintaining one standard with six entry points.
If your organization runs more than one build system, that is the difference between security gating you can promise and security gating you can only hope for. To see where this CI/CD layer sits among PMAP’s scanner and ticketing integrations, start with the security integration layer pillar.
Frequently Asked Questions
Which CI/CD vendors does PMAP support?
PMAP supports six CI/CD vendors as first-class connectors: GitHub, GitLab, Jenkins, Azure DevOps, Bamboo and Bitbucket. All six share the AssetSourceConnector archetype, which means each can enumerate repositories and pipelines and fan out CI events into the platform. There is no partial-support tier. The gate and event logic apply equally to all six.
How does PMAP verify that a CI webhook is authentic?
Each vendor uses the strongest verification method it natively offers. GitHub uses an X-Hub-Signature-256 HMAC-SHA256 signature over the request body. GitLab uses the X-Gitlab-Token header. Azure DevOps uses a Bearer token. Jenkins, Bamboo and Bitbucket use a token-style credential. Token comparisons are done in constant time to avoid timing side channels. The deeper HMAC mechanics are covered in the dedicated HMAC webhook security article.
What happens if a webhook arrives without a configured secret?
On a production instance, a missing secret causes PMAP to reject every inbound hook for that integration. The receiver fails closed. The only way to accept unsigned hooks is to deliberately set the CI_WEBHOOK_ALLOW_UNSIGNED environment flag to true, which is an explicit and auditable decision rather than a silent default.
What is the difference between BlockOnNew and WarnOnNew?
These are two severity lists in the integration’s auto-scan configuration that decide how the gate reacts to new findings. When new findings appear at a severity in BlockOnNew, PMAP reports the commit check status as failure, which a branch protection rule can use to prevent a merge. When new findings fall under WarnOnNew, PMAP reports the status as pending, surfacing the risk without hard-blocking the merge. The gate evaluates findings introduced by the change, not the entire backlog.
Does PMAP normalize events from different CI/CD vendors?
Yes. Each vendor receiver translates its native webhook payload into a single internal CIEvent structure carrying a consistent set of fields: event type, repository, branch, commit, pull request reference and action taken. All downstream logic, including the branch filter, the scan fan-out, the gate and the audit log, runs against the normalized event, so behavior is identical across all six vendors.
Can I run scans automatically when a pipeline event fires?
Yes. The auto-scan orchestrator applies a branch filter to each CI event, then fans out to pipeline triggers and to your configured SAST and SCA integrations. It also always emits a runbook trigger event regardless of whether auto-scan is enabled. The step-by-step setup for pipeline-triggered scanning is covered in the dedicated operational guide rather than in this vendor-focused article.
How can I audit which CI events were received and whether they were signed?
PMAP exposes a CI event audit through GET /{id}/ci/events, which returns the last 200 webhook events for an integration. Each entry records the event type, repository, branch, commit, pull request, the action taken, and the signature validity. The signature-validity field lets you confirm that incoming webhooks are genuinely verified and spot any sudden run of invalid signatures.