Whatever message this page gives is out now! Go check it out!
| Audience | Use case |
|---|---|
| Development teams | Get real-time security feedback while coding in Visual Studio Code. |
| DevOps teams | Run scripted scans against the RDS endpoint that the extension uses. Requires the Developer profile, valid RDS credentials, and network access to the server. |
| Security auditors | Run a full security analysis before a production deployment. |
| Compliance teams | Generate security assessment reports in HTML, JSON, CSV, or PDF for audits. |
| Option | Description |
|---|---|
| Run Security Analyzer | Analyzes the selected code and displays vulnerabilities. |
| Clean Run Security Analyzer | Resets the ignored state of all previously ignored findings, then runs a fresh scan. |
| Cancel Run Security Analyzer | Stops the current scan. |
| Clear Security Markers | Removes all security markers and warnings from the editor. |
| Card | Behavior |
|---|---|
| All issues | Shows the total number of findings and clears any active card filter. |
| High severity | Filters the issues table to High severity findings only. |
| Medium severity | Filters the issues table to Medium severity findings only. |
| Low severity | Filters the issues table to Low severity findings only. |
| Severity | Description |
|---|---|
| High | Critical vulnerability that you should fix immediately. |
| Medium | Significant risk that you should fix before production. |
| Low | Minor or contextual risk to review and fix when possible. |
| Type | Description |
|---|---|
| Error | Direct vulnerability that violates security rules. |
| Warning | Potential issue that requires context to confirm. |
| Function | Use for |
|---|---|
encodeForHTML() | HTML content. |
encodeForHTMLAttribute() | HTML attribute values. |
encodeForJavaScript() | JavaScript strings. |
encodeForCSS() | CSS values. |
encodeForURL() | URL parameters. |
encodeForLDAP() | LDAP search filters. |
encodeForXPath() | XPath expressions. |
encodeForXML() | XML content. |
| Vulnerability | Description |
|---|---|
| SQL Injection | Unvalidated user input in SQL queries. |
| XSS Attack | Cross-site scripting from unescaped output. |
| PDF XSS Attack | Cross-site scripting in PDF generation. |
| CSRF Attack | Cross-site request forgery. |
| CFLocation Validation | Unsafe redirects with cflocation. |
| Cookies Validation | Insecure cookie handling. |
| Passwords | Weak password handling or storage. |
| File Upload Validation | Unsafe file upload handling. |
| Get vs Post | Sensitive data sent over a GET request. |
| File Injection | Path traversal or unsafe file inclusion. |
| Unnamed Application | Application scope without a name attribute. |
| XML Security | Unsafe XML parsing, including external entity expansion. |
| Cryptography | Weak algorithms, hardcoded keys, or plaintext storage. |
| Vulnerability | Description |
|---|---|
| NoSQL Injection | User input in MongoDB operations without validation. |
| Command Injection | User input in cfexecute or in calls through Runtime.exec() and ProcessBuilder. |
| LDAP Injection | User input in LDAP queries without encoding. |
| XPath Injection | User input in XPath queries without validation. |
| Template Injection | User input in evaluate(), de(), cfinclude, cfmodule, or Java ScriptEngine.eval(). |
| JavaScript Injection | DOM-based cross-site scripting, eval() use, and unsafe event handlers. |
| Advanced File Security | Path traversal, zip extraction, or unsafe file operations. |
| Authentication and Session Handling | Unsafe session lifecycle, weak credential checks, or trust of client state. |
| XML security | XML External Entity (XXE) injection is an attack where malicious XML input tricks the parser into exposing sensitive server files or making unauthorized network requests by abusing the XML external entity feature. |
| Cryptography | Flags the use of weak or outdated encryption algorithms in your code and recommends stronger alternatives to protect sensitive data. |
| Unscoped variables | Unscoped variables in ColdFusion Security Analyzer flags variables that are used without an explicit scope prefix (such as variables., form., or url.). |
"enabled": true or "enabled": false on the matching entry in the rules file.| Rule name | Title | Default severity |
|---|---|---|
sqlinjection | SQL Injection | High |
xss | XSS Attack | High |
pdfxss | PDF XSS Attack | High |
csrf | CSRF Attack | High |
cflocation | CFLocation Validation | Medium |
cookies | Cookies Validation | Medium |
passwords | Passwords | High |
fileupload | File Upload Validation | High |
getvspost | Get vs Post | Medium |
fileinjection | File Injection | High |
unnamedapp | Unnamed Application | Low |
xmlsecurity | XML Security | High |
cryptography | Cryptography | High |
nosqlinjection | NoSQL Injection | High |
commandinjection | Command Injection | High |
ldapinjection | LDAP Injection | High |
xpathinjection | XPath Injection | High |
templateinjection | Template Injection | High |
javascriptinjection | JavaScript Injection | High |
advancedfilesecurity | Advanced File Security | High |
authsession | Authentication and Session Handling | High |
unscopedvariable | Unscoped Variables | Medium |
<cfscript>
// Mongo service obtained via createObject and the Mongo Java driver
results = mongoService.find(
collection = "users",
query = { "username": form.searchTerm }
);
</cfscript><cfscript>
if (isValid("regex", form.searchTerm, "^[a-zA-Z0-9\s\-_]+$")) {
results = mongoService.find(
collection = "users",
query = { "username": toString(form.searchTerm) }
);
} else {
throw(type = "InvalidInput", message = "Invalid search term");
}
</cfscript>cfexecute:<cfexecute name="#form.command#" arguments="#form.args#" variable="output"><cfscript>
allowedCommands = ["ls", "pwd", "whoami"];
cmdIndex = arrayFindNoCase(allowedCommands, form.command);
if (cmdIndex GT 0
AND isValid("regex", form.args, "^[a-zA-Z0-9\-_/\.]*$")) {
safeCommand = allowedCommands[cmdIndex];
safeArgs = form.args;
} else {
throw(type = "InvalidCommand", message = "Command or arguments not allowed");
}
</cfscript>
<cfexecute name="#safeCommand#"
arguments="#safeArgs#"
variable="output"
timeout="10" /><cfscript>
users = ldapSearch(
attributes = "cn,mail",
filter = "(&(objectClass=person)(cn=*#form.username#*))"
);
</cfscript>encodeForLDAP():<cfscript>
users = ldapSearch(
attributes = "cn,mail",
filter = "(&(objectClass=person)(cn=*#encodeForLDAP(form.username)#*))"
);
</cfscript><cfscript>
results = xmlSearch(xmlDoc, "//user[@id='#form.userId#']");
</cfscript>encodeForXPath():<cfscript>
results = xmlSearch(xmlDoc, "//user[@id='#encodeForXPath(form.userId)#']");
</cfscript>cfinclude path:<cfscript>
result = evaluate("#form.expression#");
include "#form.templatePath#";
</cfscript>evaluate() with a switch over expected values whenever possible. The same allowlist rule applies to Java-side script evaluation through ScriptEngine.eval():<cfscript>
allowedExpressions = ["math.pi", "now()", "dateFormat(now())"];
if (arrayFind(allowedExpressions, form.expression)) {
result = evaluate("#form.expression#");
}
include "includes/safe_template.cfm";
</cfscript><cfscript>
passwordHash = hash(form.password, "MD5");
dataHash = hash(form.data, "SHA-1");
</cfscript>passwordHash holds the PBKDF2 output and is the value stored in the database:<cfscript>
// SHA-256 is appropriate for non-password integrity hashing.
dataHash = hash(form.data, "SHA-256");
// For passwords, use bcrypt, scrypt, Argon2, or PBKDF2 with a per-user salt
// and a high iteration count. Never use raw SHA-256 for passwords.
salt = generateSecretKey("AES");
iterations = 100000;
passwordHash = generatePBKDFKey("PBKDF2WithHmacSHA512",
form.password, salt, iterations, 256);
</cfscript><cfquery name="storeData" datasource="#dsn#">
INSERT INTO users (password, creditcard)
VALUES ('#form.password#', '#form.creditCard#')
</cfquery>passwordHash), and uses parameterized queries:<cfscript>
// Read the encryption key from the OS environment, not from source.
systemObj = createObject("java", "java.lang.System");
encryptionKey = systemObj.getenv("ENCRYPTION_KEY");
// Derive a storable password hash using PBKDF2.
salt = generateSecretKey("AES");
iterations = 100000;
passwordHash = generatePBKDFKey("PBKDF2WithHmacSHA512",
form.password, salt, iterations, 256);
encryptedCreditCard = encrypt(form.creditCard, encryptionKey, "AES", "Base64");
</cfscript>
<cfquery name="storeEncryptedData" datasource="#dsn#">
INSERT INTO users (password_hash, encrypted_creditcard)
VALUES (
<cfqueryparam value="#passwordHash#" cfsqltype="cf_sql_varchar">,
<cfqueryparam value="#encryptedCreditCard#" cfsqltype="cf_sql_varchar">
)
</cfquery>cfqueryparam for user input in SQL queries to prevent SQL injection.<div onclick="#form.action#">Click me</div>
<script>#form.scriptCode#</script>
<a href="#form.url#">Link</a><div onclick="safeFunction()">Click me</div>
<script>
var userInput = "#encodeForJavaScript(form.input)#";
</script>
<a href="#encodeForHTMLAttribute(form.url)#">Link</a>cfinclude:<cffile action="read" file="#form.filePath#">
<cfdirectory action="list" directory="#url.directoryPath#">
<cfinclude template="#form.templatePath#">startsWith check on the raw input does not stop traversal, because the path /var/www/uploads/../../etc/passwd still starts with /var/www/uploads/. Verify the canonical path falls inside the canonical base directory and apply a filename allowlist:<cfscript>
safeBasePath = "/var/www/uploads/";
baseFile = createObject("java", "java.io.File").init(safeBasePath);
canonicalBase = baseFile.getCanonicalPath() & "/";
requestedFile = createObject("java", "java.io.File").init(safeBasePath, form.filePath);
canonicalRequested = requestedFile.getCanonicalPath();
if (canonicalRequested.startsWith(canonicalBase)
AND reFind("^[a-zA-Z0-9_\-\.]+$", requestedFile.getName())) {
fileContent = fileRead(canonicalRequested);
} else {
throw(type = "InvalidPath", message = "File path is outside the allowed directory");
}
</cfscript>
<cfinclude template="includes/safe_template.cfm">sessionInvalidate() does not accept a session identifier argument; calling it this way reflects an incorrect assumption about the API signature:<cfscript>
// ANTI-PATTERN: Role taken from a form field — caller can claim any role.
if (form.userRole EQ "admin") {
showAdminPanel();
}
// ANTI-PATTERN: Session id supplied by the URL — a session-fixation vector.
// Note: sessionInvalidate() does not accept a parameter; this pattern is
// shown to illustrate the mistake, not as a callable example.
sessionInvalidate(url.sessionId);
</cfscript>cflogin and cfloginuser to authenticate the user, stores roles in server-side session state, and rotates or invalidates sessions through the official ColdFusion APIs. Replace the placeholder calls with your application's credential-verification query and role-lookup query:<cflogin>
<cfif IsDefined("cflogin")>
<!--- Implement login: query your users table and verify the password hash. --->
<cfquery name="qUser" datasource="#dsn#">
SELECT password_hash, roles
FROM users
WHERE username = <cfqueryparam value="#cflogin.name#" cfsqltype="cf_sql_varchar">
</cfquery>
<cfif qUser.recordCount EQ 1
AND verifyPasswordHash(cflogin.password, qUser.password_hash)>
<!--- Store roles from the database, not from the request. --->
<cfloginuser name="#cflogin.name#"
password="#cflogin.password#"
roles="#qUser.roles#">
<cfset sessionRotate()>
</cfif>
</cfif>
</cflogin>
<cfscript>
if (session.authenticated AND listFindNoCase(session.userRoles, "admin")) {
showAdminPanel();
}
function logout() {
sessionInvalidate();
}
</cfscript>verifyPasswordHash() in the example above represents your application's password-verification logic (for example, a bcrypt or PBKDF2 comparison). It is not a ColdFusion built-in function.var is referenced unscoped. The reference resolves to whichever scope holds a matching name first, which may be form, url, or another caller-controlled scope:<cfscript>
function checkAccess() {
var isAdmin = session.userRole EQ "admin";
// The unscoped reference may pick up form.isAdmin from the request.
if (isAdmin) {
doSensitiveOperation();
}
}
</cfscript>local scope on both the declaration and the reference, so the lookup cannot fall through to a caller-controlled scope:<cfscript>
function checkAccess() {
local.isAdmin = session.userRole EQ "admin";
if (local.isAdmin) {
doSensitiveOperation();
}
}
</cfscript>| Operating system | Path |
|---|---|
| Windows | C:\ColdFusion2025\cfusion\lib\securityanalyzer\codeanalyzerrules.json |
| Linux | /opt/coldfusion2025/cfusion/lib/securityanalyzer/codeanalyzerrules.json |
| macOS | /Applications/ColdFusion2025/cfusion/lib/securityanalyzer/codeanalyzerrules.json |
name field."enabled": true to enable the rule, or "enabled": false to disable it.{
"name": "sqlinjection",
"enabled": true,
"severity": "high"
}cfqueryparam for all user input in SQL queries.local, variables, or session in both the declaration and the reference.| Issue | Action |
|---|---|
| Security Analyzer does not start | Confirm the project points to a ColdFusion server with the Developer profile. |
| Scan times out | Increase the RDS timeout in the extension settings. |
| No findings appear | Confirm that the project contains CFML files and is not empty. |
| Scan is slow on large projects | Run Security Analyzer on logical sub-folders or modules first, then widen the scope. As a secondary step, increase the JVM max heap if the server log shows skipped files because of memory limits. |
| Findings look incorrect | Review the context of each finding. Some findings remain false positives despite the accuracy improvements in this release. Choose Mark as Ignored when appropriate. |
# Basic use
cf-security-analyzer /path/to/coldfusion/app
# With a configuration file
cf-security-analyzer --config security-config.json --output html --severity high
# Pipeline integration
cf-security-analyzer --fail-on-issues --output sarif --format html| Option | Description |
|---|---|
ignorePaths | Paths to exclude, for example vendor/ or node_modules/. |
ignoreExtensions | File extensions to skip, for example min.js or min.css. |
ignoreScanners | Specific rules to disable. |
minSeverity | Minimum severity to report. |
includeScanners | Rules to run when you restrict the scope. |
outputFormats | Output formats, including HTML, JSON, PDF, and SARIF. |
failOnIssues | Exit with an error code when the scan finds issues. |