- Python 71.7%
- Shell 28.3%
Backlog walker hypothesis "one cluster, one rule" demonstrated. linux-libc-dev appeared on multiple sm-* LXCs hit by 10+ kernel CVEs each — same triage reason for all of them (this binary package ships /usr/include/linux/*.h only; no runtime kernel code present). Generic rule with component_regex=^linux-libc-dev$ and no vulnId_regex absorbs the whole class. The pre-existing per-CVE rule for CVE-2026-31431 is retained below for audit clarity. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .forgejo/issue_template | ||
| .woodpecker | ||
| controls | ||
| docs | ||
| .gitignore | ||
| README.md | ||
Loop ISMS
The control repository for Loop's Information Security Management System.
This repo is the place where security policy meets code: each subsystem's controls live as declarative rules, the pipelines that enforce them run from .woodpecker/, the artefacts (CVE triage records, audit comments, evidence) live as issues + git history.
Going-towards-ISMS framing — today the only fully-built control is vulnerability management. Other ISO 27001-style controls (incident response, access control, change management, supplier risk) will land here as separate
controls/<name>/subtrees.
Layout
controls/
├── vulnerability-management/ # ISO 27001 A.8.8 (or :2013 A.12.6.1)
│ ├── README.md # control statement + scope
│ ├── rules/
│ │ ├── auto-fire-rules.json # broad patterns (Debian Tracker, ...)
│ │ └── triage-rules.json # reviewer-curated per-CVE decisions
│ └── scripts/
│ └── vex-generator.py # rule engine: rules → DT VEX upload + issue cleanup
└── (incident-response/ access-control/ ... — future controls)
docs/
├── architecture.md # end-to-end map + pipeline phases
├── data-flows.md # per-event flow walkthroughs
├── secrets.md # token/cert inventory + rotation
├── cve-triage-sop.md # decision tree + workflow
├── components/ # per-component reference
│ ├── qi-trivy.md
│ ├── dependency-track.md
│ ├── dt-exporter.md
│ ├── dt-vex-generator.md
│ ├── dt-project-tagger.md
│ ├── forgejo-bridge.md
│ ├── qubes-mesh-proxy.md
│ ├── grafana-dashboards.md
│ └── govulncheck.md
└── operational/
├── runbook.md # common tasks
└── woodpecker-migration.md # cluster CronJob → Woodpecker plan
.forgejo/
└── issue_template/
└── cve-triage.md # template for human triage records
.woodpecker/
└── ci.yml # validates rules + applies on schedule
Issue streams
Two kinds of issues live here:
-
Auto-filed findings — one issue per
(project, CVE)from forgejo-bridge on every NEW_VULNERABILITY (CRITICAL only) in Dependency-Track. Title pattern:[CRITICAL] CVE-XXXX-YYYY in <project>@<version>. The vex-generator pipeline auto-closes these once a rule suppresses the (CVE, project) pair. -
Reviewer-curated triage records — one issue per CVE, written when an analyst walks the decision tree and concludes NOT_AFFECTED. Title pattern:
[triage] CVE-XXXX-YYYY — <one-line conclusion>. The matching rule intriage-rules.jsonreferences the issue URL via itsissuefield.
Pipeline
.woodpecker/ci.yml runs three jobs:
- on push / PR: validates
rules/*.jsonJSON shape and rule schema; runs the vex-generator withDRY_RUN=trueso the diff to live DT is visible in the PR comments. - cron
dt-vex-apply(daily ~06:30 UTC): runs the vex-generator with writes — applies suppressions to DT, closes finding-issues whose (CVE, project) is now suppressed. - cron
dt-vex-stale-rules(weekly Monday 09:00 UTC): scans triage-rules.json for entries past their re-check date and opens reminder issues.
Connectors
Where the pipeline reaches out to:
| System | URL | Auth | Used for |
|---|---|---|---|
| Dependency-Track | dt.dev.loop-coop.net/api/v1 (mTLS) or dependency-track-api-server.dependency-track.svc:8080 (in-cluster) |
DT api-token | Walking findings, posting VEX |
| Forgejo | git.loop-coop.net/api/v1 |
PAT (write:issue on this repo) |
Closing finding-issues |
| Debian Security Tracker | security-tracker.debian.org/tracker/data/json |
none | Auto-fire nodsa/urgency=unimportant rules |
| Debian Packages index | deb.debian.org/debian/dists/<release>/main/binary-amd64/Packages.gz |
none | Binary→source name mapping |
| CISA KEV | raw.githubusercontent.com/cisagov/kev-data/main/known_exploited_vulnerabilities.json |
none | KEV indicator on dashboard exporter (separate component) |
Out of scope today
- Incident-response runbooks (controls/incident-response/) — TODO.
- Change-management evidence (controls/change-management/) — currently lives in repo PR history of each subsystem; ISMS-style aggregation is TODO.
- Annual policy review docs — TODO.
Reading order for a new analyst
- docs/architecture.md — what fits where (start here)
- docs/data-flows.md — how events propagate
- docs/cve-triage-sop.md — the decision tree
- docs/operational/runbook.md — how to actually do triage
- Component pages on demand: docs/components/
See also
- Dependency-Track upstream runbook (config-level, in talos repo)
- qi-trivy upstream runbook (build + scan, in qubes-incus repo)
- DT portfolio dashboard
- DT CVE-detail drilldown