OWASP / threat-dragon

An open source threat modeling tool from OWASP
https://owasp.org/www-project-threat-dragon/
Apache License 2.0
942 stars 254 forks source link

GITHUB_ENTERPRISE_PORT incorrect placement due to bug in octonode #907

Open quine opened 8 months ago

quine commented 8 months ago

Describe the bug: Threat Dragon is improperly constructing GitHub Enterprise (GHE) URLs (after initial OAuth login), leading to 404 errors on GHE, with Threat Dragon then returning 500 errors.

It appears to start here:

The inclusion of both the base path (/api/v3) and the port when constructing the URL for octonode causes the URL to be invalid.

Using github.company.com as the example...

enterpriseOpts { hostname: 'github.company.com/api/v3', port: 443, protocol: 'https' }

      _url = url.format({
        protocol: urlFromPath.protocol || this.options && this.options.protocol || "https:",
        auth: urlFromPath.auth || (this.token && this.token.username && this.token.password ? this.token.username + ":" + this.token.password : ''),
        hostname: urlFromPath.hostname || this.options && this.options.hostname || "api.github.com",
        port: urlFromPath.port || this.options && this.options.port,
        pathname: urlFromPath.pathname,
        query: query
      });

Expected behaviour: Threat Dragon should properly construct the GHE URL.

Environment:

To Reproduce:

error: Not Found {
    "body": {
        "documentation_url": "https://docs.github.com/enterprise-server@3.8/rest",
        "message": "Not Found"
    },
    "headers": {
        "access-control-allow-origin": "*",
        "access-control-expose-headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset",
        "connection": "close",
        "content-length": "96",
        "content-security-policy": "default-src 'none'",
        "content-type": "application/json; charset=utf-8",
        "date": "Fri, 08 Mar 2024 12:18:19 GMT",
        "referrer-policy": "origin-when-cross-origin, strict-origin-when-cross-origin",
        "server": "nginx/1.14.2",
        "strict-transport-security": "max-age=31536000; includeSubdomains",
        "x-accepted-oauth-scopes": "repo",
        "x-content-type-options": "nosniff",
        "x-frame-options": "deny",
        "x-github-enterprise-version": "3.8.11",
        "x-github-media-type": "github.v3; format=json",
        "x-github-request-id": "8527aaa6-62b5-460d-aebc-a0093eadff93",
        "x-oauth-client-id": "b72b631276646ddd4635",
        "x-oauth-scopes": "repo",
        "x-ratelimit-limit": "14000",
        "x-ratelimit-remaining": "13999",
        "x-ratelimit-reset": "1709903899",
        "x-ratelimit-resource": "core",
        "x-ratelimit-used": "1",
        "x-runtime-rack": "0.031289",
        "x-xss-protection": "0"
    },
    "service": "threat-dragon",
    "statusCode": 404,
    "timestamp": "2024-03-08 07:18:19"
}
jgadsden commented 4 months ago

@quine are you still seeing this issue? Are you able to fix and test it?

quine commented 4 months ago

@jgadsden Sorry for not getting back to you sooner! Let me go back and check.

jgadsden commented 4 months ago

thanks, much appreciated @quine - there have been a few changes in this area so it may be working now I am not able to test it myself as I do not have access to a github enterprise account

quine commented 4 months ago

@jgadsden Roger that. Will test today. 🤞

quine commented 4 months ago

@jgadsden Unfortunately, it looks like it's still constructing the URL incorrectly:

/api/v3:443/user

As an aside, seems like Octonode is no longer maintained -- repo's been archived.

quine commented 4 months ago

Okay, so this is still totally an issue with Octonode. I reckon, if it was at all possible to get a change upstream, we could do something like this in octonode/client.coffee, something like :

if @options?.baseapipath and urlFromPath.pathname
  urlFromPath.pathname = "#{@options.baseapipath}#{urlFromPath.pathname}"

_url = url.format
  protocol: urlFromPath.protocol or @options?.protocol or "https:"
  auth: urlFromPath.auth or if @token?.username and @token?.password then "#{@token.username}:#{@token.password}" else ''
  hostname: urlFromPath.hostname or @options?.hostname or "api.github.com"
  port: urlFromPath.port or @options?.port
  pathname: urlFromPath.pathname
  query: query

and then update td.server/src/repositories/githubrepo.js like:

const getClient = (accessToken) => {
    const enterpriseHostname = env.get().config.GITHUB_ENTERPRISE_HOSTNAME;
    if (enterpriseHostname) {
        const port = env.get().config.GITHUB_ENTERPRISE_PORT;
        const protocol = env.get().config.GITHUB_ENTERPRISE_PROTOCOL;
        const enterpriseOpts = { hostname: `${enterpriseHostname}` };
        enterpriseOpts.baseapipath = '/api/v3';
        if (port) { enterpriseOpts.port = parseInt(port, 10); }
        if (protocol) { enterpriseOpts.protocol = protocol; }
        return github.client(accessToken, enterpriseOpts);
    }
    return github.client(accessToken);
};

At least then /api/v3 (or whatever) would be in the correct place in the URL 🙃

IDK, something like that might work, but again...octonode's no longer maintained, and I have no idea if anyone is taking the reins on it.

jgadsden commented 4 months ago

@quine thank you for getting to the bottom of this - we can keep it open and see if a non-default GITHUB_ENTERPRISE_PORT using octonode can be correctly used

quine commented 3 months ago

@jgadsden Sure thing. TBH, simplest workaround in the interim is to just not take in/honor the GITHUB_ENTERPRISE_PORT / not set enterpriseOpts.port, but that sort of kneecaps anyone running GHE on something other than 443/tcp.

Half-jokingly(?), someone could actually take over/fork Octonode -- or...more seriously, and far less appealing I'm sure, switch to something else, such as Octokit.js? 🙁