diff --git a/popup.js b/popup.js
index 2a243277..a6225d15 100644
--- a/popup.js
+++ b/popup.js
@@ -10,14 +10,8 @@ $('#authenticate').on('click', () => {
});
/* Get URL for welcome page */
-$('#welcome_URL').attr(
- 'href',
- chrome.runtime.getURL('welcome.html')
-);
-$('#hook_URL').attr(
- 'href',
- chrome.runtime.getURL('welcome.html')
-);
+$('#welcome_URL').attr('href', chrome.runtime.getURL('welcome.html'));
+$('#hook_URL').attr('href', chrome.runtime.getURL('welcome.html'));
chrome.storage.local.get('leethub_token', (data) => {
const token = data.leethub_token;
@@ -49,9 +43,17 @@ chrome.storage.local.get('leethub_token', (data) => {
}
const leethubHook = data3.leethub_hook;
if (leethubHook) {
- $('#repo_url').html(
- `${leethubHook}`,
+ const safeHook = leethubHook.replace(
+ /[^a-zA-Z0-9./_-]/g,
+ '',
);
+ const anchor = document.createElement('a');
+ anchor.target = 'blank';
+ anchor.style =
+ 'color: cadetblue !important; font-size:0.8em;';
+ anchor.href = `https://github.com/${safeHook}`;
+ anchor.textContent = safeHook;
+ $('#repo_url').empty().append(anchor);
}
},
);
diff --git a/scripts/authorize.js b/scripts/authorize.js
index 9b345370..6044a32b 100644
--- a/scripts/authorize.js
+++ b/scripts/authorize.js
@@ -1,3 +1,4 @@
+/* global LEETHUB_CLIENT_ID, LEETHUB_CLIENT_SECRET */
/*
(needs patch)
IMPLEMENTATION OF AUTHENTICATION ROUTE AFTER REDIRECT FROM GITHUB.
@@ -13,9 +14,15 @@ const localAuth = {
'https://github.com/login/oauth/access_token';
this.AUTHORIZATION_URL =
'https://github.com/login/oauth/authorize';
- this.CLIENT_ID = 'beb4f0aa19ab8faf5004';
- this.CLIENT_SECRET = '843f835609c7ef02ef0f2f1645bc49514c0e65a6';
- this.REDIRECT_URL = 'https://github.com/'; // for example, https://github.com
+ this.CLIENT_ID =
+ typeof LEETHUB_CLIENT_ID !== 'undefined'
+ ? LEETHUB_CLIENT_ID
+ : 'SET_YOUR_CLIENT_ID';
+ this.CLIENT_SECRET =
+ typeof LEETHUB_CLIENT_SECRET !== 'undefined'
+ ? LEETHUB_CLIENT_SECRET
+ : 'SET_YOUR_CLIENT_SECRET';
+ this.REDIRECT_URL = 'https://github.com/';
this.SCOPES = ['repo'];
},
@@ -30,8 +37,22 @@ const localAuth = {
chrome.tabs.remove(tab.id, function () {});
});
} else {
- // eslint-disable-next-line
- this.requestToken(url.match(/\?code=([\w\/\-]+)/)[1]);
+ const codeMatch = url.match(/\?code=([\w/-]+)/);
+ const stateMatch = url.match(/[&?]state=([^&]+)/);
+ if (!codeMatch) return;
+
+ const code = codeMatch[1];
+ const returnedState = stateMatch ? stateMatch[1] : null;
+
+ chrome.storage.local.get('leethub_oauth_state', (data) => {
+ const savedState = data.leethub_oauth_state;
+ if (!savedState || savedState !== returnedState) {
+ console.error('OAuth state mismatch — possible CSRF.');
+ return;
+ }
+ chrome.storage.local.remove('leethub_oauth_state');
+ this.requestToken(code);
+ });
}
},
@@ -72,8 +93,6 @@ const localAuth = {
* @param token The OAuth2 token given to the application from the provider.
*/
finish(token) {
- /* Get username */
- // To validate user, load user object from GitHub.
const AUTHENTICATION_URL = 'https://api.github.com/user';
const xhr = new XMLHttpRequest();
@@ -86,7 +105,7 @@ const localAuth = {
isSuccess: true,
token,
username,
- KEY: this.KEY,
+ KEY: 'leethub_token',
});
}
}
@@ -97,7 +116,7 @@ const localAuth = {
},
};
-localAuth.init(); // load params.
+localAuth.init();
const link = window.location.href;
/* Check for open pipe */
diff --git a/scripts/background.js b/scripts/background.js
index 8f23e775..66161544 100644
--- a/scripts/background.js
+++ b/scripts/background.js
@@ -5,17 +5,12 @@ function handleMessage(request) {
request.isSuccess === true
) {
/* Set username */
- chrome.storage.local.set(
- { leethub_username: request.username },
- () => {
- window.localStorage.leethub_username = request.username;
- },
- );
+ chrome.storage.local.set({
+ leethub_username: request.username,
+ });
/* Set token */
- chrome.storage.local.set({ leethub_token: request.token }, () => {
- window.localStorage[request.KEY] = request.token;
- });
+ chrome.storage.local.set({ leethub_token: request.token });
/* Close pipe */
chrome.storage.local.set({ pipe_leethub: false }, () => {
@@ -28,11 +23,11 @@ function handleMessage(request) {
/* Go to onboarding for UX */
const urlOnboarding = chrome.runtime.getURL('welcome.html');
- chrome.tabs.create({ url: urlOnboarding, active: true }); // creates new tab
+ chrome.tabs.create({ url: urlOnboarding, active: true });
} else if (
request &&
request.closeWebPage === true &&
- request.isSuccess === true
+ request.isSuccess === false
) {
alert(
'Something went wrong while trying to authenticate your profile!',
diff --git a/scripts/leetcode.js b/scripts/leetcode.js
index a4569f25..1edd0eb9 100644
--- a/scripts/leetcode.js
+++ b/scripts/leetcode.js
@@ -706,7 +706,7 @@ const loader = setInterval(() => {
function startUploadCountDown() {
uploadState.uploading = true;
uploadState['countdown'] = setTimeout(() => {
- if ((uploadState.uploading = true)) {
+ if (uploadState.uploading === true) {
// still uploading, then it failed
uploadState.uploading = false;
markUploadFailed();
diff --git a/scripts/oauth2.js b/scripts/oauth2.js
index 545dc4d3..cacd75c9 100644
--- a/scripts/oauth2.js
+++ b/scripts/oauth2.js
@@ -1,3 +1,4 @@
+/* global LEETHUB_CLIENT_ID, LEETHUB_CLIENT_SECRET */
// eslint-disable-next-line no-unused-vars
const oAuth2 = {
/**
@@ -9,9 +10,15 @@ const oAuth2 = {
'https://github.com/login/oauth/access_token';
this.AUTHORIZATION_URL =
'https://github.com/login/oauth/authorize';
- this.CLIENT_ID = 'beb4f0aa19ab8faf5004';
- this.CLIENT_SECRET = '843f835609c7ef02ef0f2f1645bc49514c0e65a6';
- this.REDIRECT_URL = 'https://github.com/'; // for example, https://github.com
+ this.CLIENT_ID =
+ typeof LEETHUB_CLIENT_ID !== 'undefined'
+ ? LEETHUB_CLIENT_ID
+ : 'SET_YOUR_CLIENT_ID';
+ this.CLIENT_SECRET =
+ typeof LEETHUB_CLIENT_SECRET !== 'undefined'
+ ? LEETHUB_CLIENT_SECRET
+ : 'SET_YOUR_CLIENT_SECRET';
+ this.REDIRECT_URL = 'https://github.com/';
this.SCOPES = ['repo'];
},
@@ -19,17 +26,21 @@ const oAuth2 = {
* Begin
*/
begin() {
- this.init(); // secure token params.
+ this.init();
- let url = `${this.AUTHORIZATION_URL}?client_id=${this.CLIENT_ID}&redirect_uri${this.REDIRECT_URL}&scope=`;
+ const state = crypto.getRandomValues(new Uint32Array(2)).join('');
+ chrome.storage.local.set({ leethub_oauth_state: state });
+
+ let url = `${this.AUTHORIZATION_URL}?client_id=${
+ this.CLIENT_ID
+ }&redirect_uri=${encodeURIComponent(this.REDIRECT_URL)}&scope=`;
for (let i = 0; i < this.SCOPES.length; i += 1) {
url += this.SCOPES[i];
}
+ url += `&state=${state}`;
chrome.storage.local.set({ pipe_leethub: true }, () => {
- // opening pipe temporarily
-
chrome.tabs.create({ url, active: true }, function () {
window.close();
chrome.tabs.getCurrent(function (tab) {
diff --git a/scripts/welcome.js b/scripts/welcome.js
index 9812db3c..1c372e69 100644
--- a/scripts/welcome.js
+++ b/scripts/welcome.js
@@ -6,6 +6,16 @@ const repositoryName = () => {
return $('#name').val().trim();
};
+function escapeHtml(str) {
+ const div = document.createElement('div');
+ div.appendChild(document.createTextNode(str));
+ return div.innerHTML;
+}
+
+function isValidRepoName(name) {
+ return /^[a-zA-Z0-9._-]+$/.test(name) && name.length <= 100;
+}
+
/* Status codes for creating of repo */
const statusCode = (res, status, name) => {
@@ -55,7 +65,11 @@ const statusCode = (res, status, name) => {
chrome.storage.local.set({ mode_type: 'commit' }, () => {
$('#error').hide();
$('#success').html(
- `Successfully created ${name}. Start LeetCoding!`,
+ `Successfully created ${escapeHtml(
+ name,
+ )}. Start LeetCoding!`,
);
$('#success').show();
$('#unlink').show();
@@ -107,7 +121,11 @@ const linkStatusCode = (status, name) => {
case 301:
$('#success').hide();
$('#error').html(
- `Error linking ${name} to LeetHub.
This repository has been moved permenantly. Try creating a new one.`,
+ `Error linking ${escapeHtml(
+ name,
+ )} to LeetHub.
This repository has been moved permenantly. Try creating a new one.`,
);
$('#error').show();
break;
@@ -115,7 +133,11 @@ const linkStatusCode = (status, name) => {
case 403:
$('#success').hide();
$('#error').html(
- `Error linking ${name} to LeetHub.
Forbidden action. Please make sure you have the right access to this repository.`,
+ `Error linking ${escapeHtml(
+ name,
+ )} to LeetHub.
Forbidden action. Please make sure you have the right access to this repository.`,
);
$('#error').show();
break;
@@ -123,7 +145,11 @@ const linkStatusCode = (status, name) => {
case 404:
$('#success').hide();
$('#error').html(
- `Error linking ${name} to LeetHub.
Resource not found. Make sure you enter the right repository name.`,
+ `Error linking ${escapeHtml(
+ name,
+ )} to LeetHub.
Resource not found. Make sure you enter the right repository name.`,
);
$('#error').show();
break;
@@ -176,7 +202,11 @@ const linkRepo = (token, name) => {
() => {
$('#error').hide();
$('#success').html(
- `Successfully linked ${name} to LeetHub. Start LeetCoding now!`,
+ `Successfully linked ${escapeHtml(
+ name,
+ )} to LeetHub. Start LeetCoding now!`,
);
$('#success').show();
$('#unlink').show();
@@ -253,6 +283,12 @@ $('#hook_button').on('click', () => {
);
$('#name').focus();
$('#error').show();
+ } else if (!isValidRepoName(repositoryName())) {
+ $('#error').text(
+ 'Invalid repository name - Use only letters, numbers, hyphens, underscores, and dots (max 100 chars).',
+ );
+ $('#name').focus();
+ $('#error').show();
} else {
$('#error').hide();
$('#success').text('Attempting to create Hook... Please wait.');