{"id":19710010,"url":"https://github.com/reallyreally/reallysecure","last_synced_at":"2025-04-29T17:31:08.790Z","repository":{"id":38239373,"uuid":"83919902","full_name":"reallyreally/reallySecure","owner":"reallyreally","description":"ExpressJS Security Middleware","archived":false,"fork":false,"pushed_at":"2025-03-17T07:21:51.000Z","size":651,"stargazers_count":2,"open_issues_count":32,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-20T08:49:43.237Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/reallyreally.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-03-04T19:43:24.000Z","updated_at":"2022-06-08T20:31:59.000Z","dependencies_parsed_at":"2024-04-29T20:39:25.360Z","dependency_job_id":"f8026943-1a80-47c5-8428-1d72abaf4408","html_url":"https://github.com/reallyreally/reallySecure","commit_stats":{"total_commits":52,"total_committers":4,"mean_commits":13.0,"dds":0.6346153846153846,"last_synced_commit":"6724b7b654fc83c15e60e385d0b41340ae8e0521"},"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reallyreally%2FreallySecure","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reallyreally%2FreallySecure/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reallyreally%2FreallySecure/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reallyreally%2FreallySecure/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/reallyreally","download_url":"https://codeload.github.com/reallyreally/reallySecure/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251549175,"owners_count":21607365,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-11T22:05:53.483Z","updated_at":"2025-04-29T17:31:08.470Z","avatar_url":"https://github.com/reallyreally.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Known Vulnerabilities](https://snyk.io/test/github/reallyreally/reallySecure:package.json/badge.svg?targetFile=package.json)](https://snyk.io/test/github/reallyreally/reallySecure:package.json?targetFile=package.json)\n\n# ExpressJS Security Layer\n\nIntroduces comprehensive security for your ExpressJS based application.\n\n## Is this for you?\n\nThis package has been built for our specific needs. Your mileage may vary. Be very cautious enabling HSTS - do not turn it on unless you understand the implications for your domain and subdomains.\n\n### Prerequisites\n\nThis package is called while instantiating your ExpressJS based application. It is not a stand-alone package.\n\n### Glitch\n\nYou can check this out on [Glitch](https://glitch.com/edit/#!/really-secure) - see working code examples, and test it yourself without any effort!\n\n### Installing\n\nAssuming you are starting an ExpressJS project from scratch.\nCreate your ExpressJS project.\n\n```\nexpress --view=hbs --css=less --git my-secure-project\n```\n\nThen install ExpressJS\n\n```\ncd my-secure-project \u0026\u0026 npm install\n```\n\nThen install this package\n\n```\nnpm install --save @really/really-secure\n```\n\nNow you should be able to add it to your application layer\n\n## Using with ExpressJS\n\nIn your app.js require the package\n\n```\nvar securityLayer = require('@really/really-secure');\n```\n\nPrepare your configuration\n\n```\nvar reallySecureConfig = {\n  \"csp\": {\n    \"fontSrc\": [\"'self'\", \"use.typekit.net\"],\n    \"imgSrc\": [\"'self'\", \"data:\"],\n    \"defaultSrc\": [\"'self'\"],\n    \"reportUri\": \"/cspreport\",\n    \"upgradeInsecureRequests\": true\n  },\n  \"poweredBy\": \"A Secure Engine\"\n}\n```\n\nNow add it to the application flow\n\n```\n// Secure site\napp.use(securityLayer(reallySecureConfig));\n```\n\n**Using A Load Balancer? (Like Google App Engine)**\n\nYou will need to trust the proxy or you will end up with SSL issues.\n\n```\n// Trust App Engine proxy\napp.enable('trust proxy')\n```\n\n**A Node about NODE_ENV**\n\nMany of the security requirements that force or require SSL (like HSTS) are ignored unless you are `NODE_ENV=production`\nThis is a conscious choice to enable local development (without SSL) but retain security when deployed with little to no interaction.\n\n### Example app.js\n\nYour app.js may end up looking like this\n\n```\nvar express = require('express');\nvar path = require('path');\nvar favicon = require('serve-favicon');\nvar logger = require('morgan');\nvar cookieParser = require('cookie-parser');\nvar bodyParser = require('body-parser');\n\nvar securityLayer = require('@really/really-secure');\n\nvar index = require('./routes/index');\nvar users = require('./routes/users');\n\nvar app = express();\n\n// view engine setup\napp.set('views', path.join(__dirname, 'views'));\napp.set('view engine', 'hbs');\n\nvar reallySecureConfig = {\n  \"csp\": {\n    \"fontSrc\": [\"'self'\", \"use.typekit.net\"],\n    \"imgSrc\": [\"'self'\", \"data:\"],\n    \"defaultSrc\": [\"'self'\"],\n    \"reportUri\": \"/cspreport\",\n    \"upgradeInsecureRequests\": true\n  },\n  \"poweredBy\": \"A Secure Engine\"\n}\n\n// Secure site\napp.use(securityLayer(reallySecureConfig));\n\n// uncomment after placing your favicon in /public\n//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));\napp.use(logger('dev'));\napp.use(bodyParser.json());\napp.use(bodyParser.urlencoded({ extended: false }));\napp.use(cookieParser());\napp.use(require('less-middleware')(path.join(__dirname, 'public')));\napp.use(express.static(path.join(__dirname, 'public')));\n\napp.use('/', index);\napp.use('/users', users);\n\n// catch 404 and forward to error handler\napp.use(function(req, res, next) {\n  var err = new Error('Not Found');\n  err.status = 404;\n  next(err);\n});\n\n// error handler\napp.use(function(err, req, res, next) {\n  // set locals, only providing error in development\n  res.locals.message = err.message;\n  res.locals.error = req.app.get('env') === 'development' ? err : {};\n\n  // render the error page\n  res.status(err.status || 500);\n  res.render('error');\n});\n\nmodule.exports = app;\n\n```\n\n## Using a nonce\n\nFor your security pleasure - we generate a nonce for each request. Where your site has inline script or other elements, and those elements are inserted intentionally - you can use the nonce to validate the insertion.\n\nThe nonce is automatically added to all the CSP types, so no extra work is required here. The nonce value is available in `res.locals` - as `res.locals.nonce`.\n\nIf you are using handlebars - you might end up with something like this `layout.hbs` example. (Note the `\u003cscript nonce=\"{{ nonce }}\"\u003e`)\n\n```\n\u003c!doctype html\u003e\n\u003chtml class=\"no-js\" lang=\"en-US\"\u003e\n    \u003chead\u003e\n      \u003c!-- Google Tag Manager --\u003e\n      \u003cscript nonce=\"{{ nonce }}\"\u003e(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':\n      new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],\n      j=d.createElement(s),dl=l!='dataLayer'?'\u0026l='+l:'';j.async=true;j.src=\n      'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);\n      })(window,document,'script','dataLayer','GTM-A0A0000');\u003c/script\u003e\n      \u003c!-- End Google Tag Manager --\u003e\n        \u003cmeta charset=\"utf-8\"\u003e\n        \u003cmeta http-equiv=\"x-ua-compatible\" content=\"ie=edge\"\u003e\n        \u003ctitle\u003eExample Layout\u003c/title\u003e\n        \u003cmeta name=\"description\" content=\"\"\u003e\n        \u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1\"\u003e\n    \u003c/head\u003e\n    \u003cbody\u003e\n      \u003c!-- Google Tag Manager (noscript) --\u003e\n      \u003cnoscript\u003e\u003ciframe nonce=\"{{ nonce }}\" src=\"https://www.googletagmanager.com/ns.html?id=GTM-A0A0000\"\n      height=\"0\" width=\"0\" style=\"display:none;visibility:hidden\"\u003e\u003c/iframe\u003e\u003c/noscript\u003e\n      \u003c!-- End Google Tag Manager (noscript) --\u003e\n        \u003c!--[if lt IE 8]\u003e\n        \u003cp class=\"browserupgrade\"\u003eYou are using an \u003cstrong\u003eoutdated\u003c/strong\u003e browser. Please \u003ca href=\"http://browsehappy.com/\"\u003eupgrade your browser\u003c/a\u003e to improve your experience.\u003c/p\u003e\n        \u003c![endif]--\u003e\n{{{body}}}\n    \u003c/body\u003e\n\u003c/html\u003e\n```\n\n## Configuration\n\nApart from the example above - configuration is typically passed to each component. A more exhaustive example would be:\n\n```\n{\n  \"csp\":{\n    \"fontSrc\":[\n      \"'self'\",\n      \"fonts.gstatic.com\"\n    ],\n    \"imgSrc\":[\n      \"'self'\",\n      \"data:\",\n      \"platform.slack-edge.com\",\n      \"www.google-analytics.com\",\n      \"stats.g.doubleclick.net\",\n      \"www.google.com\"\n    ],\n    \"defaultSrc\":[\n      \"'self'\"\n    ],\n    \"reportUri\":\"/v1/cspreport\",\n    \"styleSrc\":[\n      \"'self'\",\n      \"fonts.googleapis.com\",\n      \"'sha256-tFH5KRmizb/+eruMkSeYor+UVhiMbPUtVTRTEMsQopc='\",\n      \"'sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU='\"\n    ],\n    \"scriptSrc\":[\n      \"'self'\",\n      \"www.googletagmanager.com\"\n    ],\n    \"upgradeInsecureRequests\":true\n  },\n  \"hsts\":{\n    \"maxAge\":10886400,\n    \"includeSubDomains\":true,\n    \"preload\":true,\n    \"force\":true\n  },\n  \"poweredBy\":\"really-secure\"\n}\n```\n\n**Another note about HSTS**\n\nThis example would activate HSTS. It is important that you only do this knowing what the implication for your whole domain / environment is. It will (for example) break Google's G Suite domain redirection if you use this on your base domain.\n\n## Versioning\n\nWe use [SemVer](http://semver.org/) for versioning. For the versions available, see the [tags on this repository](https://github.com/your/project/tags).\n\n## Authors\n\n* **Troy Kelly** - *Initial work* - [troykelly](https://github.com/troykelly)\n* **Daniel Walton** - [imdanwalton](https://github.com/imdanwalton)\n\nSee also the list of [contributors](https://github.com/reallyreally/reallySecure/contributors) who participated in this project.\n\n## License\n\nThis project is licensed under the Apache-2.0 License\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freallyreally%2Freallysecure","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freallyreally%2Freallysecure","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freallyreally%2Freallysecure/lists"}