Thorn Tech Marketing Ad
Skip to main content
Version: 1.3.0

Release Notes

TLDR

Current Version: 1.3.0

Latest Updates (v1.3.0):

  • Marketplace licensing for the pay-as-you-go AWS, Azure, and Google Cloud images — licensed automatically for 10 StorageLink users (administrators not counted); for more users, use the Bring Your Own License (BYOL) listing or the container edition
  • Container edition (Docker Compose, Kubernetes, OpenShift) with product licensing and a self-service 30-day free trial
  • Local File System connections, in-app file previews, seekable and resumable downloads, and a separate Create Folder permission (granted alongside Upload)
  • Uploads stream concurrently in less memory and support files up to each provider's maximum object size
  • Client IP addresses are resolved against trusted proxies (list your load balancer or reverse proxy), and the platform moves to Spring Boot 4.1 / Java 21, with PostgreSQL 18 on single-instance deployments, containers, and AWS high-availability deployments

Recent Major Features:

  • v1.2.1: Security hotfix — Apache Tomcat, Netty, and Bouncy Castle CVE fixes, marketplace images rebaked
  • v1.2.0: Transfer jobs, full bilingual support, tracking metadata, API rate limiting, security hardening
  • v1.1.6: Security fix for CVE-2025-55754, syslog overflow prevention on Azure
  • v1.1.5: Improved transaction management, Ubuntu 24.04
  • v1.1.4: Download multiple files/folders as ZIP, PostgreSQL 16 support

Product: StorageLink by Thorn Technologies — cloud storage gateway for secure file sharing

Version 1.3.0​

Summary​

StorageLink 1.3.0 introduces a containerized distribution of StorageLink with product licensing and a self-service free trial, brings licensing to the AWS, Azure, and GCP marketplace images, adds local file system connections alongside cloud storage, and lets users preview files in the browser without downloading them. Folder creation becomes a permission of its own, client IP addresses are resolved so they can no longer be forged, uploads handle more concurrent transfers and much larger files in less memory, downloads support seeking and resuming via HTTP range requests, and the platform moves to Spring Boot 4, with PostgreSQL 18 on single-instance deployments, the container images, and AWS high-availability deployments.

New Features​

  • Container edition with licensing and free trial — StorageLink is now distributed as container images (backend and UI) in addition to the AWS, Azure, and GCP marketplace VM images, for Docker Compose, Kubernetes, and OpenShift deployments. A deployment generates a stable cluster ID that a license is bound to, and administrators can activate a license, or start a free trial with an email address and a verification code, directly from the admin UI. Until a license or trial is activated, administrators keep full access to configuration and user management, but file transfers (uploads, downloads, and transfer jobs) are blocked for all users. License activation is rate-limited to 5 attempts per 60 seconds, and the admin UI shows a countdown when the limit is reached. For unattended deployments, a license can also be supplied non-interactively via a license file path or environment injection. See the Container Deployment Reference for deployment details.
  • Marketplace licensing for AWS, Azure, and GCP images — VM images published to the AWS, Azure, and GCP marketplace listings (the pay-as-you-go listings, not the Bring Your Own License listings) now carry their license in the image. A marketplace instance confirms its own entitlement automatically with the cloud provider, so there is no license key to enter and no cluster ID to bind: the instance is licensed from first boot. The admin License page shows which marketplace the license came from. Marketplace instances are licensed for 10 StorageLink users; administrators are not counted against that limit. Deployments that need more users use the Bring Your Own License listing, where the license is available in 10-, 100- or 1,000-user tiers, or the container edition. The entitlement check runs in the background and needs no action unless it cannot complete, most often because the instance metadata service has been firewalled off, or on GCP because the instance cannot reach Google's signing keys or has no service account attached. In that case the admin UI explains what is blocked and links to the requirements. See "Marketplace License Network Requirements" in the in-app admin help for the specifics per cloud. See Upgrade notes.
  • Local File System connections — A local directory path (for example an NFS or on-premises mount) can now be used as a storage backend alongside cloud connections, with the same browsing, upload, download, and transfer-job support. When tracking metadata is enabled, the correlation ID, username, and remote address are written to local files as extended attributes, giving local storage the same audit trail as cloud storage; filesystems without extended-attribute support log a warning and continue. The built-in admin help documents the new connection type and explains what each Test Connection check (Connection, Read, Write) validates per provider, with troubleshooting steps, in English and French. An absolute mount path must lie entirely outside the StorageLink application directory: it may not be that directory, a directory containing it, or a directory inside it, and the restriction cannot be sidestepped with a relative path or a symbolic link. This keeps the application's configuration and audit logs from being exposed through the file browser. To keep a mount under the application home, use a relative path instead: it is treated as a managed mount name and resolves inside a mounts directory under the application home.
  • In-app file previews — Files can be previewed in a new browser tab without downloading: images (JPEG, PNG, GIF, WebP, BMP), PDFs, plain text and JSON (plus CSV and Markdown), and common audio and video formats (MP3, WAV, FLAC, M4A, MP4, WebM). Each content-type family has a size cap to keep browser tabs responsive; the caps are stated in the built-in help.
  • Seekable and resumable downloads — Downloads now support HTTP range requests (206 Partial Content): browsers can seek within audio and video without downloading the whole file, playback starts faster, and an interrupted download can resume where it left off. Only the requested bytes are fetched from storage on every provider, including local file system. Multi-file zip downloads ignore range requests, since they are generated as a stream with no fixed length.
  • Downloadable transfer job reports — A CSV report can be downloaded from the Job Details page for a completed transfer job: the job's metadata (operation, source, destination, status, timestamps) plus a per-file breakdown of successes, failures, and skips.
  • SSO-only login — Deployments that use single sign-on exclusively can hide the username/password form on the user login page, so users see only the SSO sign-in buttons. The admin login screen keeps the credentials form so administrators always have a way in, and the form is not reachable through URL manipulation. If no identity provider is configured while the option is enabled, the login screen directs the user to have an administrator configure one. Off by default.
  • Separate permission to create folders — Folder creation is now its own permission, granted separately from Upload. A user can be allowed to upload into existing folders without being able to add new ones, which suits a drop-box arrangement where administrators control the folder layout. The permission also covers folders created as a side effect: uploading a folder from the browser, or dragging in a nested tree, creates folders along the way, so those uploads are refused with a message naming the folder that would have been created. An upload into folders that already exist is unaffected, and an upload that lands some files in existing folders and others in new ones completes the part it is allowed to. Renaming or copying a folder requires the permission as well, since both change the folder layout; renaming a file does not. Create Folder narrows Upload rather than replacing it: a user needs both, and Create Folder without Upload grants nothing. Existing users keep the access they have: on upgrade every user who can upload can also create folders, matching the behavior of previous releases, and the new permission has to be removed deliberately.

Improvements to existing features​

  • Upload capacity and large files — Uploads now stream continuously from the browser to cloud storage, with chunks spooled to disk and uploaded concurrently; Azure Blob, Azure File Share, and Google Cloud Storage previously uploaded one block at a time. Because chunks wait on disk instead of in memory, each concurrent upload costs roughly 20-25% less memory, and overload degrades instead of crashing the server: in our load tests on identical hardware, v1.2.1 failed unrecoverably (out of memory) at around 35 concurrent uploads, while 1.3.0 completed 200 concurrent uploads with zero failures, which is where the test stopped, not where the server did. A single upload's transfer rate is unchanged. Maximum file size no longer trades against memory: v1.2.1 buffered every upload in fixed 8 MiB parts with no setting to raise them, which capped an S3 upload at 78 GiB, and in our tests an 85 GiB upload failed at that boundary and ran the server out of memory; 1.3.0 plans part sizes from the file size the browser declares, so uploads succeed up to each provider's maximum object size (5 TB on S3), and the same 85 GiB upload completed at the same transfer rate. An upload that would exceed the provider maximum fails immediately with a clear message instead of hours into the transfer. Chunk size and concurrency are configurable globally and per provider; the chunk spool directory is configurable (point it at a tmpfs mount for a RAM-backed spool), and a startup check refuses to start (configurable down to a warning) when the spool volume is low on space.
  • Upload failure handling and retries — An individual upload part is retried when the storage provider closes the connection mid-request, on every backend, so a transient network fault costs one retry cycle instead of the whole file. Upload failures are also classified before they reach the browser: a permanent failure (revoked or expired credentials, a policy denial, a destination the account cannot write to) is reported as permanent, while a transient failure is reported as retryable. Files that failed can be retried directly from the upload progress card without re-selecting them; they are re-queued to the folder they originally targeted, even if you have browsed elsewhere since, and a file whose failure retrying cannot fix is not offered. Uploading many files at once no longer performs a storage metadata read per file to build the audit record. On AWS S3 the number of retry cycles per part is configurable; on Azure Blob, Azure File Share, and Google Cloud Storage the equivalent retry is built in and not currently configurable.
  • Stalled-download reclamation — A download that stops making progress for 60 seconds (for example a paused or dead client) no longer holds a server streaming thread indefinitely; slow but progressing downloads are unaffected. The shared streaming executor for downloads, previews, and zips now has a fixed concurrency ceiling, so one burst cannot grow threads without bound.
  • Container logs on standard output — Container logs are emitted as structured JSON on standard output, each line tagged application, audit, or license-audit so a log collector can route the streams separately. The backend container writes no log files, so it needs no writable volume for them; /tmp is the only writable path it needs under Kubernetes readOnlyRootFilesystem. VM deployments continue to write rotated log files to disk in the same locations. License events (activation, replacement, expiry, binding, import caps, and rate limiting) now write to a dedicated license-audit stream instead of sharing the file-object access audit log, so compliance records and user file activity no longer interleave.
  • Health and readiness endpoint — StorageLink exposes a health check endpoint with Kubernetes-style liveness and readiness probes (readiness includes the database check), for load balancers and container orchestration. Health details are visible only to authorized administrators.
  • "Server starting" page auto-loads — If StorageLink is opened while the server is still starting, the page now checks readiness automatically and loads the sign-in page as soon as the server is up.
  • Administrators can see their resolved client address — An administrator sees the client address their own session resolved to, displayed as Seen as <address> in the top navigation bar. Behind a load balancer this is how to confirm the trusted-proxy configuration is right: the address shown is the one that will be written to audit records and counted for login lockout. See Upgrade notes.
  • File type icons — The file browser shows distinct icons per file type (images, documents, archives, code, and more), making folder contents easier to scan.
  • Create folders from the folder picker — When choosing a folder for a transfer job or a user's home directory, a new folder can be created right inside the picker and is selected automatically.
  • Clearer SSO failure diagnostics — When single sign-on fails because the identity provider's token does not match the configured Client ID, the application log now names the configured Client ID and issuer and points at the most common cause (a mistyped Client ID), so administrators can self-diagnose.
  • Accessible forms — Form labels across the application's most-used form components are now proper HTML labels, so screen readers announce fields correctly and clicking a label focuses its input; duplicate form field IDs on the Add Job form were fixed as part of this work.
  • Corrected admin labels and help topics — The Google Cloud connection dropdown reads "Map to Google Cloud Storage" rather than naming a bucket; the hierarchical-namespace help describes what the connection test shows; the Write Permission check help now says it verifies create only; the Local File System mount-path field states the directory ownership requirement without opening the help panel; and Azure File Share managed-identity setup documents the privileged file-data roles it requires. English and French throughout.
  • Platform upgrades — StorageLink now runs on Spring Boot 4.1 / Java 21, keeping the platform on fully supported foundations. PostgreSQL 18 ships on single-instance deployments, the container images, and AWS high-availability deployments; Azure and GCP high-availability templates continue to provision PostgreSQL 16. The end-of-life AWS SDK for Java v1 is removed in favor of SDK v2 exclusively. See Upgrade notes.

Security hardening​

  • Clickjacking protection and iframe embedding — StorageLink now sends a Content-Security-Policy frame-ancestors header that prevents other websites from embedding it in a frame, defaulting to 'self'. Deployments that intentionally embed StorageLink can configure an allowlist of embedding origins via the FRAME_ANCESTORS environment variable (container) or launch configuration (VM). The previous frame-ancestors directive in a CSP meta tag was ignored by browsers per the CSP specification, so this is the first effective enforcement.
  • Non-root containers — Both StorageLink containers run as a non-root user out of the box, pass the Kubernetes restricted pod security standard, and support OpenShift's arbitrary-UID model and read-only root filesystems, with no init-container workarounds. Only non-privileged ports are bound inside the container; externally mapped ports are unchanged. TLS material is delivered as mounted files rather than environment-variable PEMs.
  • Cloud path visibility — The file browser's cloud-location details (provider and storage path) are now shown only to administrators.
  • Client IP addresses can no longer be forged — Audit records and the failed-login lockout previously took the client address from the first entry of the X-Forwarded-For header, which any client can set. The address is now resolved by walking that header from the right and stopping at the first hop that is not a trusted proxy, so a forged value is ignored. Trusted proxies are listed in the new security.client-ip.trusted-proxies property, which defaults to loopback only; deployments behind a load balancer that adds forwarded headers must list it. See Upgrade notes. Address storage also widened to accept IPv6.
  • Login lockout is keyed on username and address together — Repeated failures now block that combination rather than the address alone, so one user's failures behind a shared corporate NAT no longer lock out colleagues, and a forged address cannot deny service to an unrelated client. Not yet effective behind Azure Application Gateway: it forwards the client's address with a source port attached, and that port changes on every request, so each attempt looks like a different address and the count never accumulates. Audit records behind Application Gateway carry the port alongside the address for the same reason, which also prevents a SIEM from correlating events by client IP. Other load balancers we have checked, including AWS ALB and Cloudflare, forward a plain address and are unaffected. Handling the ported form is planned for a later release.
  • Out-of-range login-lockout settings are refused at startup — Setting security.max-login-failed-attempts to 0 made every login fail, correct passwords included, and setting security.failed-login-timeout-seconds to 0 or below silently disabled the lockout with nothing raised and nothing logged. Neither value has a defensible meaning, so both are now rejected at startup with a message naming the property. See Upgrade notes.
  • Dependency CVE sweep — The shipped backend image was re-scanned before release and reports no high or critical severity findings in its dependencies.

Bug fixes​

  • An upload interrupted mid-transfer (a dropped connection, a closed browser tab) no longer leaves partial data at the destination. On Azure File Share an interrupted overwrite previously replaced the original file with a truncated one that could not be recovered. Every backend now publishes an upload in a single final step, once all declared bytes have arrived, so a failure before that point leaves an existing file exactly as it was and creates no partial object. The same guarantee applies to transfer-job copies and moves.
  • With upload timestamp preservation enabled, Azure File Share now stores the modification time the client reports instead of the time of the upload; the setting previously had no effect on that provider, and nothing in the log said so. Local File System connections honor the setting as well.
  • A move whose source deletion appears to fail no longer destroys the file. A move copies to the destination and then deletes the source; when that delete reported a failure even though the source was already gone, the cleanup removed the destination, which was the only remaining copy. StorageLink now re-checks the source directly, retrying the delete once, before deciding: a source confirmed still present has its destination copy removed and the failure reported, and a source whose state cannot be determined keeps both copies and reports an error naming each path.
  • Azure File Share folders are listed as folders again. Every directory in a listing was shown as a file, which also made it impossible to open, since the browser refuses to list something it has been told is not a directory.
  • Renaming or moving an Azure File Share item whose name contains % or # no longer acts on a different item. Both characters carry meaning in the URL that names the rename source, so a request could resolve to a neighboring item and report success: with sibling folders report and report#final, renaming report#final moved report instead. Where no such neighbor existed, the rename failed and fell back to copying and deleting, which is slower and not atomic.
  • A failed single sign-on now shows the reason. The message the server sends back after an SSO failure, including an account that is disabled, locked, or expired, was discarded before it could be displayed, so the browser returned to the sign-in screen with no indication of what went wrong.
  • Uploading a file whose name contains a + no longer renames it (report+v2.txt was stored as report v2.txt), and a name containing a stray % now returns a clear validation error instead of a server error. Upload file-type restrictions are applied to the real file name, so a file whose extension was encoded by the client is no longer refused.
  • Testing a connection to a bucket or container governed by a retention or immutability policy no longer reports it as not writable. The write check required its probe object to be deletable again, which such a policy refuses, so a destination that uploads succeed against was reported as unwritable. A probe object that cannot be removed is logged with its path, since it remains in your storage until the policy allows its deletion.
  • On the Azure File Share connection form, saving with the Enter key no longer reports "Share name cannot be blank" while the Share Name field is visibly filled in; the stored connection URL was only rebuilt when a field lost focus, which submitting with Enter skips. Typing a % into the URL field also no longer breaks the form.
  • Downloading a file whose name contains non-ASCII characters (for example default macOS screenshot names, which include a narrow no-break space) now saves with its correct original filename; previously the browser fell back to a name derived from the URL.
  • Text throughout the interface now renders in the font weights the theme asks for. Only the regular weight of Montserrat and Raleway was shipped, so the browser synthesized the other weights it needed, rendering text heavier and wider than the real fonts; this had been the case since the theming work in 2023.
  • Fixed file-browser tooltip problems: double-clicking a file name to select text no longer starts an unwanted download, and the tooltip no longer blocks clicking the row above it.
  • The web interface no longer gets stuck endlessly reloading at startup when the backend rejects all requests as unauthorized (for example behind a misconfigured proxy); it lands on a stable sign-in screen instead.
  • The "Inherited" checkbox no longer occasionally appears on root-folder user permissions, where there is nothing to inherit from.
  • Creating a user with a blank username now shows a single clear validation message instead of two overlapping messages run together, and validator messages are localized.
  • Closed a resource leak in the AWS KMS client used when listing encryption keys during cloud connection setup.
  • During first launch, creating the initial administrator account could leave the form with nothing shown on screen when the server rejected the request without a field-level error, for example when the initial cloud connection could not be configured. The server's explanation is now displayed. Azure File Share auto-create and credential validation during first-run setup were fixed as part of the same work.
  • Saving an identity provider with a missing or unrecognized type now returns a clear validation message instead of a generic failure.

Upgrade notes​

Action required​

Each of these can break or silently change a deployment that upgrades without acting on it. Each one leads with who is affected.

  • If you set a login-lockout property to zero, the server will not start until the value is corrected — security.max-login-failed-attempts and security.failed-login-timeout-seconds are now rejected below 1 at startup, with a message naming the offending property. Setting the timeout to 0 used to turn the lockout off silently, reporting nothing. Set a real timeout, or leave the default of 3600; there is no supported way to disable the lockout. A deployment that set the attempt limit to 0 could not log anyone in to begin with.
  • If your deployment has more than 10 users, plan before moving to a 1.3.0 marketplace image — Instances launched from a 1.3.0 AWS, Azure, or GCP marketplace image (the pay-as-you-go listing, not the Bring Your Own License listing) are licensed for 10 StorageLink users; marketplace images before 1.3.0 imposed no user limit. The limit applies to creating users (existing users keep working), so a deployment already above 10 continues to serve every one of them but cannot add or replace a user. Restoring a backup that contains more than 10 users imports the first 10 and reports each remaining user as skipped, naming it. You first encounter the limit when restoring a backup onto a newly launched 1.3.0 marketplace instance (see Upgrade Process for StorageLink). Contact sales@thorntech.com to move to a Bring Your Own License deployment with a license tier that covers your user count (10, 100 or 1,000 users), and see StorageLink Standard vs BYOL for the steps.
  • If StorageLink sits behind your load balancer, reverse proxy, or CDN, list it as a trusted proxy, or every user is recorded under the load balancer's address — Client addresses are now resolved against security.client-ip.trusted-proxies, which defaults to loopback only. Add the CIDR range your proxy sends traffic from (an Application Gateway, ALB, or Cloudflare, for example), using LOAD_BALANCER_ADDRESSES in the launch configuration on VM images or SECURITY_CLIENTIP_TRUSTEDPROXIES on containers. Until you do, nothing fails and no error is shown: logins, downloads and previews all keep working, but audit records and login rate limiting attribute every user to the load balancer's own address instead of their own. The admin's own resolved address is displayed in the top navigation bar, which is the quickest way to confirm the setting is right. Deployments where StorageLink is reached directly need no change. One exception: container deployments that set EXTERNAL_TLS_TERMINATION replace the forwarded chain with the address of the system connecting to them, so on those the trusted-proxy setting has no effect and the terminator's address is recorded regardless. Support for reading the original client address in that configuration is planned for a later release.
  • If you tuned S3 upload concurrency, move the value: the property was renamed and the old name is silently ignored — features.file-system.s3-max-concurrency is replaced by features.file-system.aws-s3.http-max-concurrency. The old key is no longer read, so a value left under it falls back to the derived default. (features.file-system.azure.max-concurrency is unchanged.)
  • If API or scripted clients form-encode upload file names, update them to URI encoding — The multipart filename on the upload endpoint is now decoded with URI rules rather than HTML-form rules, one path segment at a time, so a bare + is a literal plus instead of a space. Browser uploads are unaffected. Clients that built the name with form-style encoding (Java's URLEncoder.encode, Python's urllib.parse.quote_plus) must switch to URI-component encoding (encodeURIComponent, Python's urllib.parse.quote); until they do, a space sent as + is stored as a literal + and the upload still succeeds, so the only symptom is the stored name.
  • If you upgrade a VM instance in place, update its log-agent configuration to pick up the new license-audit log — Instances launched from a 1.3.0 image forward /opt/swiftgw/log/license-audit-*.log to CloudWatch or Google Cloud Logging alongside the existing application and audit streams; an instance upgraded in place writes the file locally but does not forward it until its log-agent configuration is updated. See the in-place upgrade guide.

Other upgrade notes​

  • PostgreSQL 16 → 18 — A single-instance deployment keeps its database on the instance. Deploying a new 1.3.0 instance and importing your backup arrives on PostgreSQL 18 (supported through November 2030) with no migration to perform. An instance upgraded in place with the in-place upgrade script keeps the PostgreSQL version it already has, which remains supported; StorageLink enforces no minimum version. Only a high-availability deployment has a standalone database that survives the upgrade: AWS templates now provision PostgreSQL 18, while the Azure and GCP templates continue to provision PostgreSQL 16, which remains supported; StorageLink enforces no minimum version. Operators who choose to upgrade a standalone database in place with pg_upgrade should note: PostgreSQL 18 enables data checksums by default (pass --no-data-checksums if the old cluster was initialized without them), and roles with MD5-hashed passwords emit deprecation warnings (re-hash as SCRAM). The bundled JDBC driver handles both authentication schemes transparently.
  • VM image naming — Published VM image names now use the storagelink- prefix instead of swiftgw-.

New Application Properties​

Upload tuning (features.file-system.upload.*)​

PropertyDefaultDescription
features.file-system.upload.chunk-size-mb8Size of each upload chunk in MB.
features.file-system.upload.max-concurrency4Chunks uploaded to cloud storage concurrently per file.
features.file-system.upload.buffer-multiplier2Chunk buffers spooled ahead of the uploads in flight.
features.file-system.upload.temp-dirJava temp dirDirectory where upload chunks are spooled. Point at a tmpfs mount for a RAM-backed spool.
features.file-system.upload.fail-fast-on-low-disktrueRefuse to start when the spool directory is low on space; false downgrades the check to a warning.
features.file-system.azure-file-share.upload-chunk-size-mb4Azure File Share upload chunk size in MB.

Cloud client HTTP timeouts and retries (optional; defaults shown)​

AWS S3 (features.file-system.aws-s3.*):

PropertyDefaultDescription
http-write-timeout-seconds0 (disabled)Per-write socket timeout for the S3 client.
http-read-timeout-seconds0 (disabled)Per-read socket timeout for the S3 client.
http-connection-acquisition-timeout-seconds120Maximum wait to lease a pooled connection.
http-connection-time-to-live-seconds300Maximum lifetime of a pooled connection.
http-connection-timeout-seconds300TCP connect timeout.
http-connection-max-idle-time-seconds300Idle time before a pooled connection is discarded.
http-max-concurrencyderivedMaximum concurrent HTTP connections; replaces features.file-system.s3-max-concurrency.
metadata-timeout-seconds30Time budget for metadata calls.
data-timeout-seconds300Time budget for data transfer calls.
upload-part-retry-attempts1Application-level retry cycles per upload part, on top of the SDK's own attempts; 0 disables.

Azure Blob (features.file-system.azure.*) and Azure File Share (features.file-system.azure-file-share.*):

PropertyDefaultDescription
http-write-timeout-seconds0 (disabled)Per-write socket timeout.
http-read-timeout-seconds0 (disabled)Per-read socket timeout.
credential-max-retry1Credential acquisition retry attempts.
credential-retry-timeout-seconds5Timeout per credential retry attempt.
storage-retry-count5Storage operation retry attempts.

Streaming executor and stalled-download reclamation​

PropertyDefaultDescription
spring.task.execution.pool.core-size32Fixed concurrency ceiling for the shared streaming executor (downloads, previews, zips).
spring.task.execution.pool.max-size32Pinned equal to core-size so the ceiling is real.
spring.task.execution.pool.allow-core-thread-timeouttrueIdle threads are reaped; the pool shrinks when quiet.
server.tomcat.connection-timeout60000Socket write timeout (ms): a response write making no progress this long is aborted and its thread reclaimed.

Health endpoint​

PropertyDefaultDescription
management.endpoint.health.probes.enabledtrueKubernetes-style liveness/readiness probe groups.
management.endpoint.health.group.readiness.includereadinessState,dbReadiness includes the database check.
management.endpoint.health.show-detailswhen_authorizedHealth details only for authorized administrators.
management.endpoint.health.rolesADMIN,ROLE_ADMINRoles allowed to see health details.

Login​

PropertyDefaultDescription
features.api.sso-only-login-enabledfalseHide the username/password form on the user login page, leaving only SSO sign-in.
security.failed-login-purge-rate-ms900000How often recorded failed-login attempts that are no longer counted are purged.

Licensing​

PropertyDefaultDescription
license.rate-limit.max-attempts5License activation attempts allowed per window.
license.rate-limit.window-seconds60Activation rate-limit window.
license.auto-activate.enabledtrueAutomatically activate a configured license at startup.
license.auto-activate.loser-wait15sHow long a contending cluster instance waits for the winning instance's activation to commit.
license.auto-activate.loser-poll-step500msPoll interval while waiting for the winning instance.
license.sync.poll-interval-ms60000How often instances re-read the stored license.
license.sync.poll-initial-delay-ms60000Delay before the first license re-read.
license.license-file-pathunsetOptional file-based license source.
license.attestation.recheck-interval-ms86400000How often a marketplace instance re-confirms its entitlement in steady state.
license.attestation.recheck-initial-delay-ms300000Delay before the first re-confirmation after startup.
license.attestation.retry-tick-ms60000Retry tick while no successful attestation has landed; backs off 1m → 5m → 30m.
lars.base-urlhttps://licensing.thorntech.comLicense activation server.
lars.connect-timeout5sActivation connect timeout.
lars.read-timeout7sActivation read timeout.

Client address and reverse proxy URL rebuilding​

PropertyDefaultDescription
server.forward-headers-strategynoneWas framework in 1.2.1. Any other value re-enables Spring's own forwarded-header handling, which trusts the first X-Forwarded-For entry from any client and overrides the trusted-proxy resolution below. Changing it is logged as an error at startup.
security.client-ip.trusted-proxies127.0.0.0/8,::1/128Comma-separated CIDR ranges and bare IP addresses whose forwarded headers are trusted when resolving the client address. DNS names are not accepted; supply the CIDR of the subnet a load balancer runs in. Unusable entries are ignored with an error rather than preventing startup.
security.redirect.base-pathbackend/Path prefix the reverse proxy strips before the backend.

Deployment environment variables​

VariableDefaultDescription
FRAME_ANCESTORS'self'Content-Security-Policy frame-ancestors allowlist; set to permit an iframe embedder, e.g. 'self' https://embedder.example.
LOAD_BALANCER_ADDRESSESunsetVM images: CIDR ranges of your load balancer or reverse proxy, trusted to assert X-Forwarded-For.
SECURITY_CLIENTIP_TRUSTEDPROXIESunsetContainers: the same trusted-proxy list.

Version 1.2.1​

Summary​

StorageLink 1.2.1 is a security hotfix off v1.2.0 that updates third-party dependencies (Apache Tomcat, Netty, Bouncy Castle) to address recently disclosed CVEs and rebakes the marketplace images to pick up the latest Linux kernel security patches. There are no application behavior changes and no breaking API changes; this release is a drop-in replacement for 1.2.0.

Security hardening​

  • Apache Tomcat upgraded to 10.1.55 — addresses CVE-2026-41293 (HTTP/2 HPACK header validation), CVE-2026-43512 (DIGEST authenticator authenticates any unknown user), and CVE-2026-43515 (improper HTTP-method enforcement on web-resource constraints). None of these is exploitable in StorageLink — nginx terminates HTTP/2 at the edge and proxies to Tomcat over HTTP/1.1, embedded Tomcat does not enable HTTP/2, and StorageLink uses JWT authentication rather than DIGEST — but the upgrade removes the affected versions.
  • Netty codecs pinned to 4.1.133.Final — addresses CVE-2026-42579 (DNS codec RFC 1035 validation bypass), CVE-2026-42581 (HTTP codec request smuggling on HTTP/1.0), and CVE-2026-42584 (HTTP client codec response desynchronization). None has a practical exploitation path in StorageLink: Tomcat handles inbound HTTP traffic, and Netty is used only as an outbound client by the AWS SDK to AWS service endpoints.
  • Bouncy Castle upgraded to 1.84 — addresses CVE-2026-0636 (LDAP injection in LDAPStoreHelper) by upgrading bcprov-jdk18on and bcpkix-jdk18on.
  • Linux kernel patches via image rebake — AWS, Azure, and GCP marketplace images are rebaked from updated base images to pick up the latest kernel CVE fixes, including CVE-2026-23112 (nvmet-tcp) and CVE-2026-31431 (algif_aead local privilege escalation). No application change is required to receive these fixes — deploy a fresh 1.2.1 instance from the marketplace to inherit the patched kernel.

Version 1.2.0​

Summary​

StorageLink 1.2.0 introduces transfer jobs for copying and moving files between folders, adds full bilingual (English/French) support throughout the application, and includes new admin tools for managing identity providers and improved visual indicators for cloud-connected folders.

New Features​

  • Transfer jobs (copy and move) — Users can now copy, move, or rename files and entire folder trees directly within the StorageLink portal. Jobs run in the background so users can continue working while transfers complete. A new Jobs page shows all submitted jobs with real-time progress tracking, transfer rates, and status updates. For directory operations, each file is tracked individually as a child job. Jobs can be canceled at any time, and failed operations are automatically retried up to three times before reporting an error. Completed job records are retained for one year before being automatically cleaned up.
  • Bilingual support — Full English and French language support across the admin portal, end-user file browser, and help documentation. The application automatically detects the user's browser language, and users can switch languages manually at any time.
  • Admin language settings — Administrators can configure which languages are available to users and set a default language for the application. When only one language is configured, the language selector is hidden automatically.
  • Configurable OIDC prompt parameter — Administrators can configure the OIDC prompt parameter on each identity provider to control SSO login behavior (e.g., force re-authentication or account selection). The recommended value is auto-suggested for known providers like Google and Microsoft.
  • Identity provider credential error alerts — When SSO credentials expire or become invalid, administrators now see an error indicator on the Identity Provider list and a detailed message on the edit form. End users see a clear error message instead of a generic login failure.
  • Cloud provider folder badges — Cloud-connected folders now display a small provider icon (AWS, Azure, or GCP) on the folder badge, with a tooltip showing the connection name on hover.
  • Tracking metadata — Uploaded files can now carry tracking metadata (correlation ID, username, and remote address) written directly to cloud object metadata on S3, Azure Blob, Azure File Share, and GCP. This enables tracing individual file operations back to the user and session that performed them. Tracking metadata is preserved through copy/move operations and is visible to admin users in the file detail API response. Each metadata field can be independently enabled via application properties. Correlation IDs are also propagated to audit log entries.
  • API rate limiting — Per-user API rate limiting protects against abuse and runaway automation. Authenticated users are limited to a configurable number of requests per second. Exceeding the limit returns HTTP 429 with a Retry-After header. Unauthenticated requests are not rate-limited. Set to 0 to disable.

Improvements to existing features​

  • Contextual help documentation is now automatically displayed on form pages at larger screen sizes
  • Backup import now supports single-click import and drag-and-drop for backup files
  • An audit log entry is now recorded when a file upload begins, in addition to the existing entry when it completes
  • File sizes, dates, and content type descriptions are now displayed in the user's selected language
  • SSO error messages are now displayed in the user's configured language instead of the server's locale
  • Improved retry handling for Google Cloud Storage operations
  • Improved cloud storage connection pool management for higher throughput during concurrent transfers
  • AWS S3 connectivity test now validates KMS key accessibility and enabled status when SSE-KMS encryption is configured, and verifies kms:GenerateDataKey and kms:Decrypt permissions via a write-then-read test
  • File upload success and error messages are now translated into all supported languages

Security hardening​

  • Content Security Policy — Added a CSP meta tag to the admin UI restricting script sources, frame ancestors, and other resource origins
  • Referrer-Policy header — Added Strict-Origin-When-Cross-Origin referrer policy to API responses
  • Configurable CORS origin — CORS allowed origin is now configurable via application properties instead of permitting all origins unconditionally
  • Exception message sanitization — API error responses no longer expose raw exception messages for DataIntegrityViolationException, BadCredentialsException, JwtException, IOException, and NotFoundException. Messages are replaced with generic i18n-safe strings to prevent leaking database schema or internal details
  • Internationalized error messages — Hardcoded English exception messages throughout the backend are replaced with MessageService calls, supporting English and French locales
  • Azure connectivity validation — Azure Blob and File Share connectivity tests now validate container/share names before attempting a connection
  • Landing page script removal — Replaced Vue.js CDN dependency in the landing page with vanilla JavaScript, eliminating an external script dependency
  • Dependency vulnerability fixes — Upgraded flatted to 3.4.2 (CVE-2026-32141, CVE-2026-33228) and cloud-sql-proxy now auto-upgrades to the latest v2.x at image build time (CVE-2026-33186)

Bug fixes​

  • Fixed an issue where password validation requirements were not displayed when the application is deployed behind a Web Application Firewall (WAF)
  • Fixed an issue where the root folder's cloud provider could not be changed after the initial automatic selection
  • Fixed Google Cloud Operations logging severity levels and timestamp formatting
  • Fixed Azure container name validation to allow names that start with numbers
  • Fixed a connection leak in S3 cloud storage clients during transfer operations
  • Fixed a streaming deadlock that could occur during large S3 file transfers
  • Fixed optimistic lock contention when multiple transfer jobs updated progress simultaneously
  • Suppressed the web server version from HTTP response headers
  • Fixed OIDC login failure when identity providers return custom numeric claims (e.g., auth_time as Long) that were rejected by the Jackson deserialization allowlist
  • Fixed leading and trailing whitespace in cloud connection base prefix being silently accepted, which caused path resolution failures
  • Fixed a console error triggered by an expected 404 response when checking the admin configuration endpoint during authentication
  • Fixed Select N+1 query performance issues in user and folder domain queries by adding @EntityGraph annotations and scalar queries
  • Upgraded Spring Boot from 3.5.7 to 3.5.11 and aligned Jackson dependency versions to resolve CVE findings
  • Fixed unclosed streams in backup import, theme upload, and Azure blob paging
  • Fixed HttpURLConnection leak in Azure IMDS metadata queries
  • Fixed GCP Storage clients not being closed on application shutdown — clients are now cached per connection and properly closed by factory shutdown
  • Fixed uncached GCP Storage clients leaking during test-connectivity flow
  • Fixed GCP cache eviction race condition on connection delete
  • Fixed S3 batch delete errors being silently ignored — now logged at WARN level

New Application Properties​

API (features.api.*)​

PropertyDefaultDescription
cors-allowed-origin-pattern*CORS allowed origin pattern. Restrict to a specific origin for security-conscious deployments.
api-rate-limit-per-second200Maximum API requests per second per authenticated user. Set to 0 to disable.

Tracking Metadata (features.file-system.metadata.*)​

PropertyDefaultDescription
enable-correlation-idfalseWrite a unique correlation ID (UUID) to each uploaded file's cloud metadata.
enable-usernamefalseWrite the authenticated username to each uploaded file's cloud metadata.
enable-remote-addressfalseWrite the client's remote IP address to each uploaded file's cloud metadata.

Transfer Jobs (features.transfer-jobs.*)​

PropertyDefaultDescription
worker-thread-count10Number of Quartz worker threads for executing transfer jobs concurrently. Also controls the default cloud client HTTP connection pool size (20 × this value). Requires restart.
cleanup-interval-hours6How often the cleanup job runs to remove expired job records.
completed-job-retention-days365Number of days to retain completed job records before automatic cleanup.
orphaned-job-retention-days1Number of days to retain orphaned (stalled) jobs in PENDING or RUNNING status before cleanup.
max-retry-count3Maximum number of automatic retry attempts for failed transfer operations.
retry-backoff-millis25Delay in milliseconds before each retry attempt.
transfer-operation-max-retries2Maximum retries for individual file transfer operations (copy/move).
progress-min-bytes-delta262144Minimum bytes transferred before a progress update is emitted (256 KiB).
progress-min-interval-nanos250000000Minimum time between progress updates in nanoseconds (250 ms).

Cloud Storage Concurrency (features.file-system.*)​

PropertyDefaultDescription
s3-max-concurrency20 × worker-thread-count (minimum 500)Maximum concurrent HTTP connections in the S3 async client pool. Values below the minimum are automatically raised with a warning.
azure.max-concurrency20 × worker-thread-count (minimum 500)Maximum concurrent HTTP connections for Azure Blob Storage operations. Values below the minimum are automatically raised with a warning.

Version 1.1.5​

Summary​

StorageLink 1.1.5 improves transaction management and error handling to improve the user experience, especially in higher volume environments.

Improvements to existing features​

  • A database connection is no longer held during api requests, so concurrent downloads or uploads are no longer limited by the number of connections available in the database connection pool.
  • The Upload Progress card has improved performance when there are many simultaneous uploads.
  • The Upload progress card better indicates an individual file upload completion or failure immediately instead of waiting for entire upload to complete.
  • When a user’s role is changed to or from an admin, that user is forced to log back in.
  • Error messages and logging when a file cannot be uploaded or downloaded are improved.
  • Error messages and logging when a user form fails to save are improved.
  • Updates the Ubuntu OS to version 24.04.

Version 1.1.4​

Summary​

StorageLink v1.1.4 introduces the ability to download multiple files or folders as compressed zip files and enhanced Identity Provider control by optionally restricting OIDC login to pre-created StorageLink users. This release adds support for PostgreSQL 16 and includes several bug fixes.

New Features​

  • Multiple files can be downloaded as a single zip file.
  • Entire folders including subfolders can be downloaded as zip files.
  • PostgreSQL 16 is now supported.
  • The launch_config.env file has newly supported variables to better support deployments into existing environments and using existing databases.

Improvements to existing features​

  • Upload error notification lists are now truncated when long and provide a link to view the full list of files.
  • Identity Provider login can be restricted to users that already exist in StorageLink.
  • File downloads no longer use iframes, providing a better experience across browsers.

Bug fixes​

  • Audit log now shows which roles are assigned to a created or updated user.
  • Database passwords with special characters like single-quote are now properly supported.
  • Supplying special characters like / in Azure Cloud Connection storage account names will no longer reset the cloud connection fields.
  • Numbers in the container name field for Blob Storage Connections are supported again.

Version 1.001.03​

Summary​

StorageLink v1.1.3 introduces the Azure File Share connection, improvements to password policy configuration, better handling of special characters in files and folders, and the ability to rename files and folders.

New Features​

  • Azure File Shares are now available for mapping to folders.
  • Folders can be "disconnected" from a cloud storage mapping. Disconnecting a folder will not delete the objects in that cloud storage location.
  • Files and folders can be renamed.

Improvements to existing features​

  • Login access token lifetime can now be configured in application properties, with a default of 8 hours:
features.api.access-token-time-to-live-seconds=28800
  • Password policy can be customized in the application properties. Can now set a required number of characters per class, prevent previously used passwords, and prevent usage of passwords from a word file:
password.policy.word-file=classpath:100k-most-used-passwords-NCSC.txt
password.policy.required-upper-count=1
password.policy.required-digit-count=1
password.policy.required-lower-count=1
password.policy.required-special-count=1
password.policy.require-digit=false
password.policy.require-lower=false
password.policy.require-special=false
password.policy.require-upper=false
password.policy.prevent-previously-used-password-count=5
  • Importing users with pbkdf2 encoded passwords is now supported. Can be configured with application properties:
password.encoder.pbkdf2.salt-length=16
password.encoder.pbkdf2.iterations=5000
password.encoder.pbkdf2.secret=
  • Preservation of timestamps for uploaded files can be disabled via application properties
features.api.preserve-file-timestamp-on-upload-enabled=true
  • Success and error icons added to the Uploaded Files list to make it easier to see which uploads have failed.
  • Folder names can now have any cloud-storage supported character in them.

Bug fixes​

  • Folders with "+" and other special characters are now navigable.
  • Deleting all items in a folder will no longer show an error that the folder no longer exists.
  • Paging on the users list now changes the page correctly.
  • Database connection properties tuned to prevent stale database connections.
  • Http Client interactions with cloud storage tuned to prevent stale cloud storage connections.

Version 1.001.02​

Security Updates​

  • Upgrades installed version of OpenSSH to overcome regression in CVE-2024-6387

Version 1.001.01​

Feature Updates​

  • Add configuration to disable admin login and access on a server. This can be used to create a public-facing server that has no admin access. defaults to:
features.api.admin-enabled=true
  • AWS base image updated from Amazon Linux 2 to Amazon Linux 2023.
  • AWS IMDSv2 now enabled, supported, and required.
  • Improved Load Balancer support to get and act on actual Client IP behind a load balancer.
  • Uploading a file with an extension and then uploading a file with the same name without an extension is now allowed.

Bug Fixes​

  • Fixes access to some restricted apis.

Version 1.001.00​

Breaking API Changes​

  • The /token/revoke endpoint is replaced with /logout, which does not need the token as a parameter
  • The /login endpoint no longer needs to specify a 'scope' value
  • The OIDC login process now delivers a Single-use token to the front-end when OIDC login completes. The single use token is posted to the /login endpoint as a code parameter with a grant_type of 'urn:ietf:params:oauth:grant-type:single-use-auth' which returns a usable hybrid token. This change was made to ensure possibly leaked token values through query string parameters would not give an attacker access to an account.

Feature Updates​

  • Pre-calculate user permissions and cloud connections to improve SFTP user connection speed
  • Add field to Azure Cloud Connections to configure if HNS is enabled or not
  • Increase max memory size for backend Java jar based on memory size of instance
  • Upgrade Google Cloud SQL Proxy to v2 to support PSC to connect to database
  • Remove network calls from instance boot to support starting instances in networks with no egress

Bug Fixes​

  • Fix issue with failing to upload files larger than 50GB to AWS
  • Limit OIDC “prompt” query string parameter to Google Identity Providers (fixes OIDC to providers like Ping that do not support that parameter)
  • Correct encoding of slashes in the base prefix for the Resolved Cloud Path for Azure Cloud Connections
  • Ensure no connection errors when uploading more than 500 simultaneous files
  • Pre-calculate user permissions and cloud connections to address bug where having many cloud connections could result in a database timeout
  • Disable password expiration after a year on Linux root account
  • Show and allow navigation to folders that have a blank name
  • Removes automatic determination of HNS enablement on Azure Storage Accounts because it failed when using a System Assigned Identity. HNS is now specified when creating/editing Azure Cloud Connection.
  • Importing a backup file with unsupported characters will now show errors with the line numbers of the unsupported characters

Other​

  • Update Java version from 11 to 17
  • Update Spring Security from 5 to 6
  • Update Spring Boot from 2 to 3

Version 1.000.03​

Bugs​

  • Corrects the code that was preventing the deletion of folders.
  • Conditionally utilize the select_account parameter when interacting with identity providers to enable support for Ping

Version 1.000.02​

Security​

  • Update SnakeYaml to v2.x to resolve CVE-2022-1471

Features​

  • Users that were automatically provisioned by OIDC login will now have a note indicating the provisioning
  • Responsive sizing for file list and buttons to display well on small screens

Bugs​

  • Downloading a file name with spaces will no longer replace spaces with +
  • Users that signed in via an Identity Provider will not be presented with the option to change their password
  • Long folder and file names will no longer cause a horizontal scrollbar

Version 1.000.00​

Files and Folders​

  • Read and write directly to Cloud Storage, using the HTTPS protocol
  • Configure folder permissions with List, Download, Upload and Delete/Overwrite
  • Map an Web User Home Folder to an Cloud Storage location
  • Folder mapping lets you configure a common scenario where an internal Web user has read/write access to external Web users' data, while external users cannot see each other's data

Web accounts​

  • Authenticate Web users with passwords or Identity Providers such as Cognito, Azure Active Directory or Google
  • Adds password complexity requirements

Web administration​

  • Supports multiple Web Admin accounts
  • Authenticate Web Admins with passwords or Identity Providers such as Cognito, Azure Active Directory or Google
  • Simplifies first-time setup, which can be done entirely from the Web Admin Interface (no command line required)
  • Imports Folders, Users and Settings via a migration process

Security​

  • Use instance profile permissions or configure credentials for each Cloud Storage location.

Performance and maintenance​

  • Improves performance and scalability through the use of the AWS/Azure/GCS SDK for Java
  • Uses Postgres instead of LDAP, for easier maintenance

Cost​

  • Software charge of 8 cents USD per hour
  • 30-day free trial