Use vm.runInNewContext to run scripts

This commit is contained in:
Jonathan Clem 2020-01-10 06:16:33 -05:00
parent 5bc9a17b5e
commit d17db37305
No known key found for this signature in database
GPG key ID: B3662C4A8F843179
4 changed files with 100 additions and 9 deletions

1
.gitattributes vendored Normal file
View file

@ -0,0 +1 @@
dist/index.js linguist-generated=true

49
.github/workflows/test.yml vendored Normal file
View file

@ -0,0 +1,49 @@
on:
pull_request: {branches: master}
push: {branches: master}
repository_dispatch:
name: Test
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- id: run-script
uses: ./
with:
github-token: ${{secrets.GITHUB_TOKEN}}
result-encoding: string
script: |
const crypto = require('crypto')
const {promisify} = require('util')
const randomBytes = promisify(crypto.randomBytes)
const repo = await github.repos.get({
owner: 'actions',
repo: 'github-script'
})
console.log('repo.url', repo.url)
console.log('context.eventName', context.eventName)
console.log('input.result-encoding', actions.core.getInput('result-encoding'))
const bytes = await randomBytes(16)
return bytes.toString('hex')
- uses: ./
name: Invalid token
continue-on-error: true
with:
github-token: ${{secrets.GITHUB_TOKEN}}
script: |
#
- uses: ./
name: Throw error
continue-on-error: true
with:
github-token: ${{secrets.GITHUB_TOKEN}}
script: |
throw new Error('Whoops!')
- run: |
echo OUTPUT: ${{steps.run-script.outputs.result}}

32
dist/index.js generated vendored
View file

@ -1479,6 +1479,8 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var _actions_core__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_actions_core__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _actions_core__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_actions_core__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _actions_github__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(469); /* harmony import */ var _actions_github__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(469);
/* harmony import */ var _actions_github__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_actions_github__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var _actions_github__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_actions_github__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var vm__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(184);
/* harmony import */ var vm__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(vm__WEBPACK_IMPORTED_MODULE_2__);
var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) { return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
@ -1489,11 +1491,11 @@ var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _argume
}; };
process.on('unhandledRejection', handleError); process.on('unhandledRejection', handleError);
main().catch(handleError); main().catch(handleError);
function main() { function main() {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
const AsyncFunction = Object.getPrototypeOf(() => __awaiter(this, void 0, void 0, function* () { })).constructor;
const token = _actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput('github-token', { required: true }); const token = _actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput('github-token', { required: true });
const debug = _actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput('debug'); const debug = _actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput('debug');
const userAgent = _actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput('user-agent'); const userAgent = _actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput('user-agent');
@ -1505,10 +1507,18 @@ function main() {
opts.userAgent = userAgent; opts.userAgent = userAgent;
if (previews != null) if (previews != null)
opts.previews = previews.split(','); opts.previews = previews.split(',');
const client = new _actions_github__WEBPACK_IMPORTED_MODULE_1__.GitHub(token, opts); const github = new _actions_github__WEBPACK_IMPORTED_MODULE_1__.GitHub(token, opts);
const script = _actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput('script', { required: true }); const script = _actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput('script', { required: true });
const fn = new AsyncFunction('require', 'github', 'context', script); const fn = wrapFunction(script);
const result = yield fn(__webpack_require__(875), client, _actions_github__WEBPACK_IMPORTED_MODULE_1__.context); const result = yield vm__WEBPACK_IMPORTED_MODULE_2__.runInNewContext(fn, {
github,
console,
context: _actions_github__WEBPACK_IMPORTED_MODULE_1__.context,
actions: { core: _actions_core__WEBPACK_IMPORTED_MODULE_0__ },
require: __webpack_require__(875) // Otherwise, the build step will compile this incorrectly.
}, {
lineOffset: -1
});
let encoding = _actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput('result-encoding'); let encoding = _actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput('result-encoding');
encoding = encoding ? encoding : 'json'; encoding = encoding ? encoding : 'json';
let output; let output;
@ -1525,6 +1535,11 @@ function main() {
_actions_core__WEBPACK_IMPORTED_MODULE_0__.setOutput('result', output); _actions_core__WEBPACK_IMPORTED_MODULE_0__.setOutput('result', output);
}); });
} }
function wrapFunction(fn) {
return `(async function() {
${fn}
})()`;
}
function handleError(err) { function handleError(err) {
console.error(err); console.error(err);
if (err && err.message) { if (err && err.message) {
@ -1689,6 +1704,13 @@ module.exports = opts => {
}; };
/***/ }),
/***/ 184:
/***/ (function(module) {
module.exports = require("vm");
/***/ }), /***/ }),
/***/ 190: /***/ 190:
@ -11312,4 +11334,4 @@ function onceStrict (fn) {
/******/ }(); /******/ }();
/******/ /******/
/******/ } /******/ }
); );

View file

@ -1,11 +1,11 @@
import * as core from '@actions/core' import * as core from '@actions/core'
import {context, GitHub} from '@actions/github' import {context, GitHub} from '@actions/github'
import * as vm from 'vm'
process.on('unhandledRejection', handleError) process.on('unhandledRejection', handleError)
main().catch(handleError) main().catch(handleError)
async function main() { async function main() {
const AsyncFunction = Object.getPrototypeOf(async () => {}).constructor
const token = core.getInput('github-token', {required: true}) const token = core.getInput('github-token', {required: true})
const debug = core.getInput('debug') const debug = core.getInput('debug')
const userAgent = core.getInput('user-agent') const userAgent = core.getInput('user-agent')
@ -14,10 +14,23 @@ async function main() {
if (debug === 'true') opts.log = console if (debug === 'true') opts.log = console
if (userAgent != null) opts.userAgent = userAgent if (userAgent != null) opts.userAgent = userAgent
if (previews != null) opts.previews = previews.split(',') if (previews != null) opts.previews = previews.split(',')
const client = new GitHub(token, opts) const github = new GitHub(token, opts)
const script = core.getInput('script', {required: true}) const script = core.getInput('script', {required: true})
const fn = new AsyncFunction('require', 'github', 'context', script) const fn = wrapFunction(script)
const result = await fn(require, client, context)
const result = await vm.runInNewContext(
fn,
{
github,
console,
context,
actions: {core},
require: require // Otherwise, the build step will compile this incorrectly.
},
{
lineOffset: -1
}
)
let encoding = core.getInput('result-encoding') let encoding = core.getInput('result-encoding')
encoding = encoding ? encoding : 'json' encoding = encoding ? encoding : 'json'
@ -38,6 +51,12 @@ async function main() {
core.setOutput('result', output) core.setOutput('result', output)
} }
function wrapFunction(fn: string) {
return `(async function() {
${fn}
})()`
}
function handleError(err: any) { function handleError(err: any) {
console.error(err) console.error(err)