Skip to content

Commit

Permalink
Merge pull request #15167 from lichess-org/scanning
Browse files Browse the repository at this point in the history
Github scanning webhook
  • Loading branch information
ornicar committed Apr 30, 2024
2 parents 39675e2 + 7c4ad3d commit 906a62c
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 0 deletions.
8 changes: 8 additions & 0 deletions app/controllers/Main.scala
Original file line number Diff line number Diff line change
Expand Up @@ -174,3 +174,11 @@ final class Main(
.map(url => JsonOk(Json.obj("imageUrl" -> url)))
case None => JsonBadRequest(jsonError("Image content only"))
}

def githubSecretScanning = AnonBodyOf(parse.json): body =>
env.oAuth.tokenApi
.secretScanning(body)
.flatMap:
_.traverse: (token, url) =>
env.msg.api.systemPost(token.userId, lila.msg.MsgPreset.apiTokenRevoked(url))
.as(NoContent)
1 change: 1 addition & 0 deletions conf/routes
Original file line number Diff line number Diff line change
Expand Up @@ -830,6 +830,7 @@ GET /verify-title controllers.Main.verifyTitle
GET /InstantChess.com controllers.Main.instantChess
GET /daily-puzzle-slack controllers.Main.dailyPuzzleSlackApp
POST /upload/image/user/:rel controllers.Main.uploadImage(rel)
POST /github/secret-scanning controllers.Main.githubSecretScanning

# Technical
GET /run/captcha/$id<\w{8}> controllers.Main.captchaCheck(id)
Expand Down
10 changes: 10 additions & 0 deletions modules/msg/src/main/MsgPreset.scala
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,13 @@ $forumPost
s"""@${by.name} has changed your leader permissions in the team "${team.name}".
Your new permissions are: ${perms.mkString(", ")}.
$baseUrl/team/${team.id}"""

def apiTokenRevoked(url: String) =
s"""Your Lichess API token has been found on GitHub

We detected one of your API tokens in a public code repository on GitHub at the following URL:

$url

We have automatically revoked the token to protect your account.
"""
24 changes: 24 additions & 0 deletions modules/oauth/src/main/AccessTokenApi.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package lila.oauth

import reactivemongo.api.bson.*
import play.api.libs.json.*

import lila.core.net.Bearer
import lila.db.dsl.{ *, given }
Expand Down Expand Up @@ -211,6 +212,29 @@ final class AccessTokenApi(
bearers.zip(openTokens).toMap
}

def secretScanning(body: JsValue): Fu[List[(AccessToken, String)]] =
body
.asOpt[List[JsObject]]
.map:
_.flatMap: obj =>
for
token <- (obj \ "token").asOpt[String]
url <- (obj \ "url").asOpt[String]
yield Bearer(token) -> url
.toMap
.so: tokensMap =>
test(tokensMap.keys.toList)
.flatMap:
_.toList.traverse: (bearer, token) =>
token match
case Some(token) =>
logger.branch("github").info(s"revoking token ${token.plain} for user ${token.userId}")
revoke(token.plain).inject(tokensMap.get(bearer).map(token -> _))
case None =>
logger.branch("github").info(s"ignoring token $bearer")
fuccess(none)
.map(_.flatten)

private val accessTokenCache =
cacheApi[AccessToken.Id, Option[AccessToken.ForAuth]](1024, "oauth.access_token"):
_.expireAfterWrite(5 minutes).buildAsyncFuture(fetchAccessToken)
Expand Down

0 comments on commit 906a62c

Please sign in to comment.