Skip to content

Paths for new resources are incorrectly generated by LDP POST #1228

Closed

Description

@Otto-AA

When trying to create a new folder via the solid-filemanager I get a 500 - Path must start with hostname (/otman.inrupt.net) with the new version on inrupt.net

I've made a POST to https://otman.inrupt.net/public with slug: my-folder, link: <http://www.w3.org/ns/ldp#BasicContainer>; rel="type" and Content-Type: text/turtle.
It responded with the status 500 and the statusText Path must start with hostname (/otman.inrupt.net).

Is this something we should change in the request setup or an error inside NSS?

Here are the complete request headers (except for bearer token and connect.sid cookie):

POST /public HTTP/1.1
Host: otman.inrupt.net
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:67.0) Gecko/20100101 Firefox/67.0
Accept: */*
Accept-Language: en,en-US;q=0.7,de;q=0.3
Accept-Encoding: gzip, deflate, br
link: <http://www.w3.org/ns/ldp#BasicContainer>; rel="type"
slug: my-folder
Content-Type: text/turtle
authorization: Bearer  {...}
Origin: https://solid-filemanager.solid.community
Content-Length: 0
DNT: 1
Connection: keep-alive
Referer: https://solid-filemanager.solid.community/public/nightly/?url=https://otman.inrupt.net/public
Cookie: connect.sid=s%3 { ... }
Pragma: no-cache
Cache-Control: no-cache

And the response headers:

HTTP/1.1 500 Internal Server Error
X-Powered-By: solid-server/5.1.5
Access-Control-Allow-Origin: https://solid-filemanager.solid.community
Vary: Accept, Authorization, Origin
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: Authorization, User, Location, Link, Vary, Last-Modified, ETag, Accept-Patch, Accept-Post, Updates-Via, Allow, WAC-Allow, Content-Length, WWW-Authenticate
Allow: OPTIONS, HEAD, GET, PATCH, POST, PUT, DELETE
Link: <public.acl>; rel="acl", <public.meta>; rel="describedBy", <http://www.w3.org/ns/ldp#Resource>; rel="type"
Content-Type: text/plain; charset=utf-8
Content-Length: 50
ETag: W/"32-fmcIjz1GGt/H6AvpCi6o3nXP7kw"
Set-Cookie: connect.sid=s%3 {...}; Domain=.inrupt.net; Path=/; Expires=Sun, 16 Jun 2019 05:44:04 GMT; HttpOnly; Secure
Date: Sat, 15 Jun 2019 05:44:04 GMT
Connection: keep-alive

Activity

  1. jaxoncreed commented on Jun 17, 2019

    @jaxoncreed
    Contributor

    I believe I know what's causing this @Otto-AA . This is probably a good first issue to get involved with the Node Solid Server maintenance team.

    If you're interested, I'd love to hop on a call with you so we can fix it together!

  2. Otto-AA commented on Jun 17, 2019

    @Otto-AA
    ContributorAuthor

    I would really love to get more involved into this project, but I am too occupied by other projects and work currently. Therefore I have to gratefully decline your offer for now. If I find more time in the future I will maybe come back to this project though.

  3. self-assigned this
    on Jun 19, 2019
  4. michielbdejong commented on Jun 20, 2019

    @michielbdejong
    Member

    Was able to reproduce this on dev.inrupt.net with:

    curl 'https://michielbdejong.dev.inrupt.net/public/' -H 'Cookie: connect.sid=...' -H 'slug: my-folder' -X 'POST'

    (you can get a valid cookie by logging in to the data browser, going to the network pane in the dev tools, and selecting 'copy as curl' on one of the xhr requests)

  5. michielbdejong commented on Jun 20, 2019

    @michielbdejong
    Member

    In fact it also happens if you leave out the -H 'slug: my-folder'

  6. michielbdejong commented on Jun 20, 2019

    @michielbdejong
    Member

    @RubenVerborgh could this have been caused your recent refactor?

  7. RubenVerborgh commented on Jun 20, 2019

    @RubenVerborgh
    Contributor

    No refactor happened, but yes, a fix for one bug was added (#1227).

    The fix itself is probably not faulty; rather, the code calling this function was (and has always been) at fault, but it went undetected before the fix. Would need a stack trace to pinpoint.

  8. michielbdejong commented on Jun 20, 2019

    @michielbdejong
    Member

    No refactor happened

    I was referring to the ResourceMapper refactor (#1213), which we know also caused the bug that #1227 fixed.

    Would need a stack trace to pinpoint.

    The following suggests this is indeed a problem with the ResourceMapper:

    ~/gh/solid/node-solid-server $ grep -r Path\ must\ start\ with\ hostname lib/
    lib//resource-mapper.js:        throw new Error(`Path must start with hostname (/${hostname})`)

    To reproduce on localhost, run in multi-user mode (need to run ./bin/solid-test init), start the server, then visit https://localhost:8443, register a user, for instance 'michielbdejong', add e.g. '127.0.0.1 michielbdejong.localhost' in your /etc/hosts, then do:

    ~/gh/solid/node-solid-server $ curl -k -X POST https://michielbdejong.localhost:8443/inbox/
    Path must start with hostname (/michielbdejong.localhost)
  9. michielbdejong commented on Jun 20, 2019

    @michielbdejong
    Member

    Maybe we should just revert to the code from before #1213?

  10. RubenVerborgh commented on Jun 20, 2019

    @RubenVerborgh
    Contributor

    No. See above answer.

    The following suggests this is indeed a problem with the ResourceMapper:

    It shows that the error is thrown by ResourceMapper. ResourceMapper will correctly throw that error when called with the wrong arguments. Hence my request for a stack trace.

  11. michielbdejong commented on Jun 20, 2019

    @michielbdejong
    Member
      solid:server Error page because of: Error: Path must start with hostname (/michielbdejong.localhost)
        at ResourceMapper.mapFileToUrl (/Users/michiel/gh/solid/node-solid-server/lib/resource-mapper.js:74:15)
        at LDP.post (/Users/michiel/gh/solid/node-solid-server/lib/ldp.js:157:68) +1ms
  12. michielbdejong commented on Jun 20, 2019

    @michielbdejong
    Member

    lib/ldp.js is calling this.resourceMapper.mapFileToUrl with:

    {
      resourcePath: '/inbox/afaf3830-9355-11e9-850a-2f6182efecf6',
      host: 'michielbdejong.localhost'
    }
  13. michielbdejong commented on Jun 20, 2019

    @michielbdejong
    Member

    The "do not expose root path" refactor changed that resourcePath value there from
    this.resourceMapper.rootPath + resourcePath to just resourcePath, so looks like that's triggering the 'Path must start with hostname' error.

  14. RubenVerborgh commented on Jun 20, 2019

    @RubenVerborgh
    Contributor

    The "do not expose root path" refactor changed that resourcePath value there from
    this.resourceMapper.rootPath + resourcePath to just resourcePath, so looks like that's triggering the 'Path must start with hostname' error.

    Indeed. And in doing so, it is catching a bug that was present in the original code, but went unnoticed. So the error is doing its job 🙂

    Historical note: ResouceMapper was introduced a year ago, as a way to finally have all knowledge about URL/filesystem correspondence in one place, as a solution to it being implemented 20 times in 10 different and incompatible ways.
    However, ResourceMapper was then extended to leak its abstraction, such that the supposedly internal knowledge was once again spreading through the code. #1213 restored the original intention.

    Now the change from this.resourceMapper.rootPath + resourcePath to resourcePath was correct (given the updated method): the (semantically) equivalent parameters are ultimately passed to the method. It is just that the original code was wrong in the first place, but this went unnoticed because there was no path correctness check—and now there is.

    Let me show where it goes wrong:
    this.resourceMapper.rootPath + resourcePath will result in /var/solid/data + /inbox/afaf3830-9355-11e9-850a-2f6182efecf6 and thus /var/solid/data/inbox/afaf3830-9355-11e9-850a-2f6182efecf6 instead of the correct (assuming multi-user mode) /var/solid/data/michielbdejong.localhost/inbox/afaf3830-9355-11e9-850a-2f6182efecf6. This is precisely the error that is being thrown now, as opposed to going silent.

    So if this code was actually used as above, then I expect to see lots of random folders under /var/solid/data on different servers (if mkdir -p was ultimately used); and/or a privilege escalation security bug where people could write to random people's folders by sending a POST to /michielbdejong.localhost/private/ (let's hope this did not happen).

    All of the above showing why one component and one component only should implement file to URL mapping.

    Now the question, how to fix this bug?

    Looking at the code it seems that the call to mapFileToUrl is wrong to begin with, because there never was a file in the first place. Instead, it should probably be something like url.resolve(container, resourcePath) (assuming here that container is the URL of the container, not sure).

  15. RubenVerborgh commented on Jun 20, 2019

    @RubenVerborgh
    Contributor

    (Not to mention that the contentType hack is terrible too.)

  16. RubenVerborgh commented on Jun 20, 2019

    @RubenVerborgh
    Contributor

    @jaxoncreed Key to getting this right will be clearly differentiating between what is a file path (naming suggestion: end with path, do unsure if properly applied in existing code), and what is a URL. Code should either path.resolve files against existing folders, url.resolve URLs against existing URLs, or take absolute file paths or URLs and pass them to ResourceMapper. All else will lead to bugs.

  17. changed the title [-]500 - Path must start with hostname[/-] [+]Paths for new resources are incorrectly generated by LDP POST[/+] on Jun 20, 2019
  18. added a commit that references this issue on Jun 26, 2019
  19. jaxoncreed commented on Jun 28, 2019

    @jaxoncreed
    Contributor

    This should be fixed

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

Metadata

Metadata

Assignees

Labels

triageIssues that need team review

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions