Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(settings): define a 'heartbeat' route, so SecurityHeaders can handle redirected root #45228

Merged
merged 2 commits into from
Jun 18, 2024

Conversation

smokris
Copy link
Contributor

@smokris smokris commented May 8, 2024

Problem

On sites where the root (/) path is redirected (e.g. when using the Social login plugin), the Admin Overview page incorrectly shows errors about security headers not being set:

Some headers are not set correctly on your instance - The X-Robots-Tag HTTP header is not set to noindex,nofollow. This is a potential security or privacy risk, as it is recommended to adjust this setting accordingly. - The X-Permitted-Cross-Domain-Policies HTTP header is not set to none. This is a potential security or privacy risk, as it is recommended to adjust this setting accordingly. For more details see the documentation ↗.

Analysis

In lib/base.php, the request path /heartbeat is handled specially by returning early, but no formal route is defined for it.

OCA\Settings\SetupChecks\SecurityHeaders calls URLGenerator::linkToRoute('heartbeat'), but the generated URL is emptystring, since there's no route defined by that name.

It then performs a request on the root (/) path (instead of the expected /heartbeat path). On sites where the root path redirects, SecurityHeaders then incorrectly analyzes the headers of the redirect, instead of analyzing the headers of the Nextcloud heartbeat page.

Proposed solution

Define a heartbeat route, so that URLGenerator::linkToRoute('heartbeat') returns /heartbeat as the SecurityHeaders test seems to expect.

Checklist

…dle redirected root

Signed-off-by: Steve Mokris <steve@kosada.com>
Copy link
Member

@provokateurin provokateurin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to add a test to the setup checks that validates that the check now works.

core/routes.php Show resolved Hide resolved
tests/lib/Route/RouterTest.php Outdated Show resolved Hide resolved
@provokateurin
Copy link
Member

TBH I've never seen this warning on my local dev instance, can you tell me how to reproduce it?

@come-nc
Copy link
Contributor

come-nc commented May 13, 2024

I cannot tell if adding a route like this is the right fix for this. The heartbeat short circuits a lot of things so it cannot be put in a controller.
It is still a supported URL endpoint so maybe it’s fine to add it like that?

Copy link
Contributor

Hello there,
Thank you so much for taking the time and effort to create a pull request to our Nextcloud project.

We hope that the review process is going smooth and is helpful for you. We want to ensure your pull request is reviewed to your satisfaction. If you have a moment, our community management team would very much appreciate your feedback on your experience with this PR review process.

Your feedback is valuable to us as we continuously strive to improve our community developer experience. Please take a moment to complete our short survey by clicking on the following link: https://cloud.nextcloud.com/apps/forms/s/i9Ago4EQRZ7TWxjfmeEpPkf6

Thank you for contributing to Nextcloud and we hope to hear from you soon!

@cdammanintopix
Copy link
Contributor

cdammanintopix commented May 22, 2024

Hello,
Thank you for this fix.
Without it, I had the following issue in my logs:

{
  "reqId": "xxxxxxxxxx",
  "level": 1,
  "time": "2024-05-22T08:09:18+00:00",
  "remoteAddr": "xxxxxxxxxx",
  "user": "xxxxxxxxxx",
  "app": "no app in context",
  "method": "GET",
  "url": "/settings/ajax/checksetup",
  "message": "Unable to generate a URL for the named route \"heartbeat\" as such route does not exist.",
  "userAgent": "xxxxxxxxxx",
  "version": "29.0.0.19",
  "exception": {
    "Exception": "Symfony\\Component\\Routing\\Exception\\RouteNotFoundException",
    "Message": "Unable to generate a URL for the named route \"heartbeat\" as such route does not exist.",
    "Code": 0,
    "Trace": [
      {
        "file": "/var/www/html/lib/private/Route/Router.php",
        "line": 410,
        "function": "generate",
        "class": "Symfony\\Component\\Routing\\Generator\\UrlGenerator",
        "type": "->",
        "args": [
          "heartbeat",
          [],
          1
        ]
      },
      {
        "file": "/var/www/html/lib/private/Route/CachingRouter.php",
        "line": 65,
        "function": "generate",
        "class": "OC\\Route\\Router",
        "type": "->",
        "args": [
          "heartbeat",
          [],
          false
        ]
      },
      {
        "file": "/var/www/html/lib/private/URLGenerator.php",
        "line": 103,
        "function": "generate",
        "class": "OC\\Route\\CachingRouter",
        "type": "->",
        "args": [
          "heartbeat",
          []
        ]
      },
      {
        "file": "/var/www/html/apps/settings/lib/SetupChecks/SecurityHeaders.php",
        "line": 60,
        "function": "linkToRoute",
        "class": "OC\\URLGenerator",
        "type": "->",
        "args": [
          "heartbeat"
        ]
      },
      {
        "file": "/var/www/html/lib/private/SetupCheck/SetupCheckManager.php",
        "line": 51,
        "function": "run",
        "class": "OCA\\Settings\\SetupChecks\\SecurityHeaders",
        "type": "->",
        "args": []
      },
      {
        "file": "/var/www/html/apps/settings/lib/Controller/CheckSetupController.php",
        "line": 179,
        "function": "runAll",
        "class": "OC\\SetupCheck\\SetupCheckManager",
        "type": "->",
        "args": []
      },
      {
        "file": "/var/www/html/lib/private/AppFramework/Http/Dispatcher.php",
        "line": 232,
        "function": "check",
        "class": "OCA\\Settings\\Controller\\CheckSetupController",
        "type": "->",
        "args": []
      },
      {
        "file": "/var/www/html/lib/private/AppFramework/Http/Dispatcher.php",
        "line": 138,
        "function": "executeController",
        "class": "OC\\AppFramework\\Http\\Dispatcher",
        "type": "->",
        "args": [
          [
            "OCA\\Settings\\Controller\\CheckSetupController"
          ],
          "check"
        ]
      },
      {
        "file": "/var/www/html/lib/private/AppFramework/App.php",
        "line": 184,
        "function": "dispatch",
        "class": "OC\\AppFramework\\Http\\Dispatcher",
        "type": "->",
        "args": [
          [
            "OCA\\Settings\\Controller\\CheckSetupController"
          ],
          "check"
        ]
      },
      {
        "file": "/var/www/html/lib/private/Route/Router.php",
        "line": 338,
        "function": "main",
        "class": "OC\\AppFramework\\App",
        "type": "::",
        "args": [
          "OCA\\Settings\\Controller\\CheckSetupController",
          "check",
          [
            "OC\\AppFramework\\DependencyInjection\\DIContainer"
          ],
          [
            "settings.checksetup.check"
          ]
        ]
      },
      {
        "file": "/var/www/html/lib/base.php",
        "line": 1050,
        "function": "match",
        "class": "OC\\Route\\Router",
        "type": "->",
        "args": [
          "/settings/ajax/checksetup"
        ]
      },
      {
        "file": "/var/www/html/index.php",
        "line": 49,
        "function": "handleRequest",
        "class": "OC",
        "type": "::",
        "args": []
      }
    ],
    "File": "/var/www/html/3rdparty/symfony/routing/Generator/UrlGenerator.php",
    "Line": 144,
    "message": "Unable to generate a URL for the named route \"heartbeat\" as such route does not exist.",
    "exception": [],
    "CustomMessage": "Unable to generate a URL for the named route \"heartbeat\" as such route does not exist."
  },
  "id": "xxxxxxxxxx"
}

Applying this change fixed the issue.

Setup to reproduce: run the docker image as mentioned in the docs with version 29, and go to the page /settings/admin/overview

@joshtrichards joshtrichards linked an issue Jun 13, 2024 that may be closed by this pull request
8 tasks
@joshtrichards
Copy link
Member

Added a link to issue #44234 since this is a potential fix for that.

@solracsf solracsf added this to the Nextcloud 30 milestone Jun 18, 2024
Co-authored-by: Kate <26026535+provokateurin@users.noreply.github.com>
Signed-off-by: Côme Chilliet <91878298+come-nc@users.noreply.github.com>
@come-nc
Copy link
Contributor

come-nc commented Jun 18, 2024

/backport to stable29

@come-nc
Copy link
Contributor

come-nc commented Jun 18, 2024

/backport to stable28

@AndyScherzinger AndyScherzinger merged commit c3354e9 into nextcloud:master Jun 18, 2024
153 of 164 checks passed
Copy link

welcome bot commented Jun 18, 2024

Thanks for your first pull request and welcome to the community! Feel free to keep them coming! If you are looking for issues to tackle then have a look at this selection: https://github.com/nextcloud/server/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22

@andreas-bulling
Copy link

andreas-bulling commented Jul 10, 2024

I've upgraded to 29.0.3 and I still see the error in the log:

"Unable to generate a URL for the named route "heartbeat" as such route does not exist."

@joshtrichards
Copy link
Member

That's because it's scheduled for the upcoming maintenance release via #45956

@blizzz blizzz mentioned this pull request Jul 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Bug]: Missing headers are reported when using the SSO application
8 participants