CommandBox 5.2.0 added a new feature called Server Profiles which allow you to dial in a bevy of development or production lockdown rules in a single setting.  Each profile can be tweaked with individual settings to customize them.

  "profile": "production"
  "web": {
    "blockCFAdmin": false

Override parts of a default lockdown

However, what if you want to go one step deeper?  For instance, the "blockSensitivePaths" setting blocks a whole bunch of stuff all in one shot.  Turning on web.blockSensitivePaths is the same as adding all of these individual rules:

// track and trace verbs can leak data in XSS attacks
"disallowed-methods( methods={trace,track} )",
// Common config files and sensitive paths in ACF and TestBox
"regex( pattern='.*/(box.json|server.json|web.config|urlrewrite.xml|package.json|package-lock.json|Gulpfile.js|CFIDE/multiservermonitor-access-policy.xml|CFIDE/probe.cfm|CFIDE/main/ide.cfm|tests/runner.cfm|testbox/system/runners/HTMLRunner.cfm)', case-sensitive=false ) -> { set-error(404); done }",
// Any file or folder starting with a period
"regex('/\.') -> { set-error( 404 ); done }",
// Additional serlvlet mappings in Adobe CF's web.xml
"path-prefix( { '/JSDebugServlet','/securityanalyzer','/WSRPProducer' } ) -> { set-error( 404 ); done }",
// java web service (Axis) files
"regex( pattern='\.jws$', case-sensitive=false ) -> { set-error( 404 ); done }"

I had a question from a client today who wants to keep the blockSensitivePaths setting active for his servers, but also wanted to open up JUST the RDS IDE integration for his developers, which funnels through the /CFIDE/main/ide.cfm path which you can see is blocked above.

Order of Server Rule Execution

The solution to this is quite simple and is all based on the ORDER in which your rules are processed as documented here:

  1. Ad-hoc rule array in server.json
  2. External rules files in server.json in the order defined
  3. Ad-hoc rule array in config setting server.defaults
  4. External rules files in config setting server.defaults in the order defined
  5. CommandBox built-in rules (web.blockCFAdmin, web.blockConfigPaths)
  6. Any module listening to server interceptions can inject their rules wherever they please in the array.

You can see that the built-in CommadBox rules are the last to process.  This means that if you highjack the predicates with a custom rule FIRST, you can override the behavior of the built in rules. 

Add a Custom Server Rule

So, if we want to allow access to the /CFIDE/main/ide.cfm path, we just need to add a custom rule that matches that path and then aborts the predicate chain so no further rules fire.  

server set web.rules="['path(/CFIDE/main/ide.cfm)->done']" --append

Which gives you the following server.json


The "done" handler is what bypasses all subsequent rules for the request.  Read more about how server rules work here:

And a fair warning-- since your custom rules are processed BEFORE the built-in rules, that also means that you have the ability to accidentally bypass security rules by applying another rule that intercepts the request.  By default a custom rule won't block subsequent rules from firing unless you rewrite the request or use the special "done" handler.

Debugging Server Rules

And to test/debug your rules, start your server with the trace flag and tail the console output.  Every hit in your browser will output several lines of debugging for each rule that is processed.

server start --trace --console

With the custom rule above, you'd see something like this:

[DEBUG] requested: '/CFIDE/main/ide.cfm'
[TRACE] io.undertow.predicate: Path(s) [/CFIDE/main/ide.cfm] MATCH input [/CFIDE/main/ide.cfm] for HttpServerExchange{ GET /CFIDE/main/ide.cfm}.
[TRACE] io.undertow.predicate: Predicate [path( '/CFIDE/main/ide.cfm' )] resolved to true. Next handler is [done] for HttpServerExchange{ GET /CFIDE/main/ide.cfm}.
[TRACE] io.undertow.predicate: Predicate chain marked done. Next handler is [Runwar PathHandler] for HttpServerExchange{ GET /CFIDE/main/ide.cfm}.
[WARN ] responded: Status Code 200 (/CFIDE/main/ide.cfm)