In my current project I the ideas from the other replies a bit further.
The configuration is active, the code caring about the configuration is stupid (well, the part that asks about configuration, anyway). Here is how it's done:
I have a namespace, MyApp::Config. MyApp::Config::Env provides environment probing data (MyApp::Config::Env->under_test will look at $0 to see if it matches /t/.+\.t$/, or $ENV{HARNESS_ACTIVE}), for the other modules.
Then, each module on it's own uses the Env module to provide configuration.
For example, the MyApp::Config::DBI will, under test, select PostgreSQL or MySQL, depending on which is on right now. This is done by instantiating little objects that score themselves, and having a singleton class whose constructor will simply select the best scoring one of these.
Under production, the One True Database is chosen, and otherwise an error is generated.
This functionlity is important, IMHO, to make the app work well, but it doesn't belong in the Real Code. Given global variables, the flexibility is limited, though.
I do it by using class methods - Config::DBI->dbh delegates to the object that was chosen, asking it to make a new database handle.
This goes further though, I also have configurating objects. For example, I have a class which runs a command line program. It cares about the interaction with the program, but not the program itself. This program has some variations, depending on the input data, the environment, and so forth. The configurator objects uses MyApp::Config::Env to see what the command should be, and then when MyApp::Config::ThatProgram->configure($obj) is called, the $obj, which is responsible for posessing the app, is modified to suite the environment.
Separating configuration from logic has made my app pretty maintainable so far, with a lot of space to grow.
Basically, what I suggest is to stop passing around data, and make a central point to get configuration data from. If there are complexities with who gets what, then that central point should be smart to resolve these differences, and real code shouldn't care.
You don't lose any flexibility, but what you gain is simplicity of the important code. This comes at a cost - the configuration code might be leaning towards magic, or become complex, but usually this code is quite linear to write, and the clarity of the real logic is, IMHO, well worth it.
Ciao!