From 744315694ed5e13a5dcef0d2064851935f872114 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Sede=C3=B1o?= Date: Wed, 9 Sep 2026 17:25:36 +0200 Subject: [PATCH] Mark CBCsrf as threadSafe so the singleton is published after autowiring Without the annotation WireBox stores the singleton in its cache before autowiring it, and the first containsKey() check in coldbox/system/ioc/scopes/Singleton.cfc runs outside the lock. A concurrent request can therefore get the instance before cacheStorage is injected and fail with "variable [CACHESTORAGE] doesn't exist". CacheStorage@cbstorages already carries the annotation for the same reason. CBCsrf has no circular dependencies, so publishing after autowire is safe. --- changelog.md | 7 +++++++ models/cbcsrf.cfc | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index 22a448d..a1abfef 100644 --- a/changelog.md +++ b/changelog.md @@ -9,6 +9,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed + +- Marked `CBCsrf` as `threadSafe` so WireBox publishes the singleton only after + autowiring it. Concurrent requests hitting a cold singleton cache (right after a + framework reinit, for instance) could otherwise get a half-wired instance and fail + with `variable [CACHESTORAGE] doesn't exist`. + ## [3.2.0] - 2025-02-19 ### Added diff --git a/models/cbcsrf.cfc b/models/cbcsrf.cfc index 2d6e4e3..1f7e35f 100644 --- a/models/cbcsrf.cfc +++ b/models/cbcsrf.cfc @@ -4,7 +4,7 @@ * --- * Service that encapsulates token security against cross site request forgery (csrf) */ -component accessors="true" singleton { +component accessors="true" singleton threadSafe { /* ********************************************************************* ** DI