Skip to content

Fix CA-key-in-image (HackerOne #3764027) and root-cron privesc in simplerisk - #169

Merged
jsokol merged 3 commits into
testingfrom
security/hackerone-3764027-docker-ssl-and-cron-privesc
Sep 20, 2026
Merged

jsokol merged 3 commits into
testingfrom
security/hackerone-3764027-docker-ssl-and-cron-privesc

Conversation

@jsokol

@jsokol jsokol commented Sep 20, 2026

Copy link
Copy Markdown
Member

Summary

  • Fixes HackerOne #3764027: simplerisk-minimal baked a CA key + Apache TLS key into the published image layer at build time and installed the CA into the container's trust store. Anyone who docker pulled the image could extract the CA private key and forge certs the container's own outbound HTTPS calls would trust. The CA is removed entirely and the self-signed Apache cert is now generated at container startup (entrypoint.sh), so each deployment gets its own unique key instead of one shared across every pull of a tag.
  • Fixes the same vulnerability class as HackerOne #3761952 (validated/fixed upstream in simplerisk/setup-scripts), found while auditing for it here: the full-stack simplerisk image ran cron/cron.php as root via /etc/cron.d/simplerisk-cron, while /var/www/simplerisk (including cron.php) is chown -R www-data. A web-tier compromise as www-data could overwrite cron.php and escalate to root on the next cron tick. The cron entry now runs as www-data, matching file ownership; cron.php only runs application-level jobs that already execute as www-data under Apache.
  • Confirmed HackerOne #3761952 and #3764025 (both against simplerisk/setup-scripts, not this repo) don't otherwise apply here: simplerisk-minimal's app cron already runs as the non-root simplerisk user, and the only external feed value we consume (download_and_verify_bundle.sh's hash lookup) is strictly regex-validated before use, never interpolated into a shell command.

Test plan

  • shellcheck --severity=error on both entrypoint.sh scripts
  • test_generate_dockerfile.sh regression suite passes for both simplerisk and simplerisk-minimal
  • Built simplerisk-minimal locally; confirmed no CA/cert/key material is present in the image, and that entrypoint.sh generates a fresh self-signed cert on first container startup (idempotent across restarts), and that HTTPS serves correctly (curl -k returns 200)
  • CI: container-validation.yml (builds all 5 variants, Dockle, Grype, generator checks)

🤖 Generated with Claude Code

jsokol and others added 2 commits September 20, 2026 13:38
…ckerOne #3764027)

The Dockerfile generated a CA key/cert and Apache TLS key/cert at build
time, baked both into the published image layer, and installed the CA
into the container's system trust store. Anyone who pulled the image
could extract the CA private key and forge certs for any hostname the
container's own outbound HTTPS calls (e.g. the schema fetch in
entrypoint.sh) would then trust.

Removes the custom CA entirely -- unnecessary, since the non-minimal
simplerisk image self-signs its Apache cert directly without one -- and
moves self-signed cert generation from build time to container startup,
so each deployment gets its own key instead of a key shared by every
pull of the same tag.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
/var/www/simplerisk (including cron/cron.php) is chowned to www-data,
but the cron.d entry executed it as root every minute. Any web-tier
compromise that gets code execution as www-data could overwrite
cron.php and escalate to root on the next cron tick -- the same
CWE-732 privilege-boundary crossing reported and fixed upstream in
simplerisk/setup-scripts as HackerOne #3761952, just baked into this
image's Dockerfile instead of the bare-metal installer script.

cron.php only runs application-level jobs that already execute as
www-data under Apache, so it doesn't need root.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@jsokol
jsokol force-pushed the security/hackerone-3764027-docker-ssl-and-cron-privesc branch from 62e0065 to d6860d5 Compare September 20, 2026 18:38
@jsokol
jsokol changed the base branch from master to testing September 20, 2026 18:38
CVE-2026-19931 and CVE-2026-18924 are the same pre-existing Grype
false positive already documented above (binary classifier reads the
PHP interpreter's embedded version string out of curl.so and reports
it as curl's own version), just newly published CVE IDs against that
same fictitious version. Verified via `grype -o json`: the only match
is /usr/local/lib/php/extensions/.../curl.so; the real Debian curl
package is a separate match Debian's tracker marks "wont-fix", which
--only-fixed already excludes on its own. This was failing
container-validation.yml on all three simplerisk-minimal PHP variants.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@jsokol
jsokol merged commit 7821e22 into testing Sep 20, 2026
7 checks passed
@jsokol
jsokol deleted the security/hackerone-3764027-docker-ssl-and-cron-privesc branch September 20, 2026 19:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant