Repository navigation
Releases
v0.3.3
Makes the chart upgradable with --reuse-values again.
Upgrade
Upgrading from 0.3.2 or older with helm upgrade --reuse-values works again.
Nothing else changes for existing installations.
Fixed
helm upgrade --reuse-valuesfrom an older chart leftscan.maxLayerSize
empty, and meles refused to start.
Dependencies
modernc.org/sqlite1.62.0,golang.org/x/sync0.25.0,
github.com/spf13/pflag1.1.0; GitHub Actions updates.
Changelog
Fixes
Other changes
- 0cc5871: chore(deps): bump the go-dependencies group across 1 directory with 3 updates (#8) (@dependabot[bot])
- 802b35c: ci: bump the actions group across 1 directory with 2 updates (#7) (@dependabot[bot])
Image: ghcr.io/movray/meles:0.3.3 (linux/amd64, linux/arm64)
Helm chart: helm install meles oci://ghcr.io/movray/charts/meles --version 0.3.3
Binaries, image and chart carry build provenance; verify with gh attestation verify
(see the README, section Install).
v0.3.2
Closes three gaps that let content pass unscanned, shows incomplete runs as
such, and is the first release tested against popular and known malicious
images: see docs/popular-images.md.
Upgrade
A client of the API that treats every status other than infected and error
as clean has to learn the new status incomplete. Scans of images with large
archives take longer with the new limits. The operator scans its images again,
because the rules changed. With the CLI against your own clamd, add
meles-own.yar to clamd's database, or meles selftest --yara fails.
Security
- The server stored runs with skipped files as
cleanand showed "No malware
found". They now have the statusincompletein the UI and the API, like in
the CLI and the operator, and count as needing attention. Stored runs are
corrected at the first start. - Whiteout entries with content were not scanned: a file named
.wh.<name>
or.wh..wh..opqcould carry malware through a scan as clean. A runtime
never unpacks such an entry, but the image ships it. Its content is now
scanned and a finding has the statusdeleted. The selftest has a new case
for it,eicar-whiteout-content. - Data after the end of a layer's tar archive was read but not scanned. It now
makes the scanIncomplete(meles.Unsupported.TrailingData), and it
counts against--max-layer-size. - Sparse files could expand far beyond
--max-layer-size, because the limit
only counted the bytes read. It now counts what the entries declare, across
the whole layer. - The mirror installs cvdupdate and its dependencies with pinned hashes
(charts/meles/files/mirror/requirements.txt) instead of the newest
matching version from PyPI. Dependabot updates the file.
Added
-
Fuzz tests for the layer extractor:
make fuzz. -
A refresh button with an interval in the header of the web UI. The browser
remembers the interval;Autorefreshes while a run is active, as before. -
Chart value
scan.maxLayerSizefor--max-layer-size. Machine learning
images can have layers above the default of 4G. -
YARA rules of our own in
meles-own.yar, for xmrig-proxy, ariominer and the
JSON configuration of XMRig and xmrig-proxy.
Changed
- Higher default limits in the chart, because popular images stayed
Incompletewith the old ones:clamd.maxFiles100000 (was 10000),
clamd.maxScanTime600000 (was 120000),clamd.maxScanSize2047M (in effect
768M before). Images with large archives take up to twice as long, in the
worst case 3.6 times, and clamd can unpack more into its ephemeral storage.
Fixed
- A long scan could end with an error: a resumed layer download failed with
403 once the signed CDN URL had expired, and with 401 once the token of the
registry had. meles now asks the registry for new access.
Changelog
Features
- a3bdc0c: feat(chart): higher default limits and scan.maxLayerSize (@movray)
- ff6b058: feat(rules): own YARA rules for xmrig-proxy, ariominer and XMRig configs (@movray)
- b09669b: feat(server): refresh button with an interval in the web UI (@movray)
Fixes
- a78f6bf: fix(chart): install the mirror's Python packages with pinned hashes (@movray)
- 5098af9: fix(ci): accept rule files that YARA-X passes without warnings (@movray)
- e9644d1: fix(extract): scan whiteout content and limit what a layer can hide (@movray)
- 57284a0: fix(server): show runs with skipped files as incomplete (@movray)
- 8297b8f: fix(source): renew expired access when resuming a download (@movray)
Image: ghcr.io/movray/meles:0.3.2 (linux/amd64, linux/arm64)
Helm chart: helm install meles oci://ghcr.io/movray/charts/meles --version 0.3.2
Binaries, image and chart carry build provenance; verify with gh attestation verify
(see the README, section Install).
v0.3.1
Shows in the UI whether meles still finds what it must find.
Upgrade
The selftest CronJob of the chart now runs daily, and the server scans the
test images every 6 hours. With clamd.enabled=false and a clamd without the
EICAR signature the UI shows the selftest as failed; set
server.selftestInterval=0 then.
Added
- The server runs the selftest every 6 hours and shows the result in the UI
and at/api/selftest: clamd can answer and still have lost its signatures.
--selftest-interval, chart valueserver.selftestInterval, 0 turns it off.
Changed
- The selftest CronJob of the chart now runs daily. Set
selftest.suspend=truefor the old behaviour.
Changelog
Features
- 916dffd: feat(chart): run the selftest CronJob daily (@movray)
- be14081: feat(server): run the selftest regularly and show the result (@movray)
Image: ghcr.io/movray/meles:0.3.1 (linux/amd64, linux/arm64)
Helm chart: helm install meles oci://ghcr.io/movray/charts/meles --version 0.3.1
Binaries, image and chart carry build provenance; verify with gh attestation verify
(see the README, section Install).
v0.3.0
Makes meles easier to start with and more robust while clamd restarts.
Upgrade
server.ingressandserver.httpRoutenow need a login. Without
server.oauth2Proxythe chart refuses to render. If another proxy in
front of the UI handles the login, or the UI stays on an internal network,
setserver.allowUnauthenticated=true.- With
clamd.detectPUAorclamd.extraConfigset, all images are
rescanned once: the signature version now carries+config.<hash>. With
the default options nothing changes.
Added
docs/results.mdexplains the results, whatCleandoes not guarantee,
limits and false positives. The README starts with an overview, and its
TL;DR now covers Kubernetes with the operator.- The release workflow scans the image with meles and Trivy before it is
published.
Changed
- The operator tries a scan again for almost 4 minutes if clamd fails, so a
clamd that is starting or being replaced no longer leads toErrorreports,
and pods held by the scan gate are no longer released unscanned because of
it. - A change of
clamd.detectPUAorclamd.extraConfigtriggers rescans and
reaches the layer cache.
Changelog
Other changes
- 87f8817: chore(deps): bump modernc.org/sqlite from 1.61.0 to 1.61.1 in the go-dependencies group across 1 directory (#5) (@dependabot[bot])
- e1fd3eb: chore(deps): bump the kubernetes group with 3 updates (#4) (@dependabot[bot])
Image: ghcr.io/movray/meles:0.3.0 (linux/amd64, linux/arm64)
Helm chart: helm install meles oci://ghcr.io/movray/charts/meles --version 0.3.0
Binaries, image and chart carry build provenance; verify with gh attestation verify
(see the README, section Install).
v0.3.0-rc.1
Changelog
Features
- ca6eb7a: feat(chart)!: refuse to expose the web UI without a login (@movray)
- 4630310: feat(clamd-proxy): put a hash of the clamd options into VERSION (@movray)
Fixes
Other changes
- 9ce42c6: ci: count files above clamd's limits as skipped in the mini clamd (@movray)
- d8db14e: ci: scan the image with meles and Trivy before a release (@movray)
Image: ghcr.io/movray/meles:0.3.0-rc.1 (linux/amd64, linux/arm64)
Helm chart: helm install meles oci://ghcr.io/movray/charts/meles --version 0.3.0-rc.1
Binaries, image and chart carry build provenance; verify with gh attestation verify
(see the README, section Install).
v0.2.0
A security release: it fixes the findings of a review of meles itself
(permissions, admission, network paths, dependencies). It has incompatible
changes; read Upgrade before you update.
Upgrade
-
Apply the CRDs first. Helm installs CRDs but never updates them:
helm pull oci://ghcr.io/movray/charts/meles --version 0.2.0 --untar kubectl apply --server-side --force-conflicts -f meles/crds/
-
Scan results moved from
.reportto.statusof each
MalwareReport (a status subresource). Results from 0.1.0 are dropped on
the upgrade, and the operator scans every image in the cluster once
more (it pulls each image again; about 45 minutes for 100 images in our
test cluster). Meanwhile reports have no result yet; reports of
CronJobs get one at their next run. Scripts,kubectlJSONPath and
dashboards that read.reporthave to read.status. -
Images from registries on private addresses (10/8, 172.16/12,
192.168/16, 100.64/10, fc00::/7) are refused by the server, the operator
and the Harbor adapter unless the registry is a configured mirror or
proxy, the Harbor that called the adapter, or listed in
scan.allowPrivateRegistries(--allow-private-registry). Loopback and
link-local addresses are always refused, plain HTTP only with
--insecure-registry. The CLI is unchanged. -
Scan gate (only with
operator.gate.enabled): the new
operator.gate.protectis on by default. In gated namespaces:-
meles.io/gate: skipneeds the namespace label
meles.io/gate-skip=allowed; without it, the pod is refused:kubectl label namespace <namespace> meles.io/gate-skip=allowed
-
new pods with
spec.nodeNameare refused (except from the kubelet), -
the image of a pod can no longer be changed in place; change the
workload instead.
To see first what it would refuse, set
operator.gate.protect.validationActions: [Warn];
operator.gate.protect.enabled: falsekeeps the behaviour of 0.1.0. -
Security
- Forged scan results. The result of a MalwareReport could be written
by anyone withpatchon MalwareReports, including the server for its
rescan button, and the operator trusted existing reports, for reuse also
those of other namespaces. Results are now in the status subresource,
which only the operator may write. - Scan gate bypass by namespace members. Anyone who could create or
update pods in a gated namespace could let an image run unscanned: opt
out, bind the pod to a node, remove the scheduling gate, switch to audit
mode or change the image after the release. A ValidatingAdmissionPolicy
(operator.gate.protect) refuses all of these. A pod created with the
gate andmeles.io/gate-mode: auditwas held in audit mode in an
enforcenamespace; the webhook now always sets the mode of the
namespace. - Server-side request forgery. Image references from pods and UI runs
could make meles connect to internal services or the cloud metadata
endpoint and put the answer into reports and events. Every connection is
now checked after the DNS lookup (redirects and token realms included),
and error bodies are cut short. - Open redirect. The back link of the ignore form accepted a tab
(/\t/evil.example), which browsers turn into a link to another host. - HTTP/2 vulnerabilities in
golang.org/x/netreachable from the
server and the registry client (GO-2026-6603, GO-2026-6610,
GO-2026-6611, GO-2026-6612, GO-2026-6617): updated to v0.62.0.
Other changes
- The history views bound the number of days they allocate for.
- CI runs
govulncheckon every push, weekly and before every release; a
known vulnerability in a code path meles reaches stops the release.
Changelog
Features
Fixes
- ee7af97: fix(api)!: keep the scan result in the status subresource (@movray)
- db3cb57: fix(deps): golang.org/x/net v0.62.0 (@movray)
- f7eb4cf: fix(operator): take the gate mode from the namespace for gated pods (@movray)
- 1cc2f4b: fix(server): refuse control characters in the back link (@movray)
- 5e720ea: fix(source): refuse internal addresses for references from others (@movray)
- c03da90: fix(store): bound the days of Daily and ClusterDaily (@movray)
Other changes
Image: ghcr.io/movray/meles:0.2.0 (linux/amd64, linux/arm64)
Helm chart: helm install meles oci://ghcr.io/movray/charts/meles --version 0.2.0
Binaries, image and chart carry build provenance; verify with gh attestation verify
(see the README, section Install).
v0.1.0
Changelog
Image: ghcr.io/movray/meles:0.1.0 (linux/amd64, linux/arm64)
Helm chart: helm install meles oci://ghcr.io/movray/charts/meles --version 0.1.0
Binaries, image and chart carry build provenance; verify with gh attestation verify
(see the README, section Install).
v0.1.0-rc.2
Changelog
Fixes
Image: ghcr.io/movray/meles:0.1.0-rc.2 (linux/amd64, linux/arm64)
Helm chart: helm install meles oci://ghcr.io/movray/charts/meles --version 0.1.0-rc.2
Binaries, image and chart carry build provenance; verify with gh attestation verify
(see the README, section Install).
v0.1.0-rc.1
Changelog
Features
- 5574269: feat!: fail on skipped files by default, raise --max-file-size to 768M (Sentuerk Ugras sugras@itknecht.de)
- 40aecb8: feat(chart): Prometheus alerts for the operator (Sentuerk Ugras sugras@itknecht.de)
- 231120f: feat(chart): clamd MaxFileSize from maxScanSize, MaxRecursion configurable (Sentuerk Ugras sugras@itknecht.de)
- c47c50c: feat(chart): clamd MaxFiles from clamd.maxFiles (Sentuerk Ugras sugras@itknecht.de)
- 1aa99ae: feat(chart): distribute YARA rules through the mirror, PUA off (Sentuerk Ugras sugras@itknecht.de)
- 37a4d1f: feat(chart): optional oauth2-proxy login in front of the web UI (Sentuerk Ugras sugras@itknecht.de)
- 6c200bc: feat(chart): trust an internal CA of the OIDC provider, warn against NFS for SQLite (Sentuerk Ugras sugras@itknecht.de)
- a193914: feat(clamd-proxy): rules hash in the VERSION reply (Sentuerk Ugras sugras@itknecht.de)
- 677fd22: feat(cli): scan local images with --input (Sentuerk Ugras sugras@itknecht.de)
- 1dd6855: feat(operator): MalwareIgnore and ClusterMalwareIgnore (Sentuerk Ugras sugras@itknecht.de)
- 0c9ecd1: feat(operator): force a rescan with the meles.io/rescan annotation (Sentuerk Ugras sugras@itknecht.de)
- db1f897: feat(operator): prune reports of workloads without pods (Sentuerk Ugras sugras@itknecht.de)
- 597e8c0: feat(operator): pull private images with the pods' pull secrets (3b) (Sentuerk Ugras sugras@itknecht.de)
- 8b5d372: feat(operator): read pull secrets per namespace on opt-in (Sentuerk Ugras sugras@itknecht.de)
- 180b833: feat(operator): reconcile pods for changed ignore rules with low priority (Sentuerk Ugras sugras@itknecht.de)
- f8eaefc: feat(operator): record the Deployment of a ReplicaSet as workload.parent (Sentuerk Ugras sugras@itknecht.de)
- 3a90208: feat(operator): rescan outdated reports and rewrite deleted ones (Sentuerk Ugras sugras@itknecht.de)
- 973dd1e: feat(operator): scan gate holds new pods until their images are scanned (Sentuerk Ugras sugras@itknecht.de)
- 62fb085: feat(operator): scan in a queue of its own, not in the reconcile loop (Sentuerk Ugras sugras@itknecht.de)
- 31a48ff: feat(scan): signature and sha256 for skipped files, sha256 for findings (Sentuerk Ugras sugras@itknecht.de)
- b79e6fd: feat(selftest): optional YARA check with --yara (Sentuerk Ugras sugras@itknecht.de)
- f589b0f: feat(server): history of the cluster's MalwareReports (Sentuerk Ugras sugras@itknecht.de)
- bca4bbd: feat(server): ignore rules from the UI (Sentuerk Ugras sugras@itknecht.de)
- 4c1b6a9: feat(server): show ignored entries on the report page (Sentuerk Ugras sugras@itknecht.de)
- d324ea7: feat(server): show the operator's MalwareReports on a Cluster page (Sentuerk Ugras sugras@itknecht.de)
- 1957d40: feat(server): workloads per day on the Cluster page (Sentuerk Ugras sugras@itknecht.de)
- 864acee: feat(ui): black and white logo (Sentuerk Ugras sugras@itknecht.de)
- 7fff52e: feat(ui): new badger logo (Sentuerk Ugras sugras@itknecht.de)
- c68b143: feat(ui): theme switch for light and dark mode (Sentuerk Ugras sugras@itknecht.de)
- 0db8c9c: feat: --clamd-timeout, derived from clamd.maxScanTime in the chart (Sentuerk Ugras sugras@itknecht.de)
- 6c2894b: feat: SARIF output (Sentuerk Ugras sugras@itknecht.de)
- 857e70e: feat: add Helm chart (Sentuerk Ugras sugras@itknecht.de)
- 4570f46: feat: add Kubernetes manifests, image build and documentation (Sentuerk Ugras sugras@itknecht.de)
- 5c6c504: feat: add clamd-proxy with TLS, token authentication and command filter (Sentuerk Ugras sugras@itknecht.de)
- b39f2f5: feat: add layer-aware image scan CLI with clamd engine (Sentuerk Ugras sugras@itknecht.de)
- 1ef7b6a: feat: add meles operator writing MalwareReports for all pods (Sentuerk Ugras sugras@itknecht.de)
- 3284d90: feat: add proof-of-concept spike (Sentuerk Ugras sugras@itknecht.de)
- abce6a3: feat: add web UI with scheduled scans, run results and reports (Sentuerk Ugras sugras@itknecht.de)
- 64dd116: feat: default YARA rules with their authors in every finding (Sentuerk Ugras sugras@itknecht.de)
- 9b64243: feat: ignore rules and meles image --ignorefile (Sentuerk Ugras sugras@itknecht.de)
- 6a40328: feat: meles harbor-adapter, Harbor's pluggable scanner API (Sentuerk Ugras sugras@itknecht.de)
- 878432a: feat: name workload, container and image in the Infected alert (Sentuerk Ugras sugras@itknecht.de)
- cba000d: feat: operator status and metrics, shown on the Cluster page (Sentuerk Ugras sugras@itknecht.de)
- 0b89a79: feat: registry mirrors (Sentuerk Ugras sugras@itknecht.de)
- 5958b01: feat: report counts metric and Grafana dashboard for the operator (Sentuerk Ugras sugras@itknecht.de)
- 6a48f2f: feat: separate retry of incomplete scans, clamd MaxScanTime in the chart (Sentuerk Ugras sugras@itknecht.de)
- c97ae3d: feat: stream large files to clamd, allow --max-file-size up to 2047M (Sentuerk Ugras sugras@itknecht.de)
Fixes
- a9f8894: fix(build): use the full image repository with ko --bare (Sentuerk Ugras sugras@itknecht.de)
- 12e8cdf: fix(chart): clamd timeouts outlast MaxScanTime (Sentuerk Ugras sugras@itknecht.de)
- 22ef6f5: fix(chart): wait for the mirror before starting clamd, restart only on config changes (Sentuerk Ugras sugras@itknecht.de)
- ad33086: fix(clamd): retry refused connections for up to 30s (Sentuerk Ugras sugras@itknecht.de)
- c64f613: fix(deploy): let clamd and freshclam log to the console, use traefik ingress (Sentuerk Ugras sugras@itknecht.de)
- 26c6d2e: fix(harbor): complete Harbor's internal registry address (Sentuerk Ugras sugras@itknecht.de)
- 9d261ba: fix(operator): end a forced rescan that fails (Sentuerk Ugras sugras@itknecht.de)
- d612b59: fix(operator): hint at the pull limit, not pull secrets, on HTTP 429 (Sentuerk Ugras sugras@itknecht.de)
- 046dab3: fix(operator): reconcile again quietly when pods of a workload race for its report; retry unresolvable images of held pods soon (Sentuerk Ugras sugras@itknecht.de)
- a4ee48c: fix(server): keep a report's history when its group changes (Sentuerk Ugras sugras@itknecht.de)
- 6066a3b: fix: close ways an infected image could pass as clean (Sentuerk Ugras sugras@itknecht.de)
- 34f647c: fix: lowercase meles in the names of skip signatures (Sentuerk Ugras sugras@itknecht.de)
- 31eaeb9: fix: resume layer downloads that break off (Sentuerk Ugras sugras@itknecht.de)
Other changes
- e668324: chore(chart): use meles image 046dab3 (Sentuerk Ugras sugras@itknecht.de)
- 808440b: chore(chart): use meles image 0b89a79 (Sentuerk Ugras sugras@itknecht.de)
- 14cce2c: chore(chart): use meles image 0c9ecd1 (Sentuerk Ugras sugras@itknecht.de)
- ce78705: chore(chart): use meles image 0db8c9c (Sentuerk Ugras sugras@itknecht.de)
- 54c0120: chore(chart): use meles image 180b833 (Sentuerk Ugras sugras@itknecht.de)
- ec54e1b: chore(chart): use meles image 1ef7b6a (Sentuerk Ugras sugras@itknecht.de)
- cf5eca6: chore(chart): use meles image 231120f (Sentuerk Ugras sugras@itknecht.de)
- bcafe4c: chore(chart): use meles image 26c6d2e (Sentuerk Ugras sugras@itknecht.de)
- 87d2563: chore(chart): use meles image 3a90208 (Sentuerk Ugras sugras@itknecht.de)
- 965eaea: chore(chart): use meles image 4c1b6a9 (Sentuerk Ugras sugras@itknecht.de)
- 8af40ed: chore(chart): use meles image 5958b01 (Sentuerk Ugras sugras@itknecht.de)
- 08ca2f2: chore(chart): use meles image 597e8c0 (Sentuerk Ugras sugras@itknecht.de)
- 8174d4a: chore(chart): use meles image 5c6c504 (...