Mirror: A maybe slightly safer-ish wrapper around eval Function constructors

Compare changes

Choose any two refs to compare.

Changed files
+52 -4
.github
workflows
src
+26
.github/workflows/mirror.yml
···
···
+
# Mirrors to https://tangled.sh/@kitten.sh (knot.kitten.sh)
+
name: Mirror (Git Backup)
+
on:
+
push:
+
branches:
+
- main
+
jobs:
+
mirror:
+
runs-on: ubuntu-latest
+
steps:
+
- name: Checkout repository
+
uses: actions/checkout@v4
+
with:
+
fetch-depth: 0
+
fetch-tags: true
+
- name: Mirror
+
env:
+
MIRROR_SSH_KEY: ${{ secrets.MIRROR_SSH_KEY }}
+
GIT_SSH_COMMAND: 'ssh -o StrictHostKeyChecking=yes'
+
run: |
+
mkdir -p ~/.ssh
+
echo "$MIRROR_SSH_KEY" > ~/.ssh/id_rsa
+
chmod 600 ~/.ssh/id_rsa
+
ssh-keyscan -H knot.kitten.sh >> ~/.ssh/known_hosts
+
git remote add mirror "git@knot.kitten.sh:kitten.sh/${GITHUB_REPOSITORY#*/}"
+
git push --mirror mirror
+1 -1
package.json
···
"name": "evalish",
"description": "A maybe slightly safer-ish wrapper around eval Function constructors",
"DISCLAIMER": "Please maybe try something else first.. Please.",
-
"version": "0.1.7",
"main": "dist/evalish.js",
"module": "dist/evalish.mjs",
"types": "dist/types/index.d.ts",
···
"name": "evalish",
"description": "A maybe slightly safer-ish wrapper around eval Function constructors",
"DISCLAIMER": "Please maybe try something else first.. Please.",
+
"version": "0.1.8",
"main": "dist/evalish.js",
"module": "dist/evalish.mjs",
"types": "dist/types/index.d.ts",
+25 -3
src/index.ts
···
const _getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
const _defineProperty = Object.defineProperty;
const _create = Object.create;
type Object = Record<string | symbol, unknown>;
···
if (new.target === undefined) {
return target.apply(this, arguments);
} else {
-
return new (target.bind.apply(target, arguments));
}
})
: _create(null);
···
standin.prototype = _create(null);
}
-
return freeze(standin);
}
let safeGlobal: Record<string | symbol, unknown> | void;
···
// Lastly, we also disallow certain property accesses on the safe global
// Wrap any given target with a Proxy preventing access to unscopables
-
return freeze(safeGlobal!);
}
interface SafeFunction {
···
const _getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
const _defineProperty = Object.defineProperty;
const _create = Object.create;
+
const _slice = Array.prototype.slice;
type Object = Record<string | symbol, unknown>;
···
if (new.target === undefined) {
return target.apply(this, arguments);
} else {
+
const args = _slice.call(arguments);
+
args.unshift(null);
+
return new (target.bind.apply(target, args));
}
})
: _create(null);
···
standin.prototype = _create(null);
}
+
return toplevel ? standin : freeze(standin);
}
let safeGlobal: Record<string | symbol, unknown> | void;
···
// Lastly, we also disallow certain property accesses on the safe global
// Wrap any given target with a Proxy preventing access to unscopables
+
if (typeof Proxy === 'function') {
+
// Wrap the target in a Proxy that disallows access to some keys
+
return (safeGlobal = new Proxy(safeGlobal!, {
+
// Return a value, if it's allowed to be returned and mask this value
+
get(target, _key) {
+
const key = safeKey(target, _key);
+
return !ignore[_key] && key !== undefined ? target[key] : undefined;
+
},
+
has(_target, _key) {
+
return true;
+
},
+
set: noop,
+
deleteProperty: noop,
+
defineProperty: noop,
+
getOwnPropertyDescriptor: noop,
+
}));
+
} else {
+
// NOTE: Some property accesses may leak through here without the Proxy
+
return freeze(safeGlobal!);
+
}
}
interface SafeFunction {