Obiente blog

Supply-chain review

A security review of SolDevelo's Bitnami replacement images

We found a real vendor, a catalog closely derived from Bitnami, and no malware indicators in the reviewed material. We also found catalog-wide provenance gaps, one published-image compatibility defect, and hundreds of similar pull requests.

15 minute read Research snapshot: August 11, 2026 By Obiente
In this report
  1. Short version
  2. Scope and limits
  3. Catalog inventory
  4. Malware review
  5. Source lineage
  6. Material differences
  7. Distribution security
  8. Published-layer scans
  9. Outreach pattern
  10. For maintainers
  11. Reproduction
  12. Primary sources
  13. Corrections

The short version

The decision in 60 seconds

Verdict

This review found no evidence that the 15 Bitnami-derived SolDevelo image families are malware. That is not enough to trust a moving image tag. We cannot prove that the published Docker Hub bytes match the public source, and the current publications have no discoverable signature, provenance, or SBOM attestation. Do not label the images malware without new evidence, and do not merge or deploy them by mutable tag.

Most important findings

What maintainers should do

  1. Open change: do not merge a moving :latest, major, or minor tag. Make the migration a maintainer-controlled dependency decision.
  2. Already deployed: record the exact digest that was actually pulled before changing anything. Do not assume compromise solely from use of this catalog.
  3. Still evaluating: pin an exact digest, scan that digest under your own policy, and test upgrades, persistence, clustering, backup, restore, and failure modes.
  4. Long-term use: prefer a project-controlled build or request signed releases, an attached SBOM, provenance, immutable tags, and digest-pinned build dependencies.

The Bitnami availability change created a genuine maintenance problem. SolDevelo responded with a commercial maintenance offering, public source, and images in its Docker Hub namespace. A contributor whose profile identifies SolDevelo as the company then opened hundreds of replacement PRs. Those PRs should be understood as vendor outreach, not independent security review.

Catalog reviewed 15 image families, 41 versioned Dockerfiles, 1,110 source and runtime files
Malware indicators None found within the stated static-analysis scope
Current published images 15 current images and 29 Linux platform manifests inspected
Runtime identity All 29 current platform manifests declare UID 1001
Signatures and attestations None discoverable for any current catalog digest
Publication defect Kafka's current manifests mix OCI and Docker media types
Outreach snapshot 425 PRs from one contributor account; 24 were merged

Scope and limits

Every advertised Bitnami-derived image family

We reviewed the complete soldevelo/ source tree at commit 9b956d52042b28afdea2182dbb564562e52f620c: 15 product families, 41 versioned Dockerfiles, and 1,110 files. For the published side, we inspected the current latest digest for every family and all 29 Linux platform manifests those digests referenced. MongoDB was the only current image with no arm64 manifest.

Review scope The review covered 15 image families, 41 versioned Dockerfiles, 1,110 source and runtime files, 15 current image digests, and 29 Linux platform manifests. 15 image families 41 versioned Dockerfiles 1,110 source and runtime files 15 current image digests 29 Linux platform manifests
Scope at the reviewed source revision. Published-image counts refer to the exact current digests recorded on August 11, 2026.

This scope covers all Bitnami-derived image families advertised in the source catalog. It does not cover every historical Docker Hub tag, five unrelated image repositories in the same namespace, or the namespace's Helm chart repositories. A historical tag can have different bytes and must be reviewed by its exact digest.

We did not execute any image. We inspected source, build paths, registry manifests, configuration, and layers statically. Static review can expose suspicious behavior and supply-chain weaknesses; it cannot prove the absence of deliberately concealed behavior or establish runtime safety in every deployment.

Catalog inventory

The exact current digests reviewed

Each family name below links to its reviewed source; each current version links to the corresponding Docker Hub tag record. The full SHA-256 value is the current multi-platform index digest, except MongoDB, where it is the single amd64 manifest digest. These are observations from August 11, 2026, not permanent identifiers for a moving tag.

Family Source lines Current Platforms Reviewed digest
jmx-exporter 1 1.6.0 amd64, arm64 sha256:303cf2c2c7233de4ae7ed1e96fe34b5cc12013f0a6192a20ee98ad57c09b432f
kafka 3.4, 3.7, 3.9, 4.0-4.3 4.3.1 amd64, arm64 sha256:1538bd0f8fe1281df475e57a90b969ab622871415c3d3f75294c8c4d8be10f13
kubectl 1.33, 1.34, 1.36 1.36.3 amd64, arm64 sha256:a308fd7c99d41fd3289be9b25842e4a20bdad6907916ee86b0754b7912f1bad4
mariadb 12.2, 12.3, 13.0 13.0.1 amd64, arm64 sha256:d2ca8842aa050de23a71e65b39031ef426ae04aa2f2314c2ebbc807feb1fcbfe
mongodb 8.2, 8.3 8.3.7 amd64 sha256:3a9d9dbb40da2a0f1d6c10429b2ca42bba8777d2fe5ee211a29cd0067d5a2028
os-shell 12 12 amd64, arm64 sha256:7a1e90bc74f01a61b63c0a46d367f6462340873778af972148d5540ecd4b3b23
pgpool 4 4.7.2 amd64, arm64 sha256:37c172fffdf97b0ad37c191a4afe36763fb1f295ab8e7b0641444e910a9cf37d
postgres-exporter 0 0.20.1 amd64, arm64 sha256:7394dd9119890866414246c2a18b0f61372b6a1463cff71d82622031f1e36022
postgresql 18 18.4.0 amd64, arm64 sha256:83c095844f257ca5595b77faa181c04f1b6ed47cbe5495693d6f93316ca54434
postgresql-repmgr 12-18 18.4.0 amd64, arm64 sha256:19b67ec59ea096d0f6c62006c2260a6da94d4965ab67c2ce4c235a672779b80b
prometheus 3.0, 3.11-3.13 3.13.2 amd64, arm64 sha256:1da85660d87494d31a5c5ebf8657e5f09a0be53e9d3ccc62e1ec7a0a30b7f23e
rabbitmq 4.1, 4.3 4.3.4 amd64, arm64 sha256:eb7d5a79521920007a32ae008efa9d83cbd3d5e18e0e93c9c6c5920b18b0953d
redis 6.2, 7.0, 8.6, 8.8, 8.10 8.10.0 amd64, arm64 sha256:193e9818fabb2a3cfa18872a24c3ec098e3c6f190bfb1da49ab3d5a278c6fc40
schema-registry 8.2, 8.3 8.3.0 amd64, arm64 sha256:7b5006857fd39e88cb02b5625db5bccfdaa93aca225615ce07aba175a92e0064
zookeeper 3.9 3.9.5 amd64, arm64 sha256:27ae279832e8d562901d64b5b9d6f52596483d3f717253e76e16e413d1a7e816

All 29 configurations declared the expected product entrypoint or command and USER 1001. We found no surprise shell, startup URL, privileged user, or unrelated executable in those configurations.

Malware review

No malicious behavior was identified in the reviewed source

We searched all 1,110 files for miner and wallet references, reverse shells, credential theft, SSH persistence, metadata-service access, encoded payload execution, curl | sh patterns, Docker socket access, container-escape mechanisms, and unexplained outbound runtime connections. We then read every match and every source file that differed from its Bitnami counterpart. No malicious behavior was identified.

The stronger-looking matches were inherited, explainable runtime mechanisms: a generic Bitnami service helper can create cron definitions; PostgreSQL's NSS wrapper and MariaDB's allocator can use LD_PRELOAD; and shared shell libraries contain controlled eval calls. The relevant code was identical to historical or current Bitnami source, aside from branding or whitespace in a few files.

We found no active outbound network call in the product runtime scripts. Downloads happen during image builds and resolve to Bitnami's Stacksmith host, Apache's Kafka download host for Kafka 3.9, or Debian package infrastructure through the base image.

"No indicators found" is intentionally narrower than "safe." Because published artifacts are not signed or attested, public source review cannot cryptographically account for every byte served from Docker Hub.

Source lineage

The catalog is substantially derived from Bitnami

We matched 39 of the 41 versioned build roots to historical bitnami/containers revisions with the same component version. Within those matched roots, 754 of 765 scoped files had an upstream counterpart: 657 were byte-identical and 97 differed. Eleven files existed only in the SolDevelo tree. We reviewed the differences, not merely the matching percentage.

Most differences were copyright and vendor labels, blank lines, newer component metadata, or later shared-helper revisions. The upstream-sync workflow and sync script explicitly preserve SolDevelo branding and functional modifications while importing Bitnami changes. That history supports genuine derivation, though it also means custom changes need separate review after each sync.

Exact historical component roots were not found for Kafka 3.9 and Prometheus 3.0. Their Dockerfiles and runtime material were therefore reviewed directly. Neither contained a malware indicator. Kafka 3.9 intentionally substitutes the Apache Kafka distribution; Prometheus 3.0 follows the conventional Bitnami-style download and non-root execution pattern.

Material differences

Four findings maintainers should evaluate

1. Kafka adds Testcontainers compatibility behavior

SolDevelo adds a /etc/kafka/docker/run wrapper that enables a Testcontainers mode, supplies local plaintext listener defaults, and delegates to the Bitnami entrypoint. Its Kafka run script also monitors output in that mode to emit a ready message. This is visible compatibility code, not a malware indicator, but it is a meaningful behavioral difference from a stock Bitnami image.

2. Kafka 3.9 downloads Apache's distribution

The Kafka 3.9 Dockerfile fetches Kafka 3.9.2 and its SHA-512 file from downloads.apache.org, while retaining Bitnami runtime scripts. The checksum detects corruption in transit, but because the payload and checksum come from the same origin it is not independent authentication of that origin.

3. MariaDB 13 relaxes certificate verification for its healthcheck

The MariaDB 13 healthcheck adds --skip-ssl-verify-server-cert when connecting to 0.0.0.0. The comment says this accommodates the image's dynamic self-signed certificate while keeping TLS enabled. The change is scoped to mysqladmin health checks, but operators with strict local certificate requirements should account for it.

4. The current Kafka publication mixes image media types

Kafka's current amd64 and arm64 manifests declare the OCI manifest media type while referencing a Docker v2 configuration media type. Strict clients can reject that mixed representation; in our snapshot, skopeo inspect docker://soldevelo/kafka:latest failed with invalid mixed OCI image with Docker v2s2 config. Manual inspection of the configuration showed the expected Kafka entrypoint, command, revision, and UID 1001. This is a publication compatibility defect, not evidence of malicious content.

current Kafka index
sha256:1538bd0f8fe1281df475e57a90b969ab622871415c3d3f75294c8c4d8be10f13

linux/amd64
sha256:09e7caf6bf605d42245a6bca107f05a5875c1e9476a4e18597e03e173d8f6420

linux/arm64
sha256:2c25bc3a330fa8c399acaa4c708e7a88d38808e1c2b0879b3e95862e695929a6

Distribution security

Traceable labels, but no verifiable build chain

Current image configurations label a public source revision, and their commands are consistent with the corresponding Dockerfiles. That is useful traceability. It is not cryptographic evidence that the registry bytes were produced only by that revision.

  • The publish workflow explicitly sets provenance: false.
  • Registry queries found no OCI referrer, conventional Cosign signature tag, or attestation tag for any of the 15 current catalog digests.
  • Docker Hub's immutable-tag setting is disabled across all 15 catalog repositories, so rolling tags can be replaced.
  • All 41 Dockerfiles start from the mutable bitnami/minideb:bookworm tag rather than a digest.
  • Thirty-eight Dockerfiles run apt-get upgrade, making the result dependent on repository state at build time.
  • Eighteen Dockerfiles use committed checksum material. Twenty-three fetch checksums from the same server as the payload, which does not protect against compromise of that server.
  • The workflow installs the current yq and crane releases without verifying a pinned version or checksum.
  • GitHub Actions are selected by moving version tags instead of immutable action commit digests.

The practical consequence is straightforward: a mutable tag can change without a consumer repository diff, and consumers cannot use a signature or attestation to verify its source and build inputs. Pinning the exact digest prevents silent tag movement, but it does not create missing provenance.

Published-layer scans

Useful negative evidence, not a clean bill of health

We used checksum-verified Trivy 0.72.0 data against the exact current platform digests. The scan enabled Debian OS-package vulnerability analysis and the secret scanner. It deliberately did not download Trivy's roughly 900 MB Java database, so this report does not claim language-library vulnerability coverage.

Every scanned Debian-based image produced OS-package vulnerability findings; severity totals are scanner observations, not proof of exploitability. The scratch-final Prometheus image produced no OS package findings because it has no Debian package database in the final filesystem. No operational secret was identified. Schema Registry produced six identical Stripe publishable-key detections in bundled third-party license text; inspection showed sample text, not an application credential.

Values below are finding occurrences for amd64 / arm64, not deduplicated CVEs. MongoDB has one value because its current publication is amd64-only.

Family Total Critical High Medium Low Unknown Secret hits
jmx-exporter 211 / 211 17 / 17 29 / 29 72 / 72 81 / 81 12 / 12 0 / 0
kafka 288 / 288 17 / 17 41 / 41 96 / 96 122 / 122 12 / 12 0 / 0
kubectl 306 / 306 18 / 18 41 / 41 103 / 103 132 / 132 12 / 12 0 / 0
mariadb 220 / 220 18 / 18 30 / 30 73 / 73 87 / 87 12 / 12 0 / 0
mongodb 267 17 37 87 114 12 0
os-shell 294 / 294 17 / 17 41 / 41 96 / 96 128 / 128 12 / 12 0 / 0
pgpool 254 / 254 18 / 18 32 / 32 73 / 73 119 / 119 12 / 12 0 / 0
postgres-exporter 215 / 215 17 / 17 29 / 29 72 / 72 85 / 85 12 / 12 0 / 0
postgresql 262 / 262 19 / 19 30 / 30 86 / 86 115 / 115 12 / 12 0 / 0
postgresql-repmgr 308 / 308 19 / 19 37 / 37 101 / 101 139 / 139 12 / 12 0 / 0
prometheus 0 / 0 0 / 0 0 / 0 0 / 0 0 / 0 0 / 0 0 / 0
rabbitmq 310 / 310 17 / 17 41 / 41 104 / 104 136 / 136 12 / 12 0 / 0
redis 228 / 228 17 / 17 29 / 29 75 / 75 86 / 86 21 / 21 0 / 0
schema-registry 215 / 215 17 / 17 29 / 29 72 / 72 85 / 85 12 / 12 6 / 6 samples
zookeeper 293 / 293 18 / 18 41 / 41 97 / 97 125 / 125 12 / 12 0 / 0

The August 11 Redis row uses the refreshed Redis 8.10 digests and the vulnerability database available during that scan. The other rows retain the August 2 results because their exact image digests did not change. Architecture pairs generally produced the same totals. The detailed per-family results and scan limitations are retained with the audit notes; maintainers should rescan their exact selected digest under their own severity, exploitability, and exception policy.

Outreach pattern

A product migration promoted at bulk scale

In the August 11 snapshot, GitHub search showed 425 pull requests authored by jkondrat-sd: 368 open, 57 closed, and 24 merged. The 55 PRs created after August 2 show that the outreach continued after publication. The account listed 1,234 public repositories; its 100 most recently updated repositories were all forks. The profile names SolDevelo as the company, while SolDevelo sells maintenance for these images.

Pull-request campaign status Of 425 pull requests, 368 were open, 33 were closed without being merged, and 24 were merged in the August 11, 2026 snapshot.
  • 368 open 86.6%
  • 33 closed, not merged 7.8%
  • 24 merged 5.6%
Mutually exclusive states derived from the 425-PR GitHub search snapshot on August 11, 2026. The 24 merged PRs are part of GitHub's 57 closed results.

Those links make the affiliation discoverable and the vendor itself appears genuine. They also mean the recommendations are interested vendor outreach. Repeated, near-identical pull requests are not a substitute for project-specific compatibility testing, threat modeling, or maintainer consent. GitHub's acceptable-use policy addresses excessive automated bulk activity and bulk promotional distribution; GitHub is the appropriate party to decide whether particular activity crosses its enforcement threshold.

For maintainers

Treat the migration as a dependency change

  1. Do not call these images malware based on the current evidence. Preserve logs and exact digests if separate compromise evidence exists.
  2. Do not accept a moving :latest, major, or minor tag as the only identity of a production artifact.
  3. Prefer an official upstream artifact or a reproducible build in a registry controlled by the consuming project. If selecting SolDevelo, pin the reviewed architecture or index digest.
  4. Test the selected image's configuration, persistence, upgrades, health checks, backup and restore, clustering, and failure modes. Pay particular attention to the documented Kafka and MariaDB differences.
  5. Scan the exact digest with the consuming project's current policy, including language packages where applicable. A scan of today's latest does not describe yesterday's deployment.
  6. Request signed images, an attached SBOM, build provenance, immutable release tags, digest-pinned workflow dependencies, and independently authenticated downloads from any long-term publisher.
  7. If an image has already been deployed, first record its local content digest. Do not assume compromise or rotate secrets solely because it came from this catalog; respond to evidence and exposure.

Reproduction

How to verify the moving parts

The source commit and digests in this report are immutable; campaign counts and registry tags are not. Record the timestamp and resolved digest when repeating the read-only checks.

# Outreach snapshot
gh api -X GET search/issues \
  -f q='type:pr author:jkondrat-sd' --jq '.total_count'

# Public source snapshot
git clone --filter=blob:none https://github.com/SolDevelo/containers.git
git -C containers checkout 9b956d52042b28afdea2182dbb564562e52f620c

# Resolve and inspect a current image without running it
skopeo inspect --raw docker://docker.io/soldevelo/postgresql:latest
skopeo inspect docker://docker.io/soldevelo/postgresql@sha256:83c095844f257ca5595b77faa181c04f1b6ed47cbe5495693d6f93316ca54434

# Query attached OCI artifacts for an exact subject digest
oras discover docker.io/soldevelo/postgresql@sha256:83c095844f257ca5595b77faa181c04f1b6ed47cbe5495693d6f93316ca54434

# Static scan; add the language databases your policy requires
trivy image --scanners vuln,secret \
  docker.io/soldevelo/postgresql@sha256:83c095844f257ca5595b77faa181c04f1b6ed47cbe5495693d6f93316ca54434

Our review additionally walked each Dockerfile's base images, package installation, downloads, checksum sources, copied files, user, entrypoint, and command; compared source blobs across Bitnami history; inspected the build-and-publish workflow; queried Docker Hub repository settings and OCI referrers; and scanned every current platform manifest statically. No container was started.

Primary sources

Evidence and further reading

Corrections and response

This is a dated technical snapshot

Registry contents, pull-request counts, source, and vulnerability data can change. If the publisher, contributor, or another maintainer can provide signatures, provenance, SBOMs, or factual corrections that were unavailable during this review, contact contact@obiente.com. Substantiated errors will be corrected and material updates recorded.