ZeroNet allows for arbitrary websites to added to the client at random, without authentication or any checking that the user would actually want this.
For example, a website (on ZeroNet or elsewhere) could embed hidden image tags like this:
<img src='http://127.0.0.1:43110/1HeLLo4uzjaLetFx6NH3PMwFP3qbRbTf3D' style='display: none;'>
This triggers the user's client to automatically add the site.
I think there needs to be some sort of confirmation process that happens.
Do you have any suggestions to detect real browser opening?
It could be possible to check http headers, but I'm not sure how reliable it is when using less-known features like
<link rel="prefetch" href="http://127.0.0.1:43110/1HeLLo4uzjaLetFx6NH3PMwFP3qbRbTf3D">
Yeah, I don't believe it would be possible to catch all "fake" requests like that.
Though couldn't ZeroNet simply not add the site if it is not requested during a real user session, and if it is a real session, display a notification that a new site has been added?
There are legitimate reasons for requesting other websites content, after all, hotlinking is actually good on ZeroNet.
I definitely saw prompt on some ZN sites, like "This is new zite for you, do you want to add it and continue?". Would be nice to have it everywhere.
I have added some restriction, so loading site as image/prefetch should no longer work. https://github.com/HelloZeroNet/ZeroNet/commit/86b0046f287f1a24a9fcb216fd1a31ea49823ee6
It's not final solution, but better solution (testing if rendering and js execution available) needs more changes.
Looks like a good start. I'll investigate further & try to find more methods to break & fix this, though one that comes to mind is <iframe>.
Using X-Frame-Options header for page requests that do not have wrapper nonce can be a good idea. When a request includes a valid wrapper nonce, turn off this header. Requested site should not be seeded unless the request is valid, including having a valid wrapper nonce.
X-Frame-Options: SAMEORIGIN
The page can only be displayed in a frame on the same origin as the page itself.
However,
X-Frame-Options: DENY will break all ZeroNet links that do not have a target=_top attribute.ALLOW-FROM is not yet supported by Chrome.X-Frame-Options: ALLOW-FROM http://127.0.0.1:43110/1SitEAdDREssYkGmy3FdyNjEb1wsDagkPb/
The RFC says:
ALLOW-FROM (followed by a serialized-origin [RFC6454])
A browser receiving content with this header MUST NOT display this
content in a frame from any page with a top-level browsing context
of different origin than the specified origin. While this can
Ross & Gondrom Informational [Page 4]
RFC 7034 X-Frame-Options October 2013
expose the page to risks by the trusted origin, in some cases, it
may be necessary to allow the framing by content from other
domains.
The meaning of the term "serialized-origin" is given in [RFC6454].
If the ALLOW-FROM value is used, it MUST be followed by a valid
origin [RFC6454] (as a subset of the URI [RFC3986]).
Any data beyond the domain address (i.e., any data after the "/"
separator) is to be ignored.
A good news is that, the frame-ancestors directive from the Content-Security-Policy header "obsoletes the X-Frame-Options header." Some CSP directives only use the origin in given source list, ignoring the rest of the URI, but the host-source format seems to support paths.
Many CSP directives use a value consisting of a source list, defined in the ABNF grammar below.
source-list = *WSP [ source-expression *( 1*WSP source-expression ) *WSP ]
/ *WSP "'none'" *WSP
source-expression = scheme-source / host-source / keyword-source / nonce-source / hash-source
host-source = [ scheme-part "://" ] host-part [ port-part ] [ path-part ]
path-part = <path production from RFC 3986, section 3.3>
...
The
default-srcdirective sets a default source list for a number of directives. The syntax for the name and value of the directive are described by the following ABNF grammar:
directive-name = "default-src"
directive-value = source-list
A list of source list formats: https://www.w3.org/TR/CSP2/#source_list
A list of defined CSP directives: https://www.w3.org/TR/CSP2/#directives
A frame-ancestors example: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-ancestors

Started HTTP server on port 8000
127.0.0.1 - "GET /wrapper.html HTTP/1.1" 200 -
127.0.0.1 - "GET /site_a/?vaild_request HTTP/1.1" 200 -
Content-Security-Policy: frame-ancestors http://127.0.0.1:8000/wrapper.html http://127.0.0.1:8000/site_a/;
127.0.0.1 - "GET /site_a/?vaild_request HTTP/1.1" 200 -
Content-Security-Policy: frame-ancestors http://127.0.0.1:8000/wrapper.html http://127.0.0.1:8000/site_a/;
127.0.0.1 - "GET /site_b/ HTTP/1.1" 200 -
Content-Security-Policy: frame-ancestors http://127.0.0.1:8000/wrapper.html http://127.0.0.1:8000/site_b/;
I only allowed a site to be framed by the wrapper, and by itself. Setting it to "frame-ancestors http://127.0.0.1:8000/ http://127.0.0.1:8000/" + site_name + "/;", however, does not work.
Wrapper source code:
<html>
<head>
<style>
#inner-iframe {
width: 80vw;
height: 80vh;
}
</style>
</head>
<body>
<iframe src="about:blank" id="inner-iframe" sandbox="allow-forms allow-scripts allow-top-navigation allow-popups"></iframe>
<script>
document.getElementById('inner-iframe').src = 'site_a/?vaild_request';
</script>
</body>
</html>
Note that host-source will not match any IPv4 address other than 127.0.0.1, or any IPv6 address.
Most helpful comment
Yeah, I don't believe it would be possible to catch all "fake" requests like that.
Though couldn't ZeroNet simply not add the site if it is not requested during a real user session, and if it is a real session, display a notification that a new site has been added?
There are legitimate reasons for requesting other websites content, after all, hotlinking is actually good on ZeroNet.