diff --git a/README.md b/README.md index e2b213e..9df1535 100644 --- a/README.md +++ b/README.md @@ -61,12 +61,15 @@ enable what you give it. | `SOC_TITLE` | | `Security scan — ` | the report's title | | `SOC_VISIBILITY` | | `private` | `private` or `authenticated` | | `SOC_TAGS` | | `collector` | extra report tags | +| `SOC_EXCLUDE_IMAGES` | | — | comma-separated substrings; running images matching any are skipped by the `cve` source | ## Notes - **Docker socket** is mounted **read-only** (`:ro`) and is only used to *list* running containers and *inspect* their config. For extra isolation, point it at a scoped socket-proxy instead of the raw socket. +- The `cve` source **skips the collector's own container**, so the scanner never reports + on itself. Use `SOC_EXCLUDE_IMAGES` to drop any other images you don't want scanned. - The collector is **pure-stdlib Python**; the image just adds `nmap` and `trivy`. - Multi-server: run one container per server with a distinct `SOC_SLUG` — one report each. diff --git a/sources/cve.py b/sources/cve.py index acb0e2a..bd28633 100644 --- a/sources/cve.py +++ b/sources/cve.py @@ -13,6 +13,9 @@ that you can apply it. For an image you don't build and already run :latest of, explicit, and actionable findings sort above the can't-do-anything ones. """ import json +import os +import re +import socket import subprocess from soc import finding @@ -23,13 +26,46 @@ OWN_PREFIX = "git.skui.io/" STATUS_RANK = {"yours": 0, "update": 1, "upstream": 2} +def _own_container_id(): + """The collector's own container id, so we don't scan ourselves. + + /proc carries the full id regardless of `--hostname`; fall back to the + hostname (== the short container id by Docker default). Empty string when + not running in a container (then nothing is excluded).""" + try: + with open("/proc/self/mountinfo") as fh: # …/containers//{hostname,hosts} + m = re.search(r"/containers/([0-9a-f]{64})/", fh.read()) + if m: + return m.group(1) + except OSError: + pass + try: + with open("/proc/self/cgroup") as fh: # cgroup v1: …/docker/ + m = re.search(r"docker[-/]([0-9a-f]{64})", fh.read()) + if m: + return m.group(1) + except OSError: + pass + try: + return socket.gethostname().strip() + except Exception: + return "" + + def _running_images(): conts = _docker.get("/containers/json") or [] + self_id = _own_container_id() + # optional extra exclusions: SOC_EXCLUDE_IMAGES=substr1,substr2 + extra = [s.strip() for s in os.environ.get("SOC_EXCLUDE_IMAGES", "").split(",") if s.strip()] seen = [] for c in conts: + cid = c.get("Id", "") + if self_id and cid.startswith(self_id): + continue # don't scan the collector itself img = c.get("Image", "") - if img and img not in seen: - seen.append(img) + if not img or img in seen or any(x in img for x in extra): + continue + seen.append(img) return seen