├── .gitignore ├── LICENSE ├── README.md ├── binding.gyp ├── examples ├── ddg └── pp.js ├── index.js ├── package.json ├── pledge.cc ├── pledge_10x.cc ├── test.js └── version.js /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | node_modules/ 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Aaron Bieber 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any 4 | purpose with or without fee is hereby granted, provided that the above 5 | copyright notice and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | node-pledge 2 | =========== 3 | 4 | Bindings for for OpenBSD's [pledge(2)](http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man2/pledge.2?query=pledge) 5 | 6 | # What? 7 | 8 | `pledge(2)` allows a process to ratchet down the privileges it requires to run, if it attempts to access 9 | a privilege it has pledged to not use, it will be killed by the kernel. 10 | 11 | # Example Usage 12 | 13 | Install via npm: 14 | 15 | ``` 16 | npm install --save node-pledge 17 | ``` 18 | 19 | ```JavaScript 20 | var http = require('http'); 21 | var pledge = require('node-pledge'); 22 | 23 | pledge.init("stdio rpath wpath prot_exec"); 24 | 25 | console.log("stuff"); 26 | 27 | // try to do something with http (will cause the kernel to kill node) 28 | http.get("http://www.google.com/", function(res) { 29 | console.log(res); 30 | }).on('error', function(e) { 31 | console.log(e); 32 | }); 33 | ``` 34 | 35 | Output: 36 | 37 | ``` 38 | node stuff.js 39 | stuff 40 | Abort trap (core dumped) 41 | ``` 42 | 43 | Line from `dmesg(8)`: 44 | 45 | ``` 46 | node(24353): sysctl 6: 4 17 0 0 3 0 47 | node(24353): syscall 202 "" 48 | ``` 49 | 50 | # This is an expirement! 51 | 52 | Use at your own risk! It will *ONLY* work on OpenBSD! 53 | -------------------------------------------------------------------------------- /binding.gyp: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "target_name": "pledge", 5 | "sources": [ "pledge.cc" ] 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /examples/ddg: -------------------------------------------------------------------------------- 1 | var https = require('https'), 2 | url = require('url'), 3 | qs = require('querystring'), 4 | pledge = require('node-pledge'), 5 | ddg_url = 'https://api.duckduckgo.com/?format=json'; 6 | 7 | pledge.init('stdio rpath wpath cpath inet dns prot_exec'); 8 | 9 | var i = 2, l = process.argv.length, q = ''; 10 | for (; i < l; i++) { 11 | q += process.argv[i]; 12 | q += ' '; 13 | } 14 | 15 | var req = https.get(ddg_url + '&q=' + q, function(res) { 16 | var data = ''; 17 | res.on('data', function(chunk) { 18 | data += chunk; 19 | }); 20 | 21 | res.on('end', function() { 22 | pledge.init('stdio'); 23 | d = JSON.parse(data); 24 | if (d.Answer !== "" && typeof(d.Answer === "string")) { 25 | console.log(d.Answer); 26 | } else { 27 | console.log(d); 28 | } 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /examples/pp.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | // Quick example of a pledged node app. 4 | // usage: 5 | // $ echo '{"a":1,"b":3}' | ./pp.js 6 | 7 | var data = '', pledge = require('node-pledge'); 8 | pledge.init('stdio prot_exec rpath tty'); 9 | 10 | process.stdin.setEncoding('utf8'); 11 | process.stdin.on('readable', function() { 12 | var chunk = process.stdin.read(); 13 | if (chunk !== null) { 14 | data += chunk; 15 | } 16 | }); 17 | 18 | process.stdin.on('end', function() { 19 | data = JSON.parse(data); 20 | console.log(JSON.stringify(data, null, 2)); 21 | }); 22 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./build/Release/pledge'); 2 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-pledge", 3 | "version": "1.1.2", 4 | "description": "OpenBSD's pledge(2) extension for node.js", 5 | "main": "index.js", 6 | "engines" : { "node" : ">=4.2.0" }, 7 | "scripts": { 8 | "test": "node test.js", 9 | "install": "node-gyp rebuild" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/qbit/node-pledge.git" 14 | }, 15 | "keywords": [ 16 | "openbsd", 17 | "pledge" 18 | ], 19 | "author": "Aaron Bieber ", 20 | "license": "ISC", 21 | "gypfile": true, 22 | "bugs": { 23 | "url": "https://github.com/qbit/node-pledge/issues" 24 | }, 25 | "homepage": "https://github.com/qbit/node-pledge#readme" 26 | } 27 | -------------------------------------------------------------------------------- /pledge.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | namespace openbsdPledge { 8 | 9 | using v8::Exception; 10 | using v8::FunctionCallbackInfo; 11 | using v8::Isolate; 12 | using v8::Local; 13 | using v8::Object; 14 | using v8::String; 15 | using v8::Value; 16 | 17 | void Pledge(const FunctionCallbackInfo& args) { 18 | Isolate* isolate = args.GetIsolate(); 19 | 20 | if (args.Length() < 1) { 21 | isolate->ThrowException(Exception::TypeError( 22 | String::NewFromUtf8(isolate, "Wrong number of arguments", 23 | v8::NewStringType::kNormal).ToLocalChecked())); 24 | 25 | return; 26 | } 27 | 28 | if (!args[0]->IsString()) { 29 | isolate->ThrowException(Exception::TypeError( 30 | String::NewFromUtf8(isolate, "Wrong arguments", 31 | v8::NewStringType::kNormal).ToLocalChecked())); 32 | return; 33 | } 34 | 35 | const int num = pledge(*String::Utf8Value(isolate, args[0]), NULL); 36 | if (num == -1) { 37 | isolate->ThrowException(Exception::TypeError( 38 | String::NewFromUtf8(isolate, "Pledge Error", 39 | v8::NewStringType::kNormal).ToLocalChecked())); 40 | return; 41 | } 42 | 43 | args.GetReturnValue().Set(num); 44 | } 45 | 46 | void Init(Local exports) { 47 | NODE_SET_METHOD(exports, "init", Pledge); 48 | } 49 | 50 | NODE_MODULE(addon, Init) 51 | 52 | } // namespace openbsdPledge 53 | -------------------------------------------------------------------------------- /pledge_10x.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace v8; 7 | 8 | Handle Pledge(const Arguments& args) { 9 | HandleScope scope; 10 | 11 | if (args.Length() < 1) { 12 | ThrowException(Exception::TypeError(String::New("Wrong number of arguments"))); 13 | return scope.Close(Undefined()); 14 | } 15 | 16 | if (!args[0]->IsString()) { 17 | ThrowException(Exception::TypeError(String::New("Wrong arguments"))); 18 | return scope.Close(Undefined()); 19 | } 20 | 21 | const int num = pledge(*String::Utf8Value(args[0]), NULL); 22 | if (num == -1) 23 | err(1, "pledge"); 24 | 25 | return scope.Close(Number::New(num)); 26 | } 27 | 28 | void Init(Handle exports) { 29 | exports->Set(String::NewSymbol("init"), 30 | FunctionTemplate::New(Pledge)->GetFunction()); 31 | } 32 | 33 | NODE_MODULE(pledge, Init) 34 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | var http = require('http'); 2 | var pledge = require('./build/Release/pledge'); 3 | 4 | pledge.init("stdio rpath wpath ioctl"); 5 | console.log("stuff"); 6 | 7 | http.get("http://www.google.com/index.html", function(res) { 8 | console.log("Got response: " + res.statusCode); 9 | }).on('error', function(e) { 10 | console.log("Got error: " + e.message); 11 | }); 12 | -------------------------------------------------------------------------------- /version.js: -------------------------------------------------------------------------------- 1 | var s = require('semver'); 2 | var v = s.gt('v4.0.0', process.version); 3 | if (v) { 4 | console.log('yes'); 5 | } else { 6 | console.log('no'); 7 | } 8 | --------------------------------------------------------------------------------