Disabling CFC auto documentation

This post is more than 2 years old.

I shared a few emails back and forth with a reader last week who had an interesting problem. They had CFCs under web root that he did not want to be auto-described. If you don't know what I'm talking about, this is the feature within ColdFusion where if you request a CFC without a method you get a description of the methods and properties. This is normally protected by a login if your CF Administrator has either a normal or RDS password, as seen below.

So the question is - is there a way to disable or block this behavior? While it's not a security risk per se - you would need a valid login to see anything (*) - the reader wanted absolutely nothing to show up based on certain conditions. Here are a few options you can consider.

  1. Within your CFC you could actually detect the lack of a method call and add one yourself. I learned of this trick from Mark Drew.

component {

if(!structKeyExists(url, "method")) {
	url.method="helloworld";
}
	
remote function helloworld() {
	return "Hello Programs";
}

}

This code could use additional logic to check remote IP, time of day, whatever. Or - as the original reader wanted - you could return a header specifying a 404 error. How about another option?

  1. The first example works - but requires every CFC to be updated. You could add such logic to a base component easily enough - and in theory - your publicly accessible CFCs are probably a small subset of your total set of CFCs. But what about blocking it at the 'viewer' application? You may not know this, but the CFC describer tool is a set of CFMs/CFCs found within your /CFIDE/componentutils folder. Unlike most of the CF code that ships in /CFIDE these files are unencrypted. This means you can open up the Application.cfm file and do whatever you want. So for example, you can cflocate to a 404 handler based on whatever rules you have in mind.

p.s. Technically - just because you've locked down a CFC's auto descriptor does not mean you've really locked it down. Consider my CFC above where I auto set a method. If I add ?wsdl to the end I get the WSDL for the component. This will describe all the remote functions of the CFC. You could do something like this:

if(cgi.query_string == "wsdl") abort;

Which throws an error when CF tries to generate the WSDL code. The error may be preferable to you though. Would it would be nice if you could turn off the auto descriptor/auto Web Service support?

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by todd sharp posted on 12/20/2010 at 8:07 PM

I hate to even mention because I would never, ever do it, but you could technically add something like this to WEB-INF.cftags.component which every CFC extends.

Comment 2 by Henry posted on 12/20/2010 at 11:13 PM

How about IP restrict the /CFIDE/componentutils/ at webserver level?

Comment 3 by Raymond Camden posted on 12/20/2010 at 11:30 PM

I had mentioned that- but he wanted it to show up as a 404. Hence my thinking to use a CFIF and CFHEADER. Not sure if you can do that w/ IIS. You may be able to.

Comment 4 by todd sharp posted on 12/20/2010 at 11:34 PM

IIS 7.5 has built in URL rewriting so I'm sure something like this can be accomplished. Let me play around with it a bit and see what I can come up with.

Comment 5 by todd sharp posted on 12/21/2010 at 12:10 AM

I put it into a quick blog entry. Hope it helps.

http://cfsilence.com/blog/c...

Comment 6 by Damien Bruyndonckx posted on 12/21/2010 at 1:14 PM

For me, the best place to handle this in an application is the onCfcRequest Method of the Application framework... What do you think??

Comment 7 by Raymond Camden posted on 12/21/2010 at 6:25 PM

Interesting Damien! I didn't try that approach. Does it work?

Comment 8 by Raymond Camden posted on 12/21/2010 at 6:57 PM

Nope - just tested this and it did not work. I used this in my Application.cfc:

public void function onCFCRequest(string cfcname, string method, struct args) {
if(!structKeyExists(url, "method")) url.method = "foo";
}

I then requested /test.cfc and it didn't auto set the method.

Comment 9 by Raymond Camden posted on 12/21/2010 at 6:59 PM

Now this is interesting. While onCFCRequest didn't fire, onRequestStart did. So if I set url.method there, it does indeed block the auto descriptor.

Comment 10 by Mike Collins posted on 12/21/2010 at 7:28 PM

What about the servlet mapping in the web.xml.

<servlet-mapping id="coldfusion_mapping_4">
<servlet-name>CFCServlet</servlet-name>
<url-pattern>*.cfc</url-pattern>
</servlet-mapping>

seems like removing that would work if you did not want url access to any cfcs.

One concern is stuff like http://www.coldfusionjedi.c...

but I don't know if that uses the .cfc mapping.

Needs testing, but might work.

Comment 11 by Raymond Camden posted on 12/21/2010 at 7:31 PM

I bet it would. Although I think the original guy I spoke to wanted to dynamically add this behavior - ie, if IP not in some range, do this.

Comment 12 by todd sharp posted on 12/21/2010 at 7:58 PM

FWIW IIS request blocking can handle IP address patterns.

Comment 13 by Tom Chiverton posted on 12/21/2010 at 9:36 PM

As could an Apache rewrite rule block to send requests elsewhere unless their from the right place...

Comment 14 by Aaron Neff posted on 12/28/2010 at 2:55 PM

@Mike,

Nice idea and I very much like the web.xml servlet mappings.

This isn't really directed at you and is SOT, but I wish url-pattern was more flexible.

Currently this is valid (where "go" is an extension-less _file_ in webroot):

<servlet-mapping>
<servlet-name>CfmServlet</servlet-name>
<url-pattern>/go/*</url-pattern>
</servlet-mapping>

That's nice for handling these URLs in onRequestStart(): http://www.mysite.com/go/st...
(note there's no file extension, like .cfm, in the URL)

That works fine, if no other site on the server is serving URL-accessible content from a root-level directory named "go". Thus I'd much prefer if the servlet spec allowed this:

<servlet-mapping>
<servlet-name>CfmServlet</servlet-name>
<url-pattern>http://www.mysite.com/go/*<...
</servlet-mapping>

Thanks,
-Aaron

Comment 15 by Mike Collins posted on 12/28/2010 at 7:18 PM

@Aaron,

I think you have a few options to route by domain:

1. Each site maps to its own web root and the JRun connector does look at the web root so that does get you close already. So /go* would always look at the relative site webroot.

2. Servlet Filters. Not sure what your end game is, but filters are a great way to do some conditional processing at this level.

3. URL rewrite in Apache or IIS. You could easily use rewrite rules to trigger any servlet mapping.

Comment 16 by Aaron Neff posted on 12/29/2010 at 4:49 AM

@Mike

Thanks very much for your follow-up. I'm trying to post a reply, but my comment keeps being blocked as spam. I've forwarded it to Ray, so hopefully he'll be able to post it for me.

Thanks again!,
-Aaron

Comment 17 by Aaron Neff posted on 12/29/2010 at 11:44 AM

@Mike,

Thank you very much for your follow-up. I'm unfamiliar with creating servlet "filters". But my issue with servlet "mappings" is 2-fold:

1. url-pattern cannot be domain-specific
2. config is only via /WEB-INF/web.xml

The problem with #1 is url-pattern could match a "folder" in one site, and match a "file" in another site.

Could a servlet filter allow the mapping to only be used when "_file_ exists"?

Example: mysite1.com/go?foo=bar versus mysite2.com/go/page.cfm
(mysite1.com has root-level extensionless file named "go", while mysite2.com has root-level directory named "go")

Currently, a /go/* mapping breaks mysite2.com's URL.

I have an idea for an enhancement to Application.cfc. I originally thought #1 would be a deal-breaker. However, if servlet mappings can be conditionally applied only to files, then there may still be a way.

If only this were possible:

<servlet-mapping>
<servlet-name>CfmServlet</servlet-name>
<url-pattern>/go/*</url-pattern>
<verify-file-exists>true</verify-file-exists>
</servlet-mapping>

Thanks again!,
-Aaron

Comment 18 by Aaron Neff posted on 12/30/2010 at 4:37 AM

By "I have an idea for an enhancement to Application.cfc", I was referring to something like:

THIS.extensionlessFileList = "/go,/foo/bar";

Where go, and bar, are extensionless CF files.

Not sure if this is possible, but just thought it'd be neat.

Thanks,
-Aaron

Comment 19 by Mike Collins posted on 1/5/2011 at 9:00 PM

@Aaron

a servlet filter could work, however I think you are really trying to route traffic to the correct server or webapp, which puts me at a router, or web server. I'd look at doing a reverse proxy with some rewrite rules that will change context roots (weapps) based on domain.