Custom User Agents For ColdFusion Debugging
Yesterday, I was debugging a page on a live site. This is, of course, not the best practice, but let's face it, sometimes you gotta do what you gotta do. The biggest problem with debugging on a live site is that any changes you make to a page can be seen by any other user that is concurrently using that page. To get around this as much as possible, I will do things like CFDump out a variable only if a certain key is in the URL. For example:
<!--- Check for debugging-user request. --->
<cfif StructKeyExists( URL, "please" )>
<!--- Output form variables. --->
<cfdump
var="#FORM#"
label="Form Variables"
/>
</cfif>
This works sometimes, but not all the time, especially if you are trying to debug errors in form processing and redirect logic where the URL parameters don't always get passed along. I started to think about ways in which I could more easily identify myself as the only person who should see a piece of output. I could work with the IP address, but something about that just seems a bit off; first I'd have to get the IP (yeah, I know that's not hard), but then what if it changes. Does the office have a static IP? A dynamic IP? I don't know, and frankly, I don't want to think about it.
And then it occurred to me, why not just change the way my browser announces itself. This would, of course, be the user agent. So that's what I did. I went into the FireFox configuration (put about:config in the URL field) and created a User Agent override (new string value):
general.useragent.override
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6 (DEVELOPER)
For the user agent override, I have taken a standard FireFox user agent (which I keep as a Code Snippet in HomeSite) and added (DEVELOPER) to the end of it. Now, when my browser announces itself, it will appear as a standard browser, but will allow me to check for the (DEVELOPER) flag. Now, my debugging output can look like this:
<!--- Check to see if current browser is in debugging mode. --->
<cfif Find( "(DEVELOPER)", CGI.http_user_agent )>
<!--- Output form variables. --->
<cfdump
var="#FORM#"
label="Form Variables"
/>
</cfif>
I like this code a whole lot better. It seems much more explicit in the "intent" of the code. In my first example, I checked for "please". The function of that doesn't feel obvious. Now, when I check for "Developer" in the user agent, the intent of my code feels so much cleaner, so much more explicit. And, I have to believe that feeling means it's more correct.
_But, isn't depending on the user agent override a security issue? _
Sure, if you are dumping out things like DSN information. But, really, that's not what we're usually doing when we debug on the live server. We're really dumping out variables that pertain to the current user (you) and this can never really be a security issue.
Anyway, I thought this was a neat little trick.
Want to use code from this post? Check out the license.
Reader Comments
Nice tip about the general.useragent.override preference, I didn't know about that one.
ColdFire also uses a custom user agent to determine whether or not to return debugging info. You could also use the Modify Headers Firefox extension to modify the user agent or to send a totally custom request header such as x-debug.
That is a neat trick: I didn't realize it was that easy to hack the browser identifier like that.
Most of the CF apps I develop require the user to authenticate, so I can code the app to behave differently if I'm the user, but your technique would be ideal for situations where the user is unidentified.
Nice work!
Glad you think it' interesting. Just be sure to use the whole FireFox useragent PLUS your custom user agent. If you put in just your custom flag, then I found gMail does not give you the proper version of the email :)
hmmm... intesting tip. This could come in handy someday.
If you're using Firefox you should consider the User Agent Switcher extension
https://addons.mozilla.org/en-US/firefox/addon/59
@Ben:
In the past when I've had to do this, I just use the cgi.remote_addr variable to check for my IP address.
Now I tend to use SeeFusion's "trace" method to dump output SeeFusion debug output. That let's me see what's going on without it showing up in the output stream. I can also then view the output for other people visiting the page.
@Dan,
Cool SeeFusion trick. I have only briefly used SeeFusion so I am not familiar with all of its goodness.
[tongue in cheek] Cool! Now all I have to do is use your FF trick and surf your site to see what you're debugging at the moment. (you didn't really use "(DEVELOPER)", did you dude? ;-)
In the past, I worked in a system where we had a secret, IP-restricted developer-only login area (de-coupled from the apps), which let us log in with a u/p combo and click a button that turned on a "unique_nerd_only_flag" (no, that's not the real name) via JS, and then we could toggle our proprietary debugger securely and obscurely. This method probably wasn't bullet-proof, but should offer more security than the FF hack... thoughts?
@Aaron,
Oh please, dude :) You don't actually think I LEAVE the debugging code in place???? I am not that amateur (can you believe this guy ;)).
I am only using this for one-off emergencies where you need to jump on a live site and debug something that is not working properly. Of course, once I am done, I remove all the code and leave the server in pristine shape.
This is not meant to be done with sensitive data. This is meant to dump out user data (that any user would know about anyway). If you want to surf a site with the intent to see the FORM data that is dump out, enjoy :) ... of course, it might be easier to just see what you enter in the forms.
@Aaron,
I have also done the IP-restricted logins and I have found that to be hugely useful.
That is sharp.
Yet another clever hack! Well played, Ben. :)
The security concerns that have been raised in the comments could be addressed at least in part by replacing "DEVELOPER" with something relatively impossible to guess. After all, sending along an identifier string with a request is exactly how cookies work. And we all build perfectly secure sites that use cookies for authentication.
@David,
Thanks for the reassurance. But, I also just want to be clear that this was not meant to let people view sites using a different "persona". This was literally meant for more meaningful debugging gestures.
I never have any bugs so I don't need any tricks. <cough cough> :)
For simple data cflog is one of the simplest ways to debug live sites assuming you have access to cfadmin or the log files on the server.
Nice one Ben. Wish I thought of it first. :p
I usually have my apps wrapped in global try/catch to at least email exception reports (with full cfdump) to me, but I also find that it's just too slow when having to debug something sour in production. HostMySite can take 5 or 10 minutes to spool that email out, and I want to be off the server in less than that if I can. I find the <cfif cgi.remote_addr is "my.cur.rent.ip"> works quite well to at least dump to screen, and I can make the temporary change right in my error handler, so it generally catches anywhere it happens, meaning I don't have to chase file changes in multiple places.
Just some thoughts ... heh
Nice trick I have been using it for years but instead of using the user agent I create a hidden page to toggle on/off a permanent cookie. So if the cookie exists the dump is shown.
Let's face it some times work needs to be done in less than ideal situations. Maybe in a different place or without my own computer. In these cases the cookie hack saves the day.
@EstebanD,
Nice cookie idea. I never thought of that. Yeah, I think instead of getting too hung up on the fact that work situations are less than ideal, we should concentrate on ways to make working in that environment as easy and seamless as possible.
Thanks! Awesome...I'm using it.