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

Improve security of docker options in stack.yaml #260

Open
borsboom opened this issue Jun 10, 2015 · 7 comments
Open

Improve security of docker options in stack.yaml #260

borsboom opened this issue Jun 10, 2015 · 7 comments

Comments

@borsboom
Copy link
Contributor

Currently, if a user has docker installed and set up so their user can run it without sudo, it's possible to craft a stack.yaml that runs arbitrary commands as root. This is due to well-known security weaknesses with Docker and basically any arbitrary code you run on your system (like, say, downloading an executable or shell script, or building a Haskell package that uses TemplateHaskell) could also take advantage of it), so this is far from unique to stack.

That said, I'd like to at least close the hole with stack.yaml, so that if you're doing your builds in a Docker container security is improved. I propose to disallow the following settings in the project's stack.yaml (but still allow them in global/user stack.yamls and from the command-line).

  • run-args
  • mount
  • pass-host
  • database-path
  • auto-pull

Since a user may want to change these settings for a project, adding the option of a "local" project config inside .stack-work may be desirable (kind of like you can add extra git excludes in .git/extra/excludes).

In addition, any time a new image is encountered in a stack.yaml, an explicit action should be required to approve it with a big warning to not approve untrusted images. Anyone could craft a malicious image and point the repo setting to it, but I don't think we want to be in the business of whitelisting images.

I also considered using the docker run -u option to always start containers as a non-root user, but anyone could still craft an image that has an entrypoint which sudos to root, so that doesn't end up helping very much.

@gregwebs
Copy link
Contributor

More concretely, the attack scenario is: I clone a project because I want to patch a library, so I start by running stack build. Generally build systems have escape hatches to execute arbitrary code, but it is limited to the user's permission. If I have docker installed, the build process could escalate its privileges to root!

I think this is getting at a larger problem for library authors; there is a stack.yaml that you would check in and distribute, and there are stack.yaml settings that you only want to develop with. Probably STACK_ROOT is meant to solve this, but in this case it cannot solve a security issue.

I think it is better to not allow enabling docker from stack.yaml because it does not make sense to distribute that setting to other people. Enabling docker should be done some other way. Obviously env variables and cli options can be used, but eventually I may want to write that setting down and have it be automatically used. The approach we could take is to have a list of docker enabled projects in ~/.stack

@borsboom
Copy link
Contributor Author

Yes, that is exactly the scenario I was thinking of. Of course, stack itself doesn't really create this problem -- any library could have some TemplateHaskell that uses the same loophole to escalate its privileges even if you're using cabal-install.

We actually really do want to allow you to enable docker and set the image in the project's stack.yaml, because that way you can ensure that everyone on a team is using a precisely consistent build environment. This is, in fact, the primary purpose of the Docker support. However, any new image will require the user to perform an explicit "stack docker pull" so you can't accidentally end up running an unknown image.

@snoyberg snoyberg modified the milestone: First stable release (0.1.0.0?) Jun 10, 2015
@gregwebs
Copy link
Contributor

We actually really do want to allow you to enable docker and set the image in the project's stack.yaml, because that way you can ensure that everyone on a team is using a precisely consistent build environment. This is, in fact, the primary purpose of the Docker support. However, any new image will require the user to perform an explicit "stack docker pull" so you can't accidentally end up running an unknown image.

Restricting to not allow pulling an unknown image helps, but does not solve the problem unless the docker build commands that are automatically executed are restricted to just stack. Maybe this is already the case? I have no idea how the docker integration actually works at this point (I am hoping for some documentation).

@gregwebs
Copy link
Contributor

This may be a little off topic, but I created a shell script in my PATH called docker to override the docker command

#!/bin/bash -e
# The goal of this script is to maintain the security privileges of sudo
# Without having to constantly type "sudo"
exec sudo /usr/bin/docker "$@"

This seems like a much better solution that the docker group that gets widely used today. Maybe I am missing something.

@borsboom
Copy link
Contributor Author

unless the docker build commands that are automatically executed are restricted to just stack

That is correct, it the only thing it'll run automatically is stack.

And using that wrapper is an excellent idea. I'll mention that in the docs I'm working on.

@snoyberg snoyberg modified the milestones: Later improvements, First stable release (0.1.0.0?) Jun 16, 2015
@borsboom borsboom modified the milestones: Docker, Later improvements Jul 22, 2015
@borsboom borsboom modified the milestones: Docker, P3 Sep 12, 2015
@jwaldmann
Copy link

@gregwebs Does your method #260 (comment) really work?

I put such a script in my $PATH (at $HOME/.local/bin/docker) and then
the initial stack docker pull works, but for stack build I get

...
@(System/Process/Read.hs:306:3)
2017-01-03 13:47:47.461984: [debug] Creating process: /home/me/.local/bin/docker start -a -i d63ea057b976fb01939e1de2e05e6f04207113685593b02a27d9fa4a070f1558
@(System/Process/Run.hs:102:5)
pid1: /opt/host/bin/stack: createProcess: runInteractiveProcess: exec: permission denied (Permission denied)
...

I have stack --version : Version 1.3.2 x86_64 hpack-0.15.0, on Fedora 25, with docker from their distro.
I have no experience with docker, but at least sudo docker run ubuntu /bin/echo 'Hello world' does work for me.

@gregwebs
Copy link
Contributor

Works for me

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

No branches or pull requests

4 participants