Module 1: Legacy Baseline
It’s late 2022. Throughout this workshop you will work with a small Spring Boot app called the Pipeline Definition API — a stand-in for the kind of internal service many teams had in production at the time.
Maven Central publishes this release as 1.33; security write-ups and Lightwell
artifacts refer to it as 1.33.0. They are the same open-source release — only the
version string differs. The Lightwell fixed build is 1.33.0.rhlw-00001.
NOTE: Run all commands from the repository root (where compose.yaml lives).
|
What the demo app does
Imagine your platform team runs a service that lets developers submit CI/CD pipeline definitions as YAML. A developer sends a file describing build stages; the service checks that it looks valid and records it for later use.
That is what demo-app/ implements:
-
A single HTTP endpoint:
POST /api/pipelines/validate -
The request body is plain YAML text (not JSON)
-
The app parses the YAML into Java objects, runs basic validation, and saves a summary row to an embedded H2 database
-
Swagger UI at http://localhost:8080/swagger-ui/index.html lets you try the endpoint in a browser
A normal pipeline file looks like this (scripts/examples/valid-pipeline.yaml):
name: build-and-test
version: "1"
stages:
- name: compile
image: maven:3.8-openjdk-11
script: mvn -q test
- name: package
image: maven:3.8-openjdk-11
script: mvn -q package -DskipTests
The app is not a real CI system. It does not run those stages. It only accepts, parses, and stores pipeline metadata — which is enough to tell the SnakeYAML story.
Why this app matters for the workshop
Spring Boot apps often use SnakeYAML behind the scenes to load application.yml.
That is usually safe because the file sits on the server and is controlled by your
team.
This demo app is different: it uses SnakeYAML to read YAML sent by whoever calls the API. That is exactly the situation the SnakeYAML bug from 2022 is about.
The code lives under demo-app/src/main/java/com/redhat/lightwell/demo/. The
important classes are:
-
PipelineController— receives the HTTP request -
PipelineValidationService— orchestrates parse, validate, save -
PipelineYamlParser— turns YAML text into aPipelineDefinitionobject
Inspect the stack
Open demo-app/pom.xml and confirm:
-
Java 11
-
Spring Boot 2.7.x
-
Explicit pin:
org.yaml:snakeyaml:1.33(Maven Central; security write-ups often call this1.33.0) -
Springfox 3.0 (Swagger UI — typical for 2022-era services)
Find the risky code path
The application does not rely on Spring’s application.yml loader. It reads
YAML from HTTP requests in PipelineYamlParser using a custom PipelineConstructor.
Yaml yaml = new Yaml(new PipelineConstructor());
return yaml.load(yamlContent);
This is the pattern the bug warns about: Constructor lets YAML include special markers
that tell SnakeYAML which Java class to create — including classes an attacker chooses.
Run the baseline
If you already ran tests during Environment Setup, skip to Start the service.
podman compose --profile tools run --rm maven clean test
Start the service
Leave the stack running in a terminal (app on port 8080; mock server on 9999 — idle until Module 2):
make up
In another terminal, verify health:
curl -s http://localhost:8080/actuator/health
Optional: open Swagger UI at http://localhost:8080/swagger-ui/index.html
Submit benign pipeline YAML
Send the sample file from the repository:
curl -s -X POST http://localhost:8080/api/pipelines/validate \
-H 'Content-Type: text/plain' \
--data-binary @./scripts/examples/valid-pipeline.yaml
You should get JSON back with the pipeline name, version, and stages. The service also writes a row to H2 — proof that parsing and validation succeeded on legitimate input.
In Module 2 you will send very different YAML to the same endpoint.