Skip to content

Commit a05bc9e

Browse files
committed
allowed-uris: Match whole schemes also when scheme is not followed by slashes
1 parent d3a85b6 commit a05bc9e

4 files changed

Lines changed: 63 additions & 1 deletion

File tree

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
synopsis: Option `allowed-uris` can now match whole schemes in URIs without slashes
3+
prs: 9547
4+
---
5+
6+
If a scheme, such as `github:` is specified in the `allowed-uris` option, all URIs starting with `github:` are allowed.
7+
Previously this only worked for schemes whose URIs used the `://` syntax.

src/libexpr/eval-settings.hh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@ struct EvalSettings : Config
6868
evaluation mode. For example, when set to
6969
`https://github.com/NixOS`, builtin functions such as `fetchGit` are
7070
allowed to access `https://github.com/NixOS/patchelf.git`.
71+
72+
Access is granted when
73+
- the URI is equal to the prefix,
74+
- or the URI is a subpath of the prefix,
75+
- or the prefix is a URI scheme ended by a colon `:` and the URI has the same scheme.
7176
)"};
7277

7378
Setting<bool> traceFunctionCalls{this, false, "trace-function-calls",

src/libexpr/eval.cc

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "memory-input-accessor.hh"
1919
#include "signals.hh"
2020
#include "gc-small-vector.hh"
21+
#include "url.hh"
2122

2223
#include <algorithm>
2324
#include <chrono>
@@ -599,6 +600,14 @@ void EvalState::allowAndSetStorePathString(const StorePath & storePath, Value &
599600
mkStorePathString(storePath, v);
600601
}
601602

603+
inline static bool isJustSchemePrefix(std::string_view prefix)
604+
{
605+
return
606+
!prefix.empty()
607+
&& prefix[prefix.size() - 1] == ':'
608+
&& isValidSchemeName(prefix.substr(0, prefix.size() - 1));
609+
}
610+
602611
bool isAllowedURI(std::string_view uri, const Strings & allowedUris)
603612
{
604613
/* 'uri' should be equal to a prefix, or in a subdirectory of a
@@ -611,8 +620,14 @@ bool isAllowedURI(std::string_view uri, const Strings & allowedUris)
611620
&& prefix.size() > 0
612621
&& hasPrefix(uri, prefix)
613622
&& (
623+
// Allow access to subdirectories of the prefix.
614624
prefix[prefix.size() - 1] == '/'
615-
|| uri[prefix.size()] == '/')))
625+
|| uri[prefix.size()] == '/'
626+
627+
// Allow access to whole schemes
628+
|| isJustSchemePrefix(prefix)
629+
)
630+
))
616631
return true;
617632
}
618633

tests/unit/libexpr/eval.cc

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,4 +103,39 @@ TEST(nix_isAllowedURI, file_url) {
103103
ASSERT_FALSE(isAllowedURI("file://", allowed));
104104
}
105105

106+
TEST(nix_isAllowedURI, github_all) {
107+
Strings allowed;
108+
allowed.push_back("github:");
109+
ASSERT_TRUE(isAllowedURI("github:", allowed));
110+
ASSERT_TRUE(isAllowedURI("github:foo/bar", allowed));
111+
ASSERT_TRUE(isAllowedURI("github:foo/bar/feat-multi-bar", allowed));
112+
ASSERT_TRUE(isAllowedURI("github:foo/bar?ref=refs/heads/feat-multi-bar", allowed));
113+
ASSERT_TRUE(isAllowedURI("github://foo/bar", allowed));
114+
ASSERT_FALSE(isAllowedURI("https://github:443/foo/bar/archive/master.tar.gz", allowed));
115+
ASSERT_FALSE(isAllowedURI("file://github:foo/bar/archive/master.tar.gz", allowed));
116+
ASSERT_FALSE(isAllowedURI("file:///github:foo/bar/archive/master.tar.gz", allowed));
117+
ASSERT_FALSE(isAllowedURI("github", allowed));
118+
}
119+
120+
TEST(nix_isAllowedURI, github_org) {
121+
Strings allowed;
122+
allowed.push_back("github:foo");
123+
ASSERT_FALSE(isAllowedURI("github:", allowed));
124+
ASSERT_TRUE(isAllowedURI("github:foo/bar", allowed));
125+
ASSERT_TRUE(isAllowedURI("github:foo/bar/feat-multi-bar", allowed));
126+
ASSERT_TRUE(isAllowedURI("github:foo/bar?ref=refs/heads/feat-multi-bar", allowed));
127+
ASSERT_FALSE(isAllowedURI("github://foo/bar", allowed));
128+
ASSERT_FALSE(isAllowedURI("https://github:443/foo/bar/archive/master.tar.gz", allowed));
129+
ASSERT_FALSE(isAllowedURI("file://github:foo/bar/archive/master.tar.gz", allowed));
130+
ASSERT_FALSE(isAllowedURI("file:///github:foo/bar/archive/master.tar.gz", allowed));
131+
}
132+
133+
TEST(nix_isAllowedURI, non_scheme_colon) {
134+
Strings allowed;
135+
allowed.push_back("https://foo/bar:");
136+
ASSERT_TRUE(isAllowedURI("https://foo/bar:", allowed));
137+
ASSERT_TRUE(isAllowedURI("https://foo/bar:/baz", allowed));
138+
ASSERT_FALSE(isAllowedURI("https://foo/bar:baz", allowed));
139+
}
140+
106141
} // namespace nix

0 commit comments

Comments
 (0)