-
-
Dongjo: every change is attacked before it can merge, and every release is watched after it ships.
-
A GitLab Duo flow plans, codes and attacks; a deterministic GitLab CI pipeline tests, gates, signs and releases.
-
Sealed benchmark, 3 runs: every gate passed all 16 planted mistakes; the red team caught 13. Misses and false positives published.
-
Production drill: a leak shipped on purpose was confirmed, bisected and rolled back 4 minutes after release; incident #14 went to Dongjo.
-
The Dongjo Map on the issue: all 9 DevSecOps stages, each linked to the job that proves it.
-
Run 4: attacks on the MR's own live Cloud Run revision. 1 of 15 succeeded, so policy-check blocked the merge until Dongjo fixed it.
-
v0.4.0 ships with a CycloneDX SBOM, OpenVEX built from the blocked attacks, and a Sigstore-signed evidence pack anyone can verify.
Who it is for
Small software teams, roughly 2 to 20 engineers, that run a web service, let coding agents write part of it, and have no security engineer and no release engineer. Their three problems: agents write merge requests faster than people can review them; green scanners do not mean safe; and customers and regulators now ask for evidence (SBOM, VEX, signed provenance) that nobody has time to write.
What it does
You assign a GitLab issue to Dongjo. That is the only human action.
- Plan. In about a minute, a Plan Card appears on the issue: acceptance criteria, a STRIDE threat table, a risk label and a sequence diagram.
- Create. The builder agent writes the code and one test per acceptance criterion, and opens a merge request.
- Attack before merge. CI deploys the merge request to its own Cloud Run revision (no traffic). The red team agent writes new attacks from the STRIDE table and runs them over real HTTP against that live revision. One successful attack blocks the merge. Dongjo fixes the code and the same attacks run again.
- Merge. When every gate passes, a CI job merges at the exact commit the gates checked. The agent itself cannot merge, and
gate-guardfails any agent change to the pipeline, the policy, the flow or existing attacks. - Release. The signed image rolls out as a canary at 10, 50 and 100 percent, judged against stable at each step, with automatic rollback. The release carries a CycloneDX SBOM, an OpenVEX document whose
not_affectedstatements are backed by the blocked attack transcripts, and an evidence pack signed with Sigstore. One cosign command verifies it. - Watch. After every release and every 15 minutes, five user journeys and every attack ever committed run against production. If a promise breaks, Dongjo confirms twice, bisects the Cloud Run revisions, rolls back to the last good one and opens an incident assigned to Dongjo, which starts the loop again. (During judging it only reports; see below.)
- Map. On the issue, the Dongjo Map links all nine DevSecOps stages (Plan, Create, Verify, Package, Secure, Release, Configure, Monitor, Govern) to the jobs that prove them.
The Hands-off brief, step by step (run 4: issue #5, MR !23, v0.4.0):
| The brief says | Dongjo |
|---|---|
| You create an issue | The issue is assigned to Dongjo at 16:20:25 UTC |
| Agents review it | 55 s later: Plan Card with five acceptance criteria, a STRIDE table and dongjo-risk::high |
| Create 1+ MRs | The builder opens MR !23 with one test per acceptance criterion |
| Run security scans | SAST, secret detection, pip-audit, and 15 attacks against the MR's own live Cloud Run revision: 1 succeeded |
| Fix what they find | Dongjo fixes the code; the same attacks: 0 of 15 |
| Merge when everything passes | The auto-merge CI job merges at the commit the gates checked, 16:31:29 |
| Deploy to staging, validate | Every MR runs on its own staging revision before merge; the canary is judged against stable |
| Promote to production | Canary 10% → 50% → 100%, PROMOTE; a failing canary rolls back with no release |
| Post a summary on the issue | The Dongjo Map: nine stages, each linked to its job |
| You touched nothing | 0 human touches, issue → release in 23 minutes (runs 5 and 6: 21 and 26) |
| "We expect submissions that go well beyond them" | OpenVEX from blocked attacks, a Sigstore-signed evidence pack, a production watch every 15 minutes with release bisect and rollback, and a sealed benchmark of the red team |
Self-healing is real, and frozen for judging. From 26 October until the submission, the watch ran against production every 15 minutes with full authority to roll back and to hand Dongjo an incident; the drill below is it doing exactly that. The rules ask that the repository stay unchanged from the deadline until the winners are announced, and a self-healing Dongjo would change it by itself: a broken promise makes the watch roll back and open an incident, and the incident starts a Dongjo run that merges and releases. So before the deadline we set watch.act: false in dongjo.yml: the watch still checks production with every journey and attack every 15 minutes, confirms and bisects, but it moves no traffic and opens no incident. What it does when it acts is shown by the drill below, with links to its jobs. The README section "During judging: the watch only reports" has the details.
Results, every one linked in the README:
- Three runs went from assignment to release with zero human touches, in 23, 21 and 26 minutes.
- On Dongjo's own builder code, the red team found four real flaws in pipelines where unit tests, the AC gate, Semgrep SAST, secret detection and pip-audit were all green. None shipped.
- Sealed benchmark, three runs. A person wrote small features with common API mistakes and sealed the answer key by SHA-256 before each run. Every gate passed all 16 mistakes. The red team caught 13 of 16. We also measured false positives on the same features without the mistake: after one prompt change they dropped from 4 of 6 to 0 of 6, and on new code in run 3 two of four were blocked, one of them by a real 500 the key had missed. Every miss and every wrong attack is quoted in the results.
- A drill in production. We shipped a leak on purpose: a search cache switched on only in production. Every gate passed it. Four minutes after the release, the watch had confirmed it, rolled production back and opened an incident; Dongjo's fix held against 30 attacks and shipped. One human touch was needed (a test line too long for lint), and that cause is fixed too.
How we used GitLab to automate the post-code lifecycle
All nine stages, each with a proof link in the README's stage table:
- Plan: the
planneragent posts a Plan Card on the issue: acceptance criteria, a STRIDE threat table, a scoped risk label and a Mermaid sequence diagram. - Create: the
builderagent opens the merge request, with a test named after every acceptance criterion. - Verify:
lint, unit tests andac-gate, which fails the MR if any acceptance criterion lacks a passing test. - Package: container build, CycloneDX SBOM, keyless cosign signature and SBOM attestation.
- Secure: GitLab SAST, secret detection and pip-audit, plus the
redteamagent's new attacks run over HTTP against the MR's own Cloud Run revision. One successful attack blocks the merge. - Release: the version is computed from Conventional Commits; the GitLab Release carries the changelog, the OpenVEX document and the signed evidence pack.
- Configure: the Google Cloud platform as Terraform, planned read-only on every MR; Cloud Run revisions deployed by digest through Workload Identity Federation, with no stored keys.
- Monitor: a canary judge at 10, 50 and 100 percent with automatic rollback; after release, a scheduled watch every 15 minutes that bisects revisions, rolls back and opens an incident assigned to Dongjo.
- Govern:
policy-checkturnsdongjo.ymlinto the merge decision;gate-guardfails any agent change to the pipeline, the policy, the flow or existing attacks; the evidence pack is mapped to NIST SSDF.
GitLab features used: Duo Agent Platform custom flows (two, in the AI Catalog, started by an Assign trigger and run by their service accounts), merge request and scheduled pipelines, environments and resource groups for staging and production, GitLab SAST and Secret Detection, OIDC ID tokens for Google Cloud and Sigstore, protected and masked variables, scoped labels, issue and MR comments, the Releases API, GitLab Pages for the Dongjo Console, and Mermaid rendering for the Dongjo Map.
Google Cloud. notes-api runs on Cloud Run in europe-north1, with images in Artifact Registry. The deployment code is in the repository: infra/terraform/ (the platform), infra/setup.sh, ci/ (staging, canary, rollout and watch scripts) and .gitlab-ci.yml.
How we built it
- Two halves: "CI computes, the LLM decides." A GitLab Duo Agent Platform custom flow (
flows/dongjo.yaml, in the AI Catalog) does what needs judgment: planner, builder, red team and shipper agents. A deterministic GitLab CI pipeline does everything that can be computed: tests, the AC gate, SAST, secret detection, pip-audit, attacks, image build, SBOM, signing, VEX, canary judging, release and watch. Merge, VEX status and promote or rollback are computed from exit codes and the policy filedongjo.yml, never from model prose. - Batons. Agents and CI hand off state as small JSON "batons" in issue and merge request comments, which also feed the Dongjo Map.
- Real attacks. Attack tests are pytest files that assert a defence holds, run over HTTP against the merge request's own Cloud Run revision tag and again against the production canary.
- Google Cloud without keys. GitLab OIDC to Workload Identity Federation for deploys, separate service accounts for staging and production, the platform described in Terraform and planned read-only on every merge request. GitLab OIDC to Sigstore for keyless signatures.
- A second flow for the benchmark. "Dongjo red team" runs only the planner and red team with identical prompts, so the benchmark measures the red team alone.
- Dongjo Console on GitLab Pages shows every release with its attacks, gates, canary and evidence.
- The service Dongjo works on is notes-api, a small FastAPI and SQLite app built during the hackathon.
Challenges we ran into
- The flow could not merge. A run went green in 14 minutes and then GitLab refused the merge with
403 insufficient_scope: the flow token cannot merge, and neither can the CI job token. We moved merging into a CI job that runs only afterpolicy-checkpasses and merges at the exact commit the gates checked. - Flows only start on a person's action, so the production watch cannot start Dongjo by itself. The watch opens the incident with a narrowly scoped team-member token that merge request pipelines never see.
- False positives. In the first benchmark run the red team blocked four of six fine changes by assuming exact status codes the contract never names. One paragraph in the prompt, "what counts as a finding", brought that to zero in run 2, and cost two catches, which we report.
- The harness had to fail closed. One attack could not run because httpx rejects a
"Bearer "header; Dongjo stopped with an exact diagnosis instead of passing. We now run every new attack over real HTTP before committing it. - Three main pipelines computed the same version. Queued pipelines each picked v0.9.0, and two failed with
409 Release already exists. Versions now come from the commit history, and a test replays that morning. - Smaller ones: Cloud Run's front end reserves paths ending in "z", so
/healthzalways answered 404; scoped labels in one scope wipe each other out; and agent prompts and tool outputs have HTML comments stripped, so batons became fenced blocks.
Accomplishments that we're proud of
- Zero-touch runs from issue to signed release in about 20 minutes, with a red team that attacks each change's own live revision before the merge.
- A benchmark with a sealed answer key, run three times, where we publish the misses and the false positives as plainly as the catches.
- OpenVEX that is earned:
not_affectedonly when blocked attack transcripts or a test-backed statement say so. - A real rollback and a real drill in production, with timestamps and job links.
- Every row of the nine-stage table in the README links to the job that proves it.
What we learned
- A green scanner run says little about what a running service answers a stranger. Attacks against the live revision found flaws that every static gate passed.
- Agents are best kept away from the decisions that matter. Letting the model write code and attacks while CI decides merge, VEX and rollout made the system both autonomous and auditable.
- Measuring false positives matters as much as measuring catches. Our first red team was too eager, and one clear definition of a finding fixed most of it.
- Honest numbers are more convincing than perfect ones.
What's next for Dongjo
- Run merge request staging with production settings, so configuration-only leaks like the drill's are caught before merge.
- More attack classes in the red team, such as rate limits and timing, behind the same "what counts as a finding" rule.
- Packaging Dongjo as AI Catalog items and a CI component that any GitLab project can enable.
- Running the sealed benchmark on more services than notes-api.
Log in or sign up for Devpost to join the conversation.