Articles
IsIPv6 - What does this built-in function do for your application?
The CFBreak 2025-18 email newsletter published May 9, 2025 highlighted isIPV6() as the CFDocs "Function of the Week".
This built-in function was added to Adobe ColdFusion 9 back in 2009. The description is "Determines whether the host supports IPv6." The argument's name is "hostname" and described as "IP address to check". The usage instructions state "When you use this function to verify if the remote host supports IPv6, pass the hostname and not the IP address. This function applies only if the server that places the request is IPv6-enabled."
Lucee's description is "checks if given IP is of IPV6 format". The argument is named "hostname" and described as "the hostname to check". The instructions state "If no hostname is provided, it defaults to checking the local machine's network interfaces".
BoxLang's description is "Determine whether the given hostname supports IPv6." (same copy as Adobe). The argument's name is "hostname" without any description.
These descriptions seemed different to me, and I got different results when I used the string "127.0.01". What should the result be? Is it 1) testing the string to determine if it is a valid IPv6 string or is 2) it performing a test of the host to determine if the hosts supports IPv6?
Our web application server supports IPv6, but that doesn't mean that all routes to the server support IPv6. I don't believe that it's currently enabled by our upstream provider. We also use a cloud-based WAF provider, and they allow for dualstack connections, but it's also disabled... so does my host "support" IPv6? The answer is "kinda" as it all depends on the routing.
I asked Gemini AI for some clarification and it responded that "As Adobe's documentation states, it simply checks if the string contains a colon (:) character. This is a very superficial check and doesn't actually validate if the string is a correctly formatted IPv6 address. Many other strings could contain a colon."... but this is an hallucination, as no documentation states this. (I'm not sure how developers can trust AI... but then again, it may be an issue regarding access to clearly-written documentation with examples.)
Using TryCF.com, the results are similar, except for IPv4 "127.0.0.1". For "8.8.8.8" (which is Google's DNS), it seems to validate the IP string whereas using the hostname "dns.google" must perform a background request to the host.
| Example | AdobeColdFusion | Lucee | BoxLang |
|---|---|---|---|
| isIPv6("127.0.0.1") | Yes | No | No |
| isIPv6("192.168.0.1") | No | No | No |
| isIPv6("::1") | Yes | Yes | Yes |
| isIPv6("0000:0000:0000:0000:0000:0000:0000:0001") | Yes | Yes | Yes |
| isIPv6("0000:0000:0000:0000:0000:0000:0000:0001") | Yes | Yes | Yes |
| isIPv6("8.8.8.8") | No | No | No |
| isIPv6("2001:4860:4860::8888") | Yes | Yes | Yes |
| isIPv6("2001:4860:4860:0:0:0:0:8888") | Yes | Yes | Yes |
| isIPv6("dns.google") // same host as 8.8.8.8 | Yes | Yes | Yes |
I'm not entirely sure what's happening under the hood. I also tested 12 bogus IPv6 strings and received consistent results. (er, except that "Excessive leading zeros causing interpretation issues" should probably be identified as invalid and require normalization since storing the "valid" IPv6 string could result in truncation.)
I know mobile devices are often provided temporary IPv6 addresses. Did this CF9 function provide some support to any of the now-deprecated <cfClient> mobile functions introduced in CF11?
Are there any other CFML functions that work with IPv6 IPs? Lucee provides a beneficial isIPInRange function, but this feature is not available in Adobe ColdFusion.
Once armed with the knowledge of whether an IP is IPv6 or not, what can you do what that information? I don't believe it requires altering any arguments of built-in network protocol tags (i.e., CFHTTP, CFFTP, CFMail, etc.) Also, by way of contrast, there's no "isIPv4" tag. IPv4 validation is not even available as an isValid("ipv4") algorithm.
Java Alternative: SeanCFoley's IPAddress Library
To provide the best cross-platform coverage for IPv4/6 support, we've integrated SeanCFoley's open source IPAddress library into our application framework to perform the following functions:
- Test whether a string is a valid IPv4 IP address
- Test whether a string is a valid IPv6 IP address
- Convert IPv4 and IPv6 string representations to 4 byte and 16 bytes binary values respectively
- Convert a 4 byte values to IP4 and 16 byte values to IPV6 string representations
- Convert IPv4/6 string representations to a normalized string
- Convert an IPv4/6 address to its reverse DNS lookup format
- Converts an IPv4/6 address to an INT (potential collision)
- Determine if the given address range contains the given IP address. (Supports IPv4 & IPv6)
This library supports a wealth of IP-related functionality. I plan on creating an online playground on myCFML to test some of the above feature and release a CFC. (Since this requires a third-party JAR file, it's not something that I can launch in either TryCF or CFFiddle.)
By using this third-party library, we've been able to capture the WAF-provided external IP address of the requestor's IP address (which is either IPv4 or 6) and then accept/reject access based on behavior patterns. Our previous WAF provider would proxy the IPv6 addresses to IPv4 without providing the requestor's IPv6 address. This made it difficult as other IPv6 users would potentially be proxied using the same temporary IPv4 IP address which results in making identifying abuse a lot more difficult.
<cfscript>
platform = (structkeyexists(server,"boxlang")) ? "Boxlang #server.boxlang.version# / #server.coldfusion.ProductName# #server.coldfusion.ProductVersion#" : (structkeyexists(server,"lucee")) ? "#server.coldfusion.ProductName# #server.lucee.version#" : "#server.coldfusion.ProductName# #server.coldfusion.ProductVersion#";
tests = [
"127.0.0.1",
"192.168.0.1",
"8.8.8.8",
"::1",
"0000:0000:0000:0000:0000:0000:0000:0001",
"0000:0000:0000:0000:0000:0000:0000:0001",
"2001:4860:4860::8888",
"2001:4860:4860:0:0:0:0:8888",
"dns.google"
];
writeoutput("<h2>Platform: #platform#</h2>");
for(test in tests){
writeoutput("<fieldset><legend>isIPV6(""#test#"")</legend>#yesnoformat(isIPV6(test))#</fieldset>");
}
badTests = [
"2001:db8:abcd:ef01:2345:6789:hijk:lmnp:qrst" // Too many colons
,"2001:db8:abcd:ef0g:2345:6789:abcd:ef01" // Invalid hexadecimal characters
,"2001:db8:abcdefghijkl:ef01:2345:6789:abcd:ef01" // Incorrect segment length (too long):
,"2001:d:a:e:2:6:a:e" // Incorrect segment length (too short, but misleading)
,"2001:db8:abcd:ef01:192.168.1.1" // Mixing IPv4 and IPv6 in the wrong way
,"2001::db8::ef01:2345"// Incorrect use of double colon
,"::2001:db8:abcd:ef01::" // Incorrect use of double colon
,"2001*db8:abcd:ef01:2345:6789:abcd:ef01" // Characters outside the allowed range
,":2001:db8:abcd:ef01:2345:6789:abcd:ef01" // Leading colons with no implied zero segments
,"2001:db8:abcd:ef01:2345:6789:abcd:ef01:" // Trailing colons with no implied zero segments
,"2001:00000db8:00abcd:000ef01:02345:06789:0abcd:0ef01" // Excessive leading zeros causing interpretation issues
,"2001:db8:abc:def:::1234:5678" // A mix of valid and invalid syntax
];
writeoutput("<h2>These are invalid IPv6 strings</h2>");
for(test in badTests){
writeoutput("<fieldset><legend>isIPV6(""#test#"")</legend>#yesnoformat(isIPV6(test))#</fieldset>");
}
</cfscript>