@@ -61,22 +61,40 @@ public class GitHubController {
6161
6262 /**
6363 * Initializes the GitHub secret from the LPVS_GITHUB_SECRET environment variable or the application property.
64+ * The environment variable takes precedence over the property.
6465 * Exits the application if the secret is not set.
6566 */
6667 @ PostConstruct
6768 public void initializeGitHubController () {
6869 this .GITHUB_SECRET =
69- Optional .ofNullable (this .GITHUB_SECRET )
70- .filter (s -> !s .isEmpty ())
71- .orElse (
72- Optional .ofNullable (System .getenv ("LPVS_GITHUB_SECRET" ))
73- .orElse ("" ));
74- if (this .GITHUB_SECRET .isEmpty ()) {
75- log .error ("LPVS_GITHUB_SECRET (github.secret) is not set." );
76- exitHandler .exit (-1 );
70+ Optional .ofNullable (System .getenv ("LPVS_GITHUB_SECRET" ))
71+ .filter (StringUtils ::hasText )
72+ .orElse (Optional .ofNullable (this .GITHUB_SECRET ).orElse ("" ));
73+ if (!StringUtils .hasText (this .GITHUB_SECRET )) {
74+ if (StringUtils .hasText (pullRequestTrigger ) || StringUtils .hasText (localPath )) {
75+ // Single scan (CLI) mode doesn't need webhooks: keep running, reject webhooks
76+ log .warn (
77+ "LPVS_GITHUB_SECRET (github.secret) is not set. Webhook endpoint is disabled." );
78+ this .GITHUB_SECRET = "" ;
79+ } else {
80+ log .error ("LPVS_GITHUB_SECRET (github.secret) is not set." );
81+ exitHandler .exit (-1 );
82+ }
7783 }
7884 }
7985
86+ /**
87+ * Trigger value to start a single scan of a pull request (optional).
88+ */
89+ @ Value ("${github.pull.request:}" )
90+ private String pullRequestTrigger ;
91+
92+ /**
93+ * Trigger value to start a single scan of local files or folder (optional).
94+ */
95+ @ Value ("${local.path:}" )
96+ private String localPath ;
97+
8098 /**
8199 * LPVSQueueService for handling user-related business logic.
82100 */
@@ -107,6 +125,7 @@ public void initializeGitHubController() {
107125 private static final String SUCCESS = "Success" ;
108126 private static final String ERROR = "Error" ;
109127 private static final String ALGORITHM = "HmacSHA256" ;
128+ private static final String SIGNATURE_PREFIX = "sha256=" ;
110129
111130 /**
112131 * Constructor for GitHubController.
@@ -175,7 +194,7 @@ public ResponseEntity<LPVSResponseWrapper> gitHubWebhooks(
175194 .headers (LPVSPayloadUtil .generateSecurityHeaders ())
176195 .body (new LPVSResponseWrapper (ERROR ));
177196 }
178- if (!GITHUB_SECRET . trim (). isEmpty () && wrongSecret (signature , payload )) {
197+ if (!StringUtils . hasText ( GITHUB_SECRET ) || wrongSecret (signature , payload )) {
179198 log .error ("Received empty or incorrect GITHUB_SECRET" );
180199 return ResponseEntity .status (HttpStatus .FORBIDDEN )
181200 .headers (LPVSPayloadUtil .generateSecurityHeaders ())
@@ -310,16 +329,25 @@ public ResponseEntity<LPVSResponseWrapper> gitHubSingleScan(
310329 * @throws Exception if an error occurs during signature verification.
311330 */
312331 public boolean wrongSecret (String signature , String payload ) throws Exception {
313- String lpvsSecret = signature .split ("=" , 2 )[1 ];
332+ if (signature == null || !signature .startsWith (SIGNATURE_PREFIX )) {
333+ return true ;
334+ }
335+ String lpvsSecret = signature .substring (SIGNATURE_PREFIX .length ());
314336
315- SecretKeySpec key = new SecretKeySpec (GITHUB_SECRET .getBytes ("utf-8" ), ALGORITHM );
337+ SecretKeySpec key =
338+ new SecretKeySpec (GITHUB_SECRET .getBytes (StandardCharsets .UTF_8 ), ALGORITHM );
316339 Mac mac = Mac .getInstance (ALGORITHM );
317340 mac .init (key );
318- String githubSecret = Hex .encodeHexString (mac .doFinal (payload .getBytes ("utf-8" )));
341+ String githubSecret =
342+ Hex .encodeHexString (
343+ mac .doFinal (
344+ Optional .ofNullable (payload )
345+ .orElse ("" )
346+ .getBytes (StandardCharsets .UTF_8 )));
319347
320- log . debug ( "lpvs signature: " + lpvsSecret );
321- log . debug ( "github signature: " + githubSecret );
322-
323- return ! lpvsSecret . equals ( githubSecret );
348+ // Constant-time comparison to prevent timing attacks
349+ return ! MessageDigest . isEqual (
350+ lpvsSecret . getBytes ( StandardCharsets . UTF_8 ),
351+ githubSecret . getBytes ( StandardCharsets . UTF_8 ) );
324352 }
325353}
0 commit comments