github cloudfoundry/stratos v5.4.1-dev.3
Stratos v5.4.1-dev.3

pre-release3 hours ago

Breaking Changes

  • API key secrets are now stored hashed instead of in plaintext
    (HMAC-SHA256 peppered with the console encryption key). Existing keys
    are hashed in place on upgrade, so keys already issued keep working.
    Because the hash is keyed with ENCRYPTION_KEY, changing that key now
    invalidates stored API keys — in addition to the stored endpoint tokens
    it already invalidates.

Features

  • The application Variables tab now masks secret-looking values —
    keys matching pass/secret/token/private/key/cred, URLs with
    embedded credentials, and PEM private-key blocks under any
    variable name — in both the variables list and the All
    Variables block. Values appear only on explicit request: a per-row
    Show/Hide toggle in the list, a Show secrets toggle on the block.
    The same value heuristics the Service Keys page already uses; hosts and
    ports in connection URLs stay readable.
  • The diagnostics resource waterfall now draws the document request itself
    as its first row, segmented by phase (stall, DNS, TCP, TLS, server wait,
    download). Previously the document was invisible — it is a navigation
    entry, not a resource entry — so on a high-latency connection the chart
    showed an unexplained void until the HTML arrived. Under the Stratos
    clock the row collapses to just server wait + download, the part the
    app can influence.

Bug Fixes

  • WebSocket upgrades (application SSH and log streaming) now validate the
    request Origin — same-origin, plus any host in ALLOWED_ORIGINS
    instead of accepting connections from any origin, closing a cross-site
    WebSocket hijacking vector.
  • The session cookie is now issued with SameSite=Lax.
  • Jetstream no longer terminates when the Cloud Foundry info request fails
    during SSO auto-connect at login. That one login fails instead of the
    whole process exiting for every user.
  • Proxied requests that time out no longer leak a goroutine and its
    buffered response body per endpoint.
  • The OAuth client secret and the application-SSH one-time code are no
    longer written to the jetstream log.
  • Jetstream now warns at startup when ENCRYPTION_KEY is left at the
    well-known default value shipped in config.example.
  • The UAA token endpoint is now checked at the point the request is made,
    rather than trusted from wherever it was built. It must be an absolute
    http(s) URL with a plain host and path — no user info, query or
    fragment. The first-run setup form supplies this value on an
    unauthenticated request, so an unconfigured console could be pointed at
    an arbitrary URL of a caller's choosing.
  • Signing in no longer flashes the Home page, blanks the console, and
    reloads it. The login click handler and the existing-session check both
    triggered the post-login redirect; the two navigations cancelled each
    other and the loser fell back to a full page reload. The redirect now
    runs once.
  • Jetstream serves its own HTTPS again where it terminates TLS itself.
    Echo v5 resolves a certificate path through a filesystem rooted at the
    working directory, which rejects an absolute path outright, and the
    certificate was still being passed as a path — so no HTTPS listener
    started at all. The Kubernetes chart, and the dev and CI configurations,
    all use path shapes that hit this. Deployments on Cloud Foundry were
    unaffected, since the router terminates TLS there.
  • Helm chart files and chart icons no longer 404 on Kubernetes. File
    serving now goes through the same rooted filesystem, which accepts an
    absolute path only beneath the working directory; the chart sets a cache
    folder outside it, so every chart file and icon answered 404 for a file
    plainly present on disk. Analysis reports and an absolute UI_PATH had
    the same exposure whenever the process was not started from an ancestor
    directory.
  • Jetstream logs through one logger again. Echo v5 logs via log/slog
    and defaults to writing JSON to standard output, which meant its
    messages interleaved with Jetstream's own text-formatted logs on the
    same stream and ignored LOG_LEVEL. Echo's output is now routed into
    the application logger, so format and level apply to everything.
    API request logs keep the format they had under Echo v4 and remain
    gated by LOG_API_REQUESTS; they now also respect LOG_LEVEL.
  • Deployed logs are no longer written with ANSI colour escapes. Colour was
    forced on rather than detected, so every line from a deployed Jetstream
    carried escape codes — visible in cf logs, where nothing is a terminal.
    A developer running the binary in a terminal still gets colour. The
    analysis container had the same problem.
  • Two boot lines reporting the resolved Cloud Foundry paging overrides were
    written before the log handler was installed, so they came out through
    the standard library formatter. Under LOG_TO_JSON a collector got two
    unparseable records on every start. Boot output is JSON all the way down
    now.
  • A LOG_LEVEL typo used to silence the backend almost completely.
    logrus returned its panic level for an unrecognised name and the
    error was discarded, so LOG_LEVEL=inof suppressed nearly every
    message. An unusable value is now reported and the current level
    kept.
  • Under LOG_TO_JSON, the log level line and the API request log each
    emitted a record with a duplicate key, because both passed an
    attribute named for a key slog writes itself. Decoders generally take
    the last occurrence, so an aggregator read the configured level
    string in place of the record's real severity, and the request start
    time in place of the record timestamp.
  • Deploying an application from a private Git repository wrote the
    supplied access token to the debug log. The source information line
    logged the whole client message, whose payload carries the token.
    Only the source type is logged now.
  • Several failures were reported as success or reported without a
    cause: a Helm chart icon whose cache folder could not be created was
    returned as a valid path, a truncated chart archive was served as
    though it had extracted cleanly, an analysis report that failed to
    serialise returned HTTP 200, and both analysis runners logged
    completion before checking whether the run had failed.
  • Two paths that could dereference a nil pointer are fixed: the Helm
    client stored a configuration it had already failed to build, and the
    Kubernetes dashboard proxy used a URL it had failed to parse.
  • Numerous log lines that named the wrong function, shared one message
    between unrelated failures, or discarded the error they were
    reporting now identify what actually happened.
  • The JSON schema form no longer emits a <form> inside a <form>. The
    renderer recurses into itself for nested object schemas and rooted every
    level in a form element, which is invalid HTML — the DOM API builds it
    anyway, and browsers scope submission and reset in ways the markup did
    not intend. Nothing in that template submits, so it is a plain container.
  • Connecting a Kubernetes endpoint through OIDC or a kubeconfig works
    again. RFC 7519 defines the token expiry claim as a number of seconds
    since the epoch; it was being read as an RFC 3339 string, so no
    conformant token could satisfy it and every attempt failed with
    "can not get Access Token expiry time claim".
  • Artifact Hub is available again when it is enabled. The flag was renamed
    from "enabled" to "disabled" when Artifact Hub support landed, but the
    test against it was not inverted, so requests were rejected as disabled
    precisely when the feature was on — which is the default.
  • A Helm release whose manifest contains a malformed custom resource is
    now reported to the console as having manifest errors. That branch
    logged the parse failure but left the flag unset, unlike the branch
    beside it.
  • kube-score analysis jobs are evicted from the job map when they finish.
    The busy flag was cleared for popeye runs and never for kube-score, and
    the cleanup pass skips busy jobs, so the map grew for as long as the
    analysis container ran.
  • Deploying an application no longer panics when a file check fails for
    any reason other than the file being absent — a permission error, a
    symlink loop, or an over-long name left a nil result that was then
    dereferenced.
  • The fallback path for the plugin scripts folder contained a stray
    character, so a layout that keeps the scripts under the plugin directory
    never matched the candidate meant to find it.
  • The endpoint filter on the Applications, Marketplace and Services
    toolbars lists endpoints by name. It was built by walking the endpoint
    list in arrival order, which no query orders, so with more than one
    endpoint of a kind the dropdown showed whatever order the rows came
    back in. "All" stays at the top. The comparator is the one the sibling
    dropdowns on those toolbars already use, so cf10 sorts after cf2.

Maintainability

  • Jetstream now runs on Echo v5. Echo v4 is in security-and-bugfix-only
    maintenance until the end of 2026, and v5 reworked enough of the API —
    a concrete request context, log/slog for logging, a rearranged error
    handler — that the move had to happen in one step across the backend
    and every plugin.
  • Retired four unmaintained or superseded dependencies:
    SermoDigital/jose (no upstream release since 2019) is gone from the
    Kubernetes auth plugin, which used it only to read one claim from a
    token the platform had already issued; satori/go.uuid (abandoned) is
    replaced by google/uuid, which the backend already depended on for
    the same purpose; golang/mock (archived) moves to its successor
    go.uber.org/mock; and gorilla/context, obsolete since Go 1.7, is
    gone along with the middleware that existed only to call it.
  • Dropped the archived AWS SDK v1. It was reachable only through
    aws-iam-authenticator, which has since moved to SDK v2; the Kubernetes
    IAM auth path moves with it.
  • Upgraded Helm to v3.21.4 and the Kubernetes client libraries to v0.36.
    Kubernetes minor releases remove APIs, so these move as a set. This
    also repairs dependency maintenance in the Kubernetes plugin, where
    go mod tidy could not run at all: the previous Helm pulled a kubectl
    that imports an API removed in k8s v0.36.
  • Jetstream now logs entirely through log/slog. Echo v5 had already
    moved to slog, which left the backend running two loggers with two
    formats and two level settings; a bridge kept them on one stream
    during the transition and is now gone. All nine Go modules are
    converted, and no first-party code imports logrus anywhere. Log
    messages are structured records rather than formatted strings, so
    identifiers that used to be interpolated into message text — user,
    endpoint and token GUIDs, org and space, chart and release names —
    are now attributes that can be filtered and correlated. LOG_LEVEL
    and LOG_TO_JSON behave as before, and every level name logrus
    accepted still works, including trace, fatal and panic.
  • Every filesystem operation in the analysis container now re-checks, at
    the point of use, that the path still sits beneath the reports
    directory, resolving any ".." before comparing. The paths were already
    built safely, but the guarantee lived in the constructors: an analyzer
    read the job folder and temporary file names directly, so a later change
    setting either from somewhere else would have reached the disk
    unchallenged. The monocular and Artifact Hub cache paths are built from
    validated segments in one place for the same reason.

Chores

  • Jetstream now builds with Go 1.27. Go 1.27 rejects the invalid hash id
    that SermoDigital/jose registers from an init function, which panics
    before main and crash-loops the binary. The dependency is reached
    through the CF CLI rather than our own code, so it is pinned to a fork
    with that registration removed until the CF CLI moves to a maintained
    JWT library.
  • make check lint runs the Go linters again. golangci-lint supports
    only a Go version at or below the one that built it, so the Go 1.27
    bump left the packaged binary failing before it reached any linter.
    It is now pinned and built from source against the toolchain named in
    go.mod.
  • Frontend dependencies moved to their current releases: Angular and the
    Angular CLI to 22.1.x, marked 16 to 18, js-yaml 4 to 5, sass-loader
    13 to 17 and @playwright/test to 1.62. The Angular devkit packages have
    to move as a set, and @angular-devkit/build-angular had to be carried
    with them by hand: it is deprecated at every published version, and
    Dependabot filters deprecated releases out of the candidate list, so it
    cannot bump that one package while bumping its siblings. Leaving it behind
    resolves two copies of @angular-devkit/architect and the devkit builders
    stop type-checking.
  • Two build scripts imported js-yaml through a default export that
    version 5 no longer provides, and failed at module load.
  • The frontend test matrix in CI listed seven of the eight vitest projects,
    so the cf-autoscaler specs ran locally and never in CI.

Don't miss a new stratos release

NewReleases is sending notifications on new releases.