Next.JS security of directory structure and JSON secrets - security

I have a security question regarding the access of Next.JS directories, and their access requirements. I have a root folder that has my pages, public, src, styles, models folders. In the src folder I have a settings.json file that is a empty JavaScript object. The idea is that settings would be added to this file and accessed by api routes, to check settings that could be modified on this settings.json file... What I am wondering is if the client can actually somehow just read/access the src directory and get the settings.json file. I want to put secret key's here that way I can easily change secret keys without having to restart my server. So I could just update the secret key live, and have it applied to the settings.json file. Then the update would be live immediately and I don't have to change the environment variables and restart the server.
Is it safe to keep and use a json file in the src directory to store confidential data? If not, is there a way to keep and use a json file for this purpose?
Thanks for the help and info.

As juliomalves pointed out client code won't be able to access a directory or file that you have on the server with the exception of the public directory.
Next gives you the ability to serve static assets from [root]/public as documented here
Note: Only assets that are in the public directory at build time will be served by Next.js.
If this directory is ever renamed, these assets are no longer available from a client.
Note: Don't name the public directory anything else. The name cannot be changed and is the only directory used to serve static assets.
"I put a settings.json file right next to that .env file and required it in an api route, could the client somehow download that settings.json file without me purposely sending them the contents/file itself?"
The only way information can be served from an api route is by expressly creating a route to call res[ponse].send() (or res.json()) with data imported from that file. Api routes are not ever bundled on the client side and only ever exist on the server as noted here.
Any file inside the folder pages/api is mapped to /api/* and will be treated as an API endpoint instead of a page. They are server-side only bundles and won't increase your client-side bundle size.
"What I am wondering is if the client can actually somehow just read/access the src directory and get the settings.json file."
As noted above only assets in the /public directory are accessible as files by path. Directories are never accessible in Next as static assets. This is even pointed out in the source code.
send(req, path)
.on('directory', () => {
// We don't allow directories to be read.
const err: any = new Error('No directory access')
err.code = 'ENOENT'
reject(err)
})

Related

How to make the Rust Game of Life WebAssembly work as a static website?

I have gone through the tutorial for the Rust Game of Life and have a working game in a web browser, but it only works from the demo web server that comes bundled with it. I can start the server with npm start and it runs the webpack-dev-server on port 8080. When I access the site through that port, it works fine. However, if I try to copy the site to a web server like Apache, it does not load correctly. The error I am currently getting from it is:
Error importing `index.js`: TypeError: Error resolving module specifier “wasm-game-of-life”. Relative module specifiers must start with “./”, “../” or “/”. bootstrap.js:5:23
<anonymous> http://www.north-winds.org/gol/bootstrap.js:5
From the tutorial, the root of the website is a folder called www/ in the repository and the generated wasm module from the Rust program is placed under pkg/. There is a symbolic link from www/node_modules/wasm-game-of-life that points up to ../../pkg/ and I've replaced that symlink with an actual copy of the top-level pkg/ folder so that the website is entirely contained inside the www/ folder and then placed that folder on my website at http://www.north-winds.org/gol/, however, accessing it returns the error above. What do I need to modify to make it work stand-alone?
As I understand it, this WebAssembly Game-of-Life is basically a stand-alone client-side app and should not require anything beyond a web server that can provide static files with the appropriate mime-types attached. I don't see anything special that should be required. I did see mention of WebSockets somewhere, but I don't know why that is required for this app. I compared this to the "Hello, World" WebAssembly example for C from https://webassembly.org/ and it ended up with a .wasm file generated from the C source code, and a single JavaScript and HTML supporting file to execute it. The files worked correctly when simply copied to static web server location. This is what I'd like for the Rust example.
Some relevant code from the Rust Game-of-Life is as follows. The top-level HTML file includes this among other lines:
<script src="./bootstrap.js"></script>
The bootstrap JavaScript file contains only this:
import("./index.js")
.catch(e => console.error("Error importing `index.js`:", e));
And the index.js file that it references has this among other glue logic for the Wasm:
import { Universe, Cell } from "wasm-game-of-life";
// Import the WebAssembly memory at the top of the file.
import { memory } from "wasm-game-of-life/wasm_game_of_life_bg";
What's missing to make this work standalone?
The www and pkg folders contain the source files you need, but you do not have a static site yet. The create-wasm-app template uses Webpack, so you need to build the final output by running npm run build in the www folder. This will create a subfolder named dist which contains the actual static files that can be placed on your web server.

How to change the directory/file path of a file being served by Firebase?

I am currently hosting a static website through Firebase, but the one file being served (index.html) exists in my Mac computer's Public folder. Since I would like to serve other files, I want to move the index to a project folder that will contain future linked files (e.g. /public/my-project/index.html).
How would I go about updating the file path/directory?
In your project directory (the directory in which you run firebase deploy or firebase deploy --only hosting), open or create firebase.json and make sure it points to the correct public folder.
{
"hosting": {
"public": "public"
}
}
This is a relative path. If your project and your firebase.json are located in /projects/my-project, this will deploy everything in /projects/my-project/public.
All of this is set up automatically if you initialize your Firebase project with firebase init.
Since your project may contain lots of files that aren't supposed to be deployed (readme, node_modules, build scripts etc.), I'd recommend having a public folder inside the project folder, like described above. (You can, however, ignore files with the ignore option, but you'd like to keep this list of ignored files manageable.)
If you really don't want a public folder inside your project, you may try pointing to the current folder from your firebase.json:
{
"hosting": {
"public": "."
}
}
More information about hosting configuration: https://firebase.google.com/docs/hosting/full-config
I accidentally stumbled across the answer while tweaking my settings in Terminal, it was a lot simpler than I expected. For future reference to anyone who sees this,
Open Terminal, and enter firebase init (assuming you have node.js and firebase already installed).
Use your arrows keys to navigate down to the ○ Hosting option, press your spacebar to select, and Return/Enter key to proceed.
The question "What do you want to use as your public directory?" will prompt. Type your desired file path (i.e. public/my-project/public) and enter.
The question "Configure as a single-page app (rewrite all urls to /index.html)?" This is your choice and depends on your platform.
If a file named index.html already exists in that location, it will ask if you want to overwrite it and create a new one. Most likely, you will want to keep the existing index you have -- if this is the case, type n.
Make sure to also follow #nicoqh's valuable advice and differentiate between your public and private folders so that not all of your files end up getting deployed by Firebase.

Securing files in Google Cloud app engine (NodeJS)

I have created a small web application with NodeJS Express. Basically a webserver that has a 'webserver.properties' file. With a very basic app.yaml file.
After deploying it to Google Cloud by use of 'gcloud app deploy' I get the everything up and running.
However...when I open the following URL in the browser: https://webserverurl.com/webserver.properties , the webserver.properties file can be approached and is in turn downloaded immediately.
How can I prevent this from happening and make sure that such properties files are inaccessible from outside?
The problem is that when you use this line:
app.use('/', express.static(__dirname + '/'));
you are giving access to your root directory. See this for a definition of __dirname. If you want to give access to a specific folder you can do this:
Lets say your root directory is src and you fave a dir with static files called src/myfiles. In order to give acces to files in myfiles you can use this line:
app.use('/mypathname', express.static('myfiles'));
where:
'/mypathname' is the part pertaining your URL. In your case it would be https://webserverurl.com/mypathname/any-file-name.jpg
express.static('myfiles') is the name of your local dir.
See this guide.
Hope this helps

controlled access of classified files in laravel-4

I've read that files in the public folder are accessible via a web browser in Laravel. When I type in the path to files in my public folder, I don't see the file, unless I defined the path in the routes.
I am making a downloads page so that a user can download encrypted/classified materials via a from.
I do not want the ability for a user to access the files in any other way other than the download form or other controlled methods.
Do I need to create lets say a private folder and store the files their. If I do, will I still have access to the files in the back end?
Or are files in the public folder not accessible unless defined by the routes? If thats right could I just store the files under public?
Files under public folder are accessible by anyone, unless your webserver has a policy set to a particular directory.
If you are currently not able to access a file in your public folder is because, maybe, you are not writing the url correctly, ie:
A file in
/var/www/myapp/public/img/logo.png
Will be accessible via:
http://myapp.com/img/logo.png
Note that the public part of your folder is not present in your URL ONLY IF your webserver is correctly configured and your .htaccess file is in place and able to rewrite your URL.
For sensitive files, what you can do is to store them insite your app folder (or any other folder outside public), where just your application will have access to, something like this can be ok:
/var/www/myapp/app/storage/<create a new folder here>
And then, yes, create a route to read and present your secure files:
Route::get('readfile/{fileName}', ['before' => 'auth', 'use' => 'ReadFileController#read']);
The filter 'before' => 'auth' will assure that one not authenticated will never be able to access a file.
In your controller you could do something like this to check if one can see a file:
class ReadFileController extends Controller {
public function read($fileName)
{
if(Auth::user()->id == 1) // of course this is not a good way, just an example
{
return $this->getFile($fileName);
}
else
{
return Response::make(null, 403); // forbidden
}
}
private function getFile($fileName)
{
...
}
}
Also, you can use authentication "middelware" in your routes to add better access control.
Route::get('routeName', ['middleware' => 'auth', 'uses' =>'XController#action']);

How do you change the express static directories?

I am working on a development platform, I have code similar to the following:
app.use('/public', express.static( config.directory.public ));
The issue is that there are many (100s) of projects each with its own directory structure. The project will be selected via the URL:
http://localhost/dev/accounts
Where accounts is a project with its own directory tree and static public directory.
I do not want to run a separate copy of node for each project. Once a project has been selected via the URL then express needs to be reconfigured to serve files for that request.
However, that approach is probably not feasible because we may be working on many projects at the same time. So every request for static files would have to be processed according to the project URL. It seems to negate the benefit of static directories.
I think what I am after is a way to put variables into the directory path
http://localhost/dev/accounts
Would set a variable called prj = "accounts" and then somehow set express so that the root directory is "c:\projects\" + prj + "\public".
If I simply issue a new app.use(..) statement for every request I imagine bad things will happen.
Maybe I am better off just manually reading the file contents for each static request and sending the contents back.
Is there another way to approach this problem?
I'm not sure if I understood your question correctly, but express serves static files in file directories automatically for you. If you have a bunch of projects in some 'path/to/public' folder, you just need to do something like
app.use('/', express.static( __dirname + '/public' ));
That way, you just need to type some url like
http://localhost/project1
or
http://localhost/project2

Resources