Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Way to disable go get import and enforce to use only defined import list #151

Open
rabits opened this issue Nov 25, 2023 · 3 comments · May be fixed by #152
Open

Way to disable go get import and enforce to use only defined import list #151

rabits opened this issue Nov 25, 2023 · 3 comments · May be fixed by #152
Assignees

Comments

@rabits
Copy link
Contributor

rabits commented Nov 25, 2023

Hi, question - trying to keep the execution environment of gomacro more controllable and allow only predefined packages to be usable, otherwise raise an error that the package is not allowed to be used. Is there any way to do this?

@cosmos72 cosmos72 self-assigned this Nov 26, 2023
@cosmos72
Copy link
Owner

cosmos72 commented Nov 26, 2023

There's currently no mechanism to disable import of third-party packages at runtime.
Implementing it would be very easy, just a few lines of code.

A word of warning: if you are thinking about using gomacro to create a "safe sandbox", where you can execute arbitrary untrusted Go code, disabling import of third-party packages is definitely not enough.

You also need to limit import of standard library packages to a set of white-listed packages - for example, you probably don't want os.Create() and exec.Cmd

Also, same-language sandboxes don't work very well: the Java Applet security disaster taught a harsh lesson on this topic.
Let me explain: gomacro is written in Go, and the Go code interpreted by it uses normal Go objects through gomacro code itself, through the reflect package and through Go runtime - all of them are written in Go.

A diagram would be:

+-------------+     +---------+     +---------+     +---------+     +------+
|  untrusted  |     |         |     | reflect |     |   Go    |     |      |
| interpreted | <-> | gomacro | <-> | package | <-> | runtime | <-> |  OS  |
|    code     |     |         |     |         |     |         |     |      |
+-------------+     +---------+     +---------+     +---------+     +------+

Starting from the right, the OS trusts the system calls it receives, i.e. (by default) it does not "sandbox" processes.
Similarly, the Go runtime trusts the function calls it receives and has no "sandbox" mechanism at all.
Idem for the reflect package: it trusts the caller of their functions, and has no "sandbox" mechanism at all.
Idem for gomacro itself: it trusts the code it interprets, and has no "sandbox" mechanism at all.

In theory, one can try adding a sandbox mechanism at some level,
but in this case the only effective one is at the OS level,
for example with Linux containers/chroot (which often have escapes) or better, BSD jails.

Adding a sandbox mechanism at any other level is not robust:
it's all Go code, and as soon as the untrusted interpreted code
manages to somehow put its hands on an "unsafe" value or type
(typically by inspecting the content of some "safe" value or type through reflection)
the sandbox has failed.

In other words, there is no language barrier, which is one of the few places where one can add a robust sandbox mechanism.

@rabits
Copy link
Contributor Author

rabits commented Nov 26, 2023

Oh yeah, no not-trusted logic execution is needed - just to not scare users, when by accident user will add some unsupported module import and gomacro would try to get it. Just trying to make the module-writers life a bit easier in the future. But could imagine how the complete whitelist of imports will be helpful in other projects to sandbox the logic.

Yeah I agree - any sandboxing is much more complex system, which involves the OS fortification, but let's look at the limitations of imports as just another tool to steer the user in the right direction. It should have a huge warning in docs, that this feature is not for executin ofg the untrusted code.

I would love to try my skills and add this import limit feature to the gomacro - but not sure how much it will take...

@rabits
Copy link
Contributor Author

rabits commented Nov 27, 2023

Oh, that was much easier than I expected! So, added #152 : I found that it's relatively easy to manipulate the imports.Packages map in case you want to disable some import functionality for the gomacro scripts. So in general case manipulation with imports.Packages (like removing not wanted or adding wanted package addresses there) and a simple variable BlockExternal in Importer and checking it in doImportPackagesOrError function will do the trick for me.

Also I noticed a possible need for Allow/Deny lists, so added them there as well - by default they are empty so should not penalty the performance much. But if you think it's too much - they are not needed for this particular issue I described, I will be good just with BlockExternal functionality.

Not quite sure if interp.Comp.CompGlobals.Importer.BlockExternal = true is a good interface (so feel free to suggest the better place), but works for me just fine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants