GitHub PullRequestEvent at 2014-02-07 19:54:34
Repository: Plack
Actor: miyagawa
Payload: {"action":"closed","number":446,"pull_request":{"url":"https://api.github.com/repos/plack/Plack/pulls/446","id":12306670,"html_url":"https://github.com/plack/Plack/pull/446","diff_url":"https://github.com/plack/Plack/pull/446.diff","patch_url":"https://github.com/plack/Plack/pull/446.patch","issue_url":"https://api.github.com/repos/plack/Plack/issues/446","number":446,"state":"closed","title":"Plack::App::File: Fix a security issue by not pruning trailing slashes","user":{"login":"avar","id":45301,"avatar_url":"https://gravatar.com/avatar/57332d67a86eb51e06bf78d2baf42c3c?d=https%3A%2F%2Fidenticons.github.com%2F439d098c32d07e695014220aca9ed223.png&r=x","gravatar_id":"57332d67a86eb51e06bf78d2baf42c3c","url":"https://api.github.com/users/avar","html_url":"https://github.com/avar","followers_url":"https://api.github.com/users/avar/followers","following_url":"https://api.github.com/users/avar/following{/other_user}","gists_url":"https://api.github.com/users/avar/gists{/gist_id}","starred_url":"https://api.github.com/users/avar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/avar/subscriptions","organizations_url":"https://api.github.com/users/avar/orgs","repos_url":"https://api.github.com/users/avar/repos","events_url":"https://api.github.com/users/avar/events{/privacy}","received_events_url":"https://api.github.com/users/avar/received_events","type":"User","site_admin":false},"body":"Before this Plack::App::File would prune trailing slashes via its split\r\ninvocation. I.e. it would think this:\r\n\r\n    $ perl -MData::Dumper -wle 'print Dumper [split /[\\\\\\/]/, shift]' a/file.txt\r\n    $VAR1 = [\r\n              'a',\r\n              'file.txt'\r\n            ];\r\n\r\nWas the same as:\r\n\r\n    $ perl -MData::Dumper -wle 'print Dumper [split /[\\\\\\/]/, shift]' a/file.txt///\r\n    $VAR1 = [\r\n              'a',\r\n              'file.txt'\r\n            ];\r\n\r\nThis can. turn into a nasty code exposure issue if you e.g. have an app\r\nthat basically does this:\r\n\r\n    1. I'd do a regex /.txt.pl\\z/ on a file to see if it was a text file\r\n    2. If so, do magic to generate text file via perl\r\n    3. Else it's not a /.txt.pl\\z/ file, so it must be some other static\r\n       file with a different extension\r\n    4. Serve it up with Plack::Middleware::Static\r\n\r\nThis is also not how other webservers or Unix utilities work:\r\n\r\n    $ touch /tmp/foo.txt\r\n    $ file /tmp/foo.txt\r\n    /tmp/foo.txt: empty\r\n    $ file /tmp/foo.txt/\r\n    /tmp/foo.txt/: ERROR: cannot open `/tmp/foo.txt/' (Not a directory)\r\n\r\nThis resolves issue #405 that I filed around 9 months ago. I was\r\npreviously working around it in my own code by doing:\r\n\r\n    {\r\n        # Let's see if someone's trying to be evil by\r\n        # requesting e.g. /index.html/ instead of\r\n        # /index.html. We don't want to fall through\r\n        # and just serve up the raw content.\r\n        my $plack_app_file = Plack::App::File->new({ root => PLACK_WEBSERVER_DOCUMENT_ROOT() });\r\n        my ($file) = $plack_app_file->locate_file($env);\r\n        if (\r\n            # We'll get a reference if it's a full\r\n            # Plack response. I.e. a 404 or whatever.\r\n            ref $file ne 'ARRAY'\r\n            and\r\n            # WTF once we canonicalize the file and it\r\n            # looks like a Mason handled path let's\r\n            # not accept it, because we don't want to\r\n            # serve up the raw unprocessed Mason page\r\n            # via this hack.\r\n            $file =~ $mason_handles_this_path_rx\r\n        ) {\r\n            TELL \"Middleware::Static: Path <$path> request, doesn't match <$mason_handles_this_path_rx>, but actually resolves to it via resolved file <$file>\" if DEBUG;\r\n            # Tells our app to just serve up a\r\n            # 400. Apache would do a 404 but I think\r\n            # these requests are bad, so say so.\r\n            $env->{$magic_marker_to_return_400} = 1;\r\n            return;\r\n        }\r\n    }","created_at":"2014-02-07T10:30:54Z","updated_at":"2014-02-07T19:54:34Z","closed_at":"2014-02-07T19:54:34Z","merged_at":"2014-02-07T19:54:33Z","merge_commit_sha":"f49c8ecdd67fc7bccc32e8286735424363dd6952","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/plack/Plack/pulls/446/commits","review_comments_url":"https://api.github.com/repos/plack/Plack/pulls/446/comments","review_comment_url":"https://api.github.com/repos/plack/Plack/pulls/comments/{number}","comments_url":"https://api.github.com/repos/plack/Plack/issues/446/comments","statuses_url":"https://api.github.com/repos/plack/Plack/statuses/bc1731dbb53850c380875ad683cd87c8ec99eee3","head":{"label":"avar:avar/fix-issue-405","ref":"avar/fix-issue-405","sha":"bc1731dbb53850c380875ad683cd87c8ec99eee3","user":{"login":"avar","id":45301,"avatar_url":"https://gravatar.com/avatar/57332d67a86eb51e06bf78d2baf42c3c?d=https%3A%2F%2Fidenticons.github.com%2F439d098c32d07e695014220aca9ed223.png&r=x","gravatar_id":"57332d67a86eb51e06bf78d2baf42c3c","url":"https://api.github.com/users/avar","html_url":"https://github.com/avar","followers_url":"https://api.github.com/users/avar/followers","following_url":"https://api.github.com/users/avar/following{/other_user}","gists_url":"https://api.github.com/users/avar/gists{/gist_id}","starred_url":"https://api.github.com/users/avar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/avar/subscriptions","organizations_url":"https://api.github.com/users/avar/orgs","repos_url":"https://api.github.com/users/avar/repos","events_url":"https://api.github.com/users/avar/events{/privacy}","received_events_url":"https://api.github.com/users/avar/received_events","type":"User","site_admin":false},"repo":{"id":5693726,"name":"Plack","full_name":"avar/Plack","owner":{"login":"avar","id":45301,"avatar_url":"https://gravatar.com/avatar/57332d67a86eb51e06bf78d2baf42c3c?d=https%3A%2F%2Fidenticons.github.com%2F439d098c32d07e695014220aca9ed223.png&r=x","gravatar_id":"57332d67a86eb51e06bf78d2baf42c3c","url":"https://api.github.com/users/avar","html_url":"https://github.com/avar","followers_url":"https://api.github.com/users/avar/followers","following_url":"https://api.github.com/users/avar/following{/other_user}","gists_url":"https://api.github.com/users/avar/gists{/gist_id}","starred_url":"https://api.github.com/users/avar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/avar/subscriptions","organizations_url":"https://api.github.com/users/avar/orgs","repos_url":"https://api.github.com/users/avar/repos","events_url":"https://api.github.com/users/avar/events{/privacy}","received_events_url":"https://api.github.com/users/avar/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/avar/Plack","description":"PSGI toolkit and server adapters","fork":true,"url":"https://api.github.com/repos/avar/Plack","forks_url":"https://api.github.com/repos/avar/Plack/forks","keys_url":"https://api.github.com/repos/avar/Plack/keys{/key_id}","collaborators_url":"https://api.github.com/repos/avar/Plack/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/avar/Plack/teams","hooks_url":"https://api.github.com/repos/avar/Plack/hooks","issue_events_url":"https://api.github.com/repos/avar/Plack/issues/events{/number}","events_url":"https://api.github.com/repos/avar/Plack/events","assignees_url":"https://api.github.com/repos/avar/Plack/assignees{/user}","branches_url":"https://api.github.com/repos/avar/Plack/branches{/branch}","tags_url":"https://api.github.com/repos/avar/Plack/tags","blobs_url":"https://api.github.com/repos/avar/Plack/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/avar/Plack/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/avar/Plack/git/refs{/sha}","trees_url":"https://api.github.com/repos/avar/Plack/git/trees{/sha}","statuses_url":"https://api.github.com/repos/avar/Plack/statuses/{sha}","languages_url":"https://api.github.com/repos/avar/Plack/languages","stargazers_url":"https://api.github.com/repos/avar/Plack/stargazers","contributors_url":"https://api.github.com/repos/avar/Plack/contributors","subscribers_url":"https://api.github.com/repos/avar/Plack/subscribers","subscription_url":"https://api.github.com/repos/avar/Plack/subscription","commits_url":"https://api.github.com/repos/avar/Plack/commits{/sha}","git_commits_url":"https://api.github.com/repos/avar/Plack/git/commits{/sha}","comments_url":"https://api.github.com/repos/avar/Plack/comments{/number}","issue_comment_url":"https://api.github.com/repos/avar/Plack/issues/comments/{number}","contents_url":"https://api.github.com/repos/avar/Plack/contents/{+path}","compare_url":"https://api.github.com/repos/avar/Plack/compare/{base}...{head}","merges_url":"https://api.github.com/repos/avar/Plack/merges","archive_url":"https://api.github.com/repos/avar/Plack/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/avar/Plack/downloads","issues_url":"https://api.github.com/repos/avar/Plack/issues{/number}","pulls_url":"https://api.github.com/repos/avar/Plack/pulls{/number}","milestones_url":"https://api.github.com/repos/avar/Plack/milestones{/number}","notifications_url":"https://api.github.com/repos/avar/Plack/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/avar/Plack/labels{/name}","releases_url":"https://api.github.com/repos/avar/Plack/releases{/id}","created_at":"2012-09-05T21:15:52Z","updated_at":"2014-02-07T19:54:34Z","pushed_at":"2014-02-07T10:30:19Z","git_url":"git://github.com/avar/Plack.git","ssh_url":"git@github.com:avar/Plack.git","clone_url":"https://github.com/avar/Plack.git","svn_url":"https://github.com/avar/Plack","homepage":"http://plackperl.org/","size":5804,"stargazers_count":0,"watchers_count":0,"language":"Perl","has_issues":false,"has_downloads":true,"has_wiki":true,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master","master_branch":"master"}},"base":{"label":"plack:master","ref":"master","sha":"9c8a5bc1ea8750613767a70085e8d9eb522cfc94","user":{"login":"plack","id":1691275,"avatar_url":"https://gravatar.com/avatar/35c2459f3be692577c94426f6eb68550?d=https%3A%2F%2Fidenticons.github.com%2Fd8b86ff33812d85aa6f2ea105d5197c2.png&r=x","gravatar_id":"35c2459f3be692577c94426f6eb68550","url":"https://api.github.com/users/plack","html_url":"https://github.com/plack","followers_url":"https://api.github.com/users/plack/followers","following_url":"https://api.github.com/users/plack/following{/other_user}","gists_url":"https://api.github.com/users/plack/gists{/gist_id}","starred_url":"https://api.github.com/users/plack/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/plack/subscriptions","organizations_url":"https://api.github.com/users/plack/orgs","repos_url":"https://api.github.com/users/plack/repos","events_url":"https://api.github.com/users/plack/events{/privacy}","received_events_url":"https://api.github.com/users/plack/received_events","type":"Organization","site_admin":false},"repo":{"id":299695,"name":"Plack","full_name":"plack/Plack","owner":{"login":"plack","id":1691275,"avatar_url":"https://gravatar.com/avatar/35c2459f3be692577c94426f6eb68550?d=https%3A%2F%2Fidenticons.github.com%2Fd8b86ff33812d85aa6f2ea105d5197c2.png&r=x","gravatar_id":"35c2459f3be692577c94426f6eb68550","url":"https://api.github.com/users/plack","html_url":"https://github.com/plack","followers_url":"https://api.github.com/users/plack/followers","following_url":"https://api.github.com/users/plack/following{/other_user}","gists_url":"https://api.github.com/users/plack/gists{/gist_id}","starred_url":"https://api.github.com/users/plack/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/plack/subscriptions","organizations_url":"https://api.github.com/users/plack/orgs","repos_url":"https://api.github.com/users/plack/repos","events_url":"https://api.github.com/users/plack/events{/privacy}","received_events_url":"https://api.github.com/users/plack/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/plack/Plack","description":"PSGI toolkit and server adapters","fork":false,"url":"https://api.github.com/repos/plack/Plack","forks_url":"https://api.github.com/repos/plack/Plack/forks","keys_url":"https://api.github.com/repos/plack/Plack/keys{/key_id}","collaborators_url":"https://api.github.com/repos/plack/Plack/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/plack/Plack/teams","hooks_url":"https://api.github.com/repos/plack/Plack/hooks","issue_events_url":"https://api.github.com/repos/plack/Plack/issues/events{/number}","events_url":"https://api.github.com/repos/plack/Plack/events","assignees_url":"https://api.github.com/repos/plack/Plack/assignees{/user}","branches_url":"https://api.github.com/repos/plack/Plack/branches{/branch}","tags_url":"https://api.github.com/repos/plack/Plack/tags","blobs_url":"https://api.github.com/repos/plack/Plack/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/plack/Plack/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/plack/Plack/git/refs{/sha}","trees_url":"https://api.github.com/repos/plack/Plack/git/trees{/sha}","statuses_url":"https://api.github.com/repos/plack/Plack/statuses/{sha}","languages_url":"https://api.github.com/repos/plack/Plack/languages","stargazers_url":"https://api.github.com/repos/plack/Plack/stargazers","contributors_url":"https://api.github.com/repos/plack/Plack/contributors","subscribers_url":"https://api.github.com/repos/plack/Plack/subscribers","subscription_url":"https://api.github.com/repos/plack/Plack/subscription","commits_url":"https://api.github.com/repos/plack/Plack/commits{/sha}","git_commits_url":"https://api.github.com/repos/plack/Plack/git/commits{/sha}","comments_url":"https://api.github.com/repos/plack/Plack/comments{/number}","issue_comment_url":"https://api.github.com/repos/plack/Plack/issues/comments/{number}","contents_url":"https://api.github.com/repos/plack/Plack/contents/{+path}","compare_url":"https://api.github.com/repos/plack/Plack/compare/{base}...{head}","merges_url":"https://api.github.com/repos/plack/Plack/merges","archive_url":"https://api.github.com/repos/plack/Plack/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/plack/Plack/downloads","issues_url":"https://api.github.com/repos/plack/Plack/issues{/number}","pulls_url":"https://api.github.com/repos/plack/Plack/pulls{/number}","milestones_url":"https://api.github.com/repos/plack/Plack/milestones{/number}","notifications_url":"https://api.github.com/repos/plack/Plack/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/plack/Plack/labels{/name}","releases_url":"https://api.github.com/repos/plack/Plack/releases{/id}","created_at":"2009-09-07T06:43:52Z","updated_at":"2014-02-07T19:54:33Z","pushed_at":"2014-02-07T19:54:33Z","git_url":"git://github.com/plack/Plack.git","ssh_url":"git@github.com:plack/Plack.git","clone_url":"https://github.com/plack/Plack.git","svn_url":"https://github.com/plack/Plack","homepage":"http://plackperl.org/","size":8754,"stargazers_count":367,"watchers_count":367,"language":"Perl","has_issues":true,"has_downloads":true,"has_wiki":true,"forks_count":130,"mirror_url":null,"open_issues_count":55,"forks":130,"open_issues":55,"watchers":367,"default_branch":"master","master_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/plack/Plack/pulls/446"},"html":{"href":"https://github.com/plack/Plack/pull/446"},"issue":{"href":"https://api.github.com/repos/plack/Plack/issues/446"},"comments":{"href":"https://api.github.com/repos/plack/Plack/issues/446/comments"},"review_comments":{"href":"https://api.github.com/repos/plack/Plack/pulls/446/comments"},"review_comment":{"href":"https://api.github.com/repos/plack/Plack/pulls/comments/{number}"},"commits":{"href":"https://api.github.com/repos/plack/Plack/pulls/446/commits"},"statuses":{"href":"https://api.github.com/repos/plack/Plack/statuses/bc1731dbb53850c380875ad683cd87c8ec99eee3"}},"merged":true,"mergeable":null,"mergeable_state":"unknown","merged_by":{"login":"miyagawa","id":3499,"avatar_url":"https://gravatar.com/avatar/49e1240c84b221f3dcca57d005a2f569?d=https%3A%2F%2Fidenticons.github.com%2F3ea2db50e62ceefceaf70a9d9a56a6f4.png&r=x","gravatar_id":"49e1240c84b221f3dcca57d005a2f569","url":"https://api.github.com/users/miyagawa","html_url":"https://github.com/miyagawa","followers_url":"https://api.github.com/users/miyagawa/followers","following_url":"https://api.github.com/users/miyagawa/following{/other_user}","gists_url":"https://api.github.com/users/miyagawa/gists{/gist_id}","starred_url":"https://api.github.com/users/miyagawa/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/miyagawa/subscriptions","organizations_url":"https://api.github.com/users/miyagawa/orgs","repos_url":"https://api.github.com/users/miyagawa/repos","events_url":"https://api.github.com/users/miyagawa/events{/privacy}","received_events_url":"https://api.github.com/users/miyagawa/received_events","type":"User","site_admin":false},"comments":1,"review_comments":0,"commits":1,"additions":31,"deletions":1,"changed_files":3}}