Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ All historical references to "CFWheels" in this changelog have been preserved fo
- Use the Adobe-safe 3-argument `mid()` form when stripping the `wheels` prefix in the MCP command executor and its security spec; the prior 2-arg call crashed the entire `security/` test bundle on Adobe ColdFusion (#2613)
- Replace Lucee-only `directoryCreate(path, true)` calls in `BrowserTest.$captureFailureArtifacts` and `McpServer` test-file generation with `java.io.File.mkdirs()` so artifact directory creation no longer trips Adobe ColdFusion's `DIRECTORYCREATE` single-argument validator (#2614)
- Generated `Application.cfc` (and the in-repo `public/`, `examples/tweet/`, `examples/starter-app/` copies) now assigns the injector directly to `application.wheelsdi` in `onApplicationStart()` and `onError()` instead of an orphan local `injector` variable, matching the documented 4.0 DI container name and the way every other reference in the file reads (#2622)
- Interpolate plugin and package names in the "Loading plugin..." / "Loading package..." `wheels_security.log` INFO lines so operators can read which plugin/package was being loaded; the call sites were double-escaping the pound signs (`##var##`) and emitting literal `#var#` placeholders instead of resolved values (#2630)
- Update the scaffolded `config/routes.cfm` doc-URL comment in `cli/src/templates/ConfigRoutes.txt` and `cli/lucli/templates/app/app/snippets/ConfigRoutes.txt` from the dead `https://guides.wheels.dev/docs/routing` path to the canonical `https://guides.wheels.dev/v4-0-0-snapshot/handling-requests-with-controllers/routing` URL, so freshly scaffolded apps no longer ship a broken link (#2635)
- `wheels new --no-sqlite` now suppresses the SQLite datasource pair in the scaffolded `lucee.json` so Lucee no longer auto-creates `db/development.sqlite` / `db/test.sqlite` on first connection (#2621)

Expand Down
2 changes: 1 addition & 1 deletion vendor/wheels/PackageLoader.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ component output="false" {

try {
WriteLog(
text = "[Wheels] Loading package '##arguments.dirName##' from ##arguments.pkgDir##",
text = "[Wheels] Loading package '#arguments.dirName#' from #arguments.pkgDir#",
type = "information",
file = "wheels_security"
);
Expand Down
2 changes: 1 addition & 1 deletion vendor/wheels/Plugins.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ component output="false" extends="wheels.Global"{
local.pluginValue = local.plugins[local.pluginKey];
try {
WriteLog(
text = "[Wheels] Loading plugin '##local.pluginKey##' from ##local.pluginValue.folderPath##",
text = "[Wheels] Loading plugin '#local.pluginKey#' from #local.pluginValue.folderPath#",
type = "information",
file = "wheels_security"
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// GH##2630: guard the PackageLoader / Plugins load-trace WriteLog calls against re-escaping #var# as ##var##.
component extends="wheels.WheelsTest" {

function run() {
describe("Plugin & package loader log interpolation (##2630)", () => {

it("does not escape pounds in the PackageLoader load-trace message", () => {
var source = FileRead(ExpandPath("/wheels/PackageLoader.cfc"));

// "####" in a CFML string literal evaluates to "##" at runtime — the bug form.
expect(FindNoCase("####arguments.dirName####", source) GT 0).toBeFalse(
"PackageLoader.cfc must not emit escaped pounds around "
& "arguments.dirName in WriteLog text — CFML reads each "
& "doubled pound as a literal pound, so the placeholder "
& "never interpolates. Use a single pound on each side. "
& "See issue ##2630."
);

expect(FindNoCase("####arguments.pkgDir####", source) GT 0).toBeFalse(
"PackageLoader.cfc must not emit escaped pounds around "
& "arguments.pkgDir in WriteLog text — see issue ##2630."
);

// Positive guard: fails if the WriteLog line is silently removed.
expect(FindNoCase("'##arguments.dirName##'", source) GT 0).toBeTrue(
"PackageLoader.cfc must retain single-pound interpolation "
& "around arguments.dirName in WriteLog text — see issue ##2630."
);

expect(FindNoCase("from ##arguments.pkgDir##", source) GT 0).toBeTrue(
"PackageLoader.cfc must retain single-pound interpolation "
& "around arguments.pkgDir in WriteLog text — see issue ##2630."
);
});

it("does not escape pounds in the Plugins load-trace message", () => {
var source = FileRead(ExpandPath("/wheels/Plugins.cfc"));

expect(FindNoCase("####local.pluginKey####", source) GT 0).toBeFalse(
"Plugins.cfc must not emit escaped pounds around "
& "local.pluginKey in WriteLog text — CFML reads each "
& "doubled pound as a literal pound, so the placeholder "
& "never interpolates. Use a single pound on each side. "
& "See issue ##2630."
);

expect(FindNoCase("####local.pluginValue.folderPath####", source) GT 0).toBeFalse(
"Plugins.cfc must not emit escaped pounds around "
& "local.pluginValue.folderPath in WriteLog text — see "
& "issue ##2630."
);

// Positive assertions: see PackageLoader block above for rationale.
expect(FindNoCase("'##local.pluginKey##'", source) GT 0).toBeTrue(
"Plugins.cfc must retain single-pound interpolation around "
& "local.pluginKey in WriteLog text — see issue ##2630."
);

expect(FindNoCase("from ##local.pluginValue.folderPath##", source) GT 0).toBeTrue(
"Plugins.cfc must retain single-pound interpolation around "
& "local.pluginValue.folderPath in WriteLog text — see issue ##2630."
);
});

});
}

}
Loading