{"id":50668073,"url":"https://github.com/davidcollom/komodor-security-reporter","last_synced_at":"2026-06-08T08:06:24.494Z","repository":{"id":356327688,"uuid":"1231926428","full_name":"davidcollom/komodor-security-reporter","owner":"davidcollom","description":"low-noise bridge between running Kubernetes workloads, vulnerability scanners (Trivy, Snyk, Wiz), and Komodor","archived":false,"fork":false,"pushed_at":"2026-05-07T16:16:10.000Z","size":89,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-07T16:40:46.549Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/davidcollom.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-07T12:22:37.000Z","updated_at":"2026-05-07T15:43:23.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/davidcollom/komodor-security-reporter","commit_stats":null,"previous_names":["davidcollom/komodor-security-reporter"],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/davidcollom/komodor-security-reporter","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidcollom%2Fkomodor-security-reporter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidcollom%2Fkomodor-security-reporter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidcollom%2Fkomodor-security-reporter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidcollom%2Fkomodor-security-reporter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/davidcollom","download_url":"https://codeload.github.com/davidcollom/komodor-security-reporter/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidcollom%2Fkomodor-security-reporter/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34053517,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-08T02:00:07.615Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-08T08:05:46.170Z","updated_at":"2026-06-08T08:06:24.489Z","avatar_url":"https://github.com/davidcollom.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Komodor Image Vulnerability Watcher\n\nA Kubernetes-native watcher that detects container image vulnerabilities and publishes actionable security events to Komodor.\n\n## Overview\n\nThis application provides a secure, low-noise bridge between running Kubernetes workloads, vulnerability scanners (Trivy, Trivy Operator reports, Snyk, Wiz, Clair), and Komodor. It:\n\n- Watches Kubernetes workloads (Deployments, StatefulSets, DaemonSets, Jobs, CronJobs)\n- Extracts container images from running workloads\n- Resolves mutable tags to immutable digests\n- Scans images for vulnerabilities using pluggable scanner drivers\n- Normalises scanner-specific results into a common model\n- Publishes meaningful vulnerability events to Komodor\n- Deduplicates scan results to avoid alert fatigue\n\n## Security Model\n\nThe watcher is designed with a strong security posture:\n\n- **No host access**: No hostPath mounts, runtime sockets, or privileged containers\n- **No Secret access**: Does not require Kubernetes API permissions to read Secrets\n- **No impersonation**: Does not impersonate workload ServiceAccounts\n- **Minimal RBAC**: Read-only access to workload metadata only\n- **Restricted container**: Runs as non-root with read-only filesystem and dropped capabilities\n\nSee [RFC](docs/rfc.md) for full security principles.\n\n## Quick Start\n\n### Prerequisites\n\n- Kubernetes 1.24+\n- A container image scanner (e.g., Trivy)\n- Komodor account and API key\n\n### Installation\n\n```bash\n# Using make\nmake install-tools\nmake build\n\n# Or manually\ngo install ./cmd/komodor-security-reporter\n```\n\n### Configuration\n\nCopy and customise the example configuration:\n\n```bash\ncp docs/example-config.yaml config.yaml\n```\n\nKey configuration options:\n\n```yaml\nclusterName: prod-eks-01\n\n# Namespaces to watch\nnamespaces:\n  include:\n    - production\n    - platform\n  exclude:\n    - kube-system\n\n# Workload kinds to watch\nworkloads:\n  kinds:\n    - Deployment\n    - StatefulSet\n\n# Scanners to use\nscanners:\n  scanners:\n    - name: trivy\n      type: trivy\n      enabled: true\n      command:\n        binary: /usr/local/bin/trivy\n        timeout: 5m\n\n# Publishing policies\npublishing:\n  mode: komodor\n  minimumSeverity: high\n  includeTopFindings: 5\n  publishCleanScans: false\n  dedupeTTL: 24h\n\nkomodor:\n  baseURL: https://app.komodor.io\n```\n\n### Running Locally\n\n```bash\n# Set Komodor API key (required for publish mode: komodor or both)\nexport KOMODOR_API_KEY=your-api-key\n\n# Run with config\n./bin/komodor-security-reporter -config config.yaml\n\n# Enable debug logging\n./bin/komodor-security-reporter -config config.yaml -log-level debug\n```\n\n## Development\n\nSee [DEVELOPMENT.md](./docs/DEVELOPMENT.md) for more info\n\n## Architecture\n\n### Components\n\n1. **Kubernetes Workload Watcher**: Observes supported workload resources and detects image references\n2. **Image Extractor**: Reads images from containers, initContainers, and ephemeralContainers\n3. **Digest Resolver**: Resolves image tags to immutable digests using go-containerregistry\n4. **Scanner Registry**: Loads configured scanner drivers and invokes them\n5. **Scanner Drivers**: Scan images and return structured results (Trivy, Trivy Operator, Snyk, Wiz, Clair)\n6. **Finding Normaliser**: Converts scanner-specific results to a common model\n7. **Policy Evaluator**: Determines whether to publish based on severity and deduplication\n8. **Komodor Publisher**: Publishes normalised events to Komodor\n9. **State Store**: ConfigMap-backed deduplication state\n\n### Data Flow\n\n```plain\nKubernetes Workload\n  ↓\nImage Extractor\n  ↓\nDigest Resolver\n  ↓\nScanner Registry\n  ↓\nFinding Normaliser\n  ↓\nPolicy Evaluator\n  ↓\nKomodor Event Publisher\n  ↓\nState / Dedupe Store\n```\n\n## Testing\n\n```bash\n# Run all tests\nmake test\n\n# Run with coverage\nmake coverage\n\n# Run short tests only (excludes integration tests)\nmake test-short\n\n# Run specific test\ngo test -run TestFingerprint ./internal/policy\n```\n\n### Test Strategy\n\n- **Unit tests**: All core logic components (config, scanners, registry, policy)\n- **Table-driven tests**: For parsing logic and policy evaluation\n- **Mock/fake clients**: For Kubernetes and Komodor interactions\n- **Integration tests**: Optional for scanner drivers (skipped by default)\n\n## Deployment\n\n### Kubernetes Manifests\n\nSee `helm/` directory for complete Helm chart.\n\nMinimal ServiceAccount and RBAC:\n\n```yaml\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: komodor-security-reporter\n  namespace: security\n\n---\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n  name: komodor-security-reporter\nrules:\n  - apiGroups: [\"\"]\n    resources: [namespaces]\n    verbs: [get, list, watch]\n  - apiGroups: [apps]\n    resources: [deployments, statefulsets, daemonsets]\n    verbs: [get, list, watch]\n  - apiGroups: [batch]\n    resources: [jobs, cronjobs]\n    verbs: [get, list, watch]\n  # For ConfigMap-backed state store\n  - apiGroups: [\"\"]\n    resources: [configmaps]\n    verbs: [get, list, create, update]\n\n---\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRoleBinding\nmetadata:\n  name: komodor-security-reporter\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: komodor-security-reporter\nsubjects:\n  - kind: ServiceAccount\n    name: komodor-security-reporter\n    namespace: security\n```\n\n### Pod Security\n\n```yaml\nspec:\n  securityContext:\n    runAsNonRoot: true\n    runAsUser: 65534\n    readOnlyRootFilesystem: true\n    allowPrivilegeEscalation: false\n    capabilities:\n      drop:\n        - ALL\n\n  containers:\n    - name: watcher\n      image: komodor-security-reporter:latest\n      imagePullPolicy: IfNotPresent\n\n      env:\n        - name: KOMODOR_API_KEY\n          valueFrom:\n            secretKeyRef:\n              name: komodor-credentials\n              key: api-key\n\n      ports:\n        - name: metrics\n          containerPort: 8080\n\n      volumeMounts:\n        - name: config\n          mountPath: /etc/komodor-security-reporter\n          readOnly: true\n        - name: tmp\n          mountPath: /tmp\n        - name: cache\n          mountPath: /var/cache/komodor-security-reporter\n\n  volumes:\n    - name: config\n      configMap:\n        name: komodor-security-reporter\n    - name: tmp\n      emptyDir: {}\n    - name: cache\n      emptyDir: {}\n```\n\n## Metrics\n\nPrometheus metrics are exposed on `:8080/metrics`:\n\n- `image_vuln_watcher_images_observed_total` - Total images observed\n- `image_vuln_watcher_images_resolved_total` - Total images resolved to digest\n- `image_vuln_watcher_image_resolution_errors_total` - Resolution failures\n- `image_vuln_watcher_scans_total` - Total scans performed\n- `image_vuln_watcher_scan_errors_total` - Scan failures\n- `image_vuln_watcher_scan_duration_seconds` - Scan duration histogram\n- `image_vuln_watcher_events_published_total` - Events published\n- `image_vuln_watcher_event_publish_errors_total` - Publishing failures\n- `image_vuln_watcher_dedupe_hits_total` - Deduplicated events\n\n## Debugging Kubernetes Events\n\nWhen running with `--publish-mode=events` or `--publish-mode=both`, the reporter creates native Kubernetes `Warning` Events on the affected workload. You can inspect these with `kubectl`:\n\n```bash\n# List all VulnerabilityScan events across all namespaces\nkubectl get events -A --field-selector reason=VulnerabilityScan\n\n# Filter to a specific namespace\nkubectl get events -n \u003cnamespace\u003e --field-selector reason=VulnerabilityScan\n\n# Watch events in real time\nkubectl get events -A --field-selector reason=VulnerabilityScan -w\n\n# Show full event details for a specific workload\nkubectl describe deployment/\u003cname\u003e -n \u003cnamespace\u003e | grep -A5 VulnerabilityScan\n\n# Filter by the reporting component\nkubectl get events -A \\\n  --field-selector reportingComponent=komodor-security-reporter\n```\n\nEvents use `reason=VulnerabilityScan` and `type=Warning` (or `Normal` for clean scans). The `MESSAGE` column contains the vulnerability summary, e.g.:\n\n```plain\nsummary=\"critical=3 high=21 medium=16 low=1 total=49\" scanner=trivy image=... findings=49 (critical=3 high=21 medium=16 low=1)\n```\n\n\u003e **Note:** For human-readable local output, add `--log-format=text` to the reporter flags.\n\n## Logging\n\nStructured logging uses JSON output with contextual fields:\n\n```json\n{\"level\":\"info\",\"msg\":\"loaded configuration\",\"cluster\":\"prod-eks-01\",\"time\":\"2024-01-15T10:30:45Z\"}\n{\"level\":\"warn\",\"msg\":\"failed to resolve image digest\",\"image\":\"ghcr.io/acme/app:1.0\",\"error\":\"404 not found\"}\n```\n\nLog levels: `debug`, `info` (default), `warn`, `error`\n\n## Observability\n\n### Health Checks\n\n`GET /healthz` - Returns 200 OK if service is healthy\n\n### Metrics\n\n`GET /metrics` - Prometheus-format metrics\n\n### Logs\n\nAll events are structured with fields:\n\n- `cluster` - Cluster name\n- `namespace` - Workload namespace\n- `workloadKind` - Kind of workload (Deployment, etc)\n- `workloadName` - Workload name\n- `container` - Container name\n- `image` - Image reference\n- `digest` - Image digest\n- `scanner` - Scanner name\n\n## Release\n\n### Build Release Locally\n\n```bash\n# Build snapshot (development)\nmake release-snapshot\n\n# Create a release (requires git tag)\n# 1. Tag the release: git tag v0.1.0\n# 2. Run release:\nmake release\n```\n\nThe release process:\n\n1. Builds binaries for linux/amd64, linux/arm64, darwin/amd64, darwin/arm64\n2. Creates archives and checksums\n3. Builds and pushes Docker images (requires Docker credentials)\n4. Creates GitHub release with binaries\n5. Generates changelog from commits\n\n### Docker Images\n\nImages are published to: `ghcr.io/davidcollom/komodor-security-reporter`\n\nTags:\n\n- `vX.Y.Z` - Specific release\n- `latest` - Latest release\n\n## Configuration Reference\n\nSee [docs/example-config.yaml](docs/example-config.yaml) for full configuration options.\n\n## Architecture Decision Records\n\nSee [docs/rfc.md](docs/rfc.md#decision-record) for design decisions:\n\n- No CRDs in v1\n- No Kubernetes Secret read RBAC\n- No impersonation\n- No host-level access\n\n## Contributing\n\n1. Ensure tests pass: `make test`\n2. Format code: `make fmt`\n3. Run linters: `make lint`\n4. Create a pull request\n\n## License\n\nApache License 2.0\n\n## Support\n\nFor issues, questions, or suggestions, please open a GitHub issue.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidcollom%2Fkomodor-security-reporter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdavidcollom%2Fkomodor-security-reporter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidcollom%2Fkomodor-security-reporter/lists"}