No description
  • Python 71.7%
  • Shell 28.3%
Find a file
statevault 2db9734cee feat(triage): generic linux-libc-dev rule (kernel headers only)
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>
2026-05-10 12:54:45 +02:00
.forgejo/issue_template docs: bootstrap CVE triage SOP + issue template 2026-05-06 13:39:05 +02:00
.woodpecker chore: rename references security-findings → isms 2026-05-06 14:17:03 +02:00
controls feat(triage): generic linux-libc-dev rule (kernel headers only) 2026-05-10 12:54:45 +02:00
docs feat(vex): alpine-secdb auto-fire + backlog-walker 2026-05-10 12:46:29 +02:00
.gitignore feat(vex): alpine-secdb auto-fire + backlog-walker 2026-05-10 12:46:29 +02:00
README.md docs(readme): point at the new docs/ tree 2026-05-06 14:30:01 +02:00

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:

  1. 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.

  2. 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 in triage-rules.json references the issue URL via its issue field.

Pipeline

.woodpecker/ci.yml runs three jobs:

  • on push / PR: validates rules/*.json JSON shape and rule schema; runs the vex-generator with DRY_RUN=true so 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

  1. docs/architecture.md — what fits where (start here)
  2. docs/data-flows.md — how events propagate
  3. docs/cve-triage-sop.md — the decision tree
  4. docs/operational/runbook.md — how to actually do triage
  5. Component pages on demand: docs/components/

See also