ValidateSSHConfigOption validates one deployment SSH option before it is written to users' local SSH configs.
(key, value string)
| 783 | // ValidateSSHConfigOption validates one deployment SSH option before it is |
| 784 | // written to users' local SSH configs. |
| 785 | func ValidateSSHConfigOption(key, value string) error { |
| 786 | if key == "" { |
| 787 | return xerrors.New("ssh config option key must not be empty") |
| 788 | } |
| 789 | if strings.ContainsAny(key, "=\r\n\x00") || strings.ContainsFunc(key, unicode.IsSpace) { |
| 790 | return xerrors.Errorf("ssh config option key %q is invalid", key) |
| 791 | } |
| 792 | // These options are rejected because, written into a user's SSH config by a |
| 793 | // deployment, they can execute code, load shared libraries, or override |
| 794 | // Coder's managed SSH settings on the client machine. When extending this |
| 795 | // list, classify the directive against these categories; the newline and |
| 796 | // whitespace checks above already prevent multi-line injection, so only |
| 797 | // single-line dangerous directives belong here. |
| 798 | switch strings.ToLower(key) { |
| 799 | // Structural directives that escape Coder's managed block. |
| 800 | case "host", "match", "include", |
| 801 | // Directives that run an attacker-supplied command string. |
| 802 | "proxycommand", "localcommand", "permitlocalcommand", "remotecommand", "knownhostscommand", |
| 803 | // Directives that dlopen an attacker-controlled shared library. |
| 804 | "pkcs11provider", "securitykeyprovider", "smartcarddevice", |
| 805 | // Directives that execute a command for X11 authentication. |
| 806 | "xauthlocation": |
| 807 | return xerrors.Errorf("ssh config option %q is not allowed: it can execute code, load shared libraries, or override Coder's managed SSH settings on client machines", key) |
| 808 | // ProxyJump conflicts with Coder's managed ProxyCommand. |
| 809 | case "proxyjump": |
| 810 | return xerrors.Errorf("ssh config option %q is not allowed: it conflicts with Coder's managed ProxyCommand", key) |
| 811 | } |
| 812 | if strings.ContainsAny(value, "\r\n\x00") { |
| 813 | return xerrors.Errorf("ssh config option %q must not contain carriage return, newline, or NUL characters", key) |
| 814 | } |
| 815 | return nil |
| 816 | } |
| 817 | |
| 818 | // SessionLifetime refers to "sessions" authenticating into Coderd. Coder has |
| 819 | // multiple different session types: api keys, tokens, workspace app tokens, |
no test coverage detected