Every variable in ColdFusion lives in a scope — a named container that determines who can see it and how long it lasts. Get scoping wrong inside a function and a variable can silently leak into the page that called it, overwrite another request's data, or worse.
Learning Objectives
After completing this lesson, you'll be able to:
- Explain what the default VARIABLES scope is and its limits.
- Use var to keep a function's local variables from leaking out.
- State ColdFusion's scope-lookup order for unscoped variable names.
- Recognize the real security risk of leaving user-facing variables unscoped.
The Default: VARIABLES Scope
Any variable set without an explicit scope prefix on a .cfm page gets the VARIABLES scope automatically — myVar and variables.myVar are the same thing. It's only accessible within that page (and pages it includes), not from other requests or other pages.
Inside a Function: LOCAL Scope and var
Variables declared with var inside a function belong to that function's own LOCAL scope — they exist only for the duration of that call and don't collide with a page-level variable of the same name.
Leave out var inside a function and ColdFusion assigns the VARIABLES scope instead — the variable silently leaks out to the calling page, which is rarely what's intended.
Scope-Lookup Order
When a variable name has no explicit scope prefix, ColdFusion searches through scopes in a fixed order until it finds a match. This is the full order, from first-checked to last:
| Order | Scope |
|---|---|
| 1 | Local (function-local, var-declared) |
| 2 | Arguments |
| 3 | Thread local |
| 4 | Query (inside a query loop) |
| 5 | Thread |
| 6 | Variables |
| 7 | CGI |
| 8 | cffile |
| 9 | URL |
| 10 | Form |
| 11 | Cookie |
| 12 | Client |
Notice URL and Form are near the bottom of the list, checked one after the other — that's the exact mechanism behind the next section's security gotcha.
The Real Gotcha: Unscoped Variables Are a Security Risk
Because URL is checked before Form in the lookup order, an unscoped variable name that matches both a URL parameter and a form field will silently resolve to whichever one ColdFusion finds first — usually not the one the code was written expecting.
This becomes a genuine cross-site scripting (XSS) risk: if a page reads an unscoped search variable expecting it to come from a submitted form, an attacker can supply the same name as a URL parameter instead — ?search=<script>...</script> — and have it accepted and rendered the same way.
<cfscript>
if (isDefined("search")) {
writeOutput("You searched for: " & search); // could be url.search OR form.search
}
</cfscript><cfif isDefined("search")>
You searched for: <cfoutput>#search#</cfoutput>
<!--- could be url.search OR form.search --->
</cfif><cfscript>
if (structKeyExists(form, "search")) {
writeOutput("You searched for: " & encodeForHtml(form.search));
}
</cfscript><cfif structKeyExists(form, "search")>
You searched for: <cfoutput>#encodeForHtml(form.search)#</cfoutput>
</cfif>Explicitly scoping the variable (form.search, not search) removes the ambiguity entirely — the code only ever reads from the source it was written for.
Common Beginner Mistakes
Forgetting var on a function-local variable
Without var, ColdFusion assigns the VARIABLES scope, which can silently overwrite a page-level variable of the same name and leak state between calls.
Reading form/url data without an explicit scope prefix
This relies on ColdFusion's scope-lookup order picking the source you meant, which isn't guaranteed and opens the door to the URL/Form ambiguity described above. Always write form.fieldname or url.paramname explicitly.
Declaring var statements after other code in a function
In CFScript, var declarations should come first in the function body — declaring them partway through works in practice but is a bad habit that makes the function harder to read.
Best Practices
- Explicitly scope every variable you can — form.x, url.x, variables.x — instead of relying on the lookup order.
- Always use var for a function's local variables, even in a small function where a leak seems unlikely.
- Run any user-facing output that originated from form/url/cookie data through encodeForHtml() (or the equivalent) before writing it back to the page.
Interview Questions
What happens if you forget var on a variable inside a function?
ColdFusion assigns it the VARIABLES scope by default, so it becomes visible to (and can overwrite) variables outside the function, instead of staying local to that call.
Why is leaving form/URL variables unscoped a security concern?
Because URL is checked before Form in ColdFusion's scope-lookup order, an attacker can supply a URL parameter with the same name as an expected form field and have it silently accepted — a classic reflected-XSS vector if the value is ever output without encoding.
Which scope do variables declared with var inside a function belong to?
The Local (function-local) scope — the very first scope checked in ColdFusion's lookup order, and the one that exists only for the duration of that function call.
Summary
In this lesson, you covered the default VARIABLES scope, using var to keep function-local variables from leaking, the full scope-lookup order, and a real security gotcha where unscoped variables create ambiguity between URL and Form data.
That wraps up the core mechanics of writing functions in ColdFusion.
What's Next?
The final lesson in this module covers recursion — functions that call themselves, with a base case, an accumulator pattern, and the scoping habits that keep recursive calls from interfering with each other.