Compare commits

..

22 Commits

Author SHA1 Message Date
Alicia Sykes
4b4bf20a6f Bump version from 2.0.1 to 2.0.2 2025-11-14 21:54:24 +00:00
Alicia Sykes
9407f5c4b0 Merge pull request #252 from jayrizon/patch-1
adds ports to check environment variable.
2025-08-03 14:08:31 +01:00
jayrizon
8715274c9a adds ports to check environment variable.
Checks if the env PORTS_TO_CHECK is set, if so the string is split via "," to get an array of ports to check.
If the env is not set, return the default commonly used ports.
2025-08-01 08:27:15 +02:00
Alicia Sykes
6ef6720ec0 Merge pull request #249 from tnga/fixes
fix: Fix navigation links and add smooth scrolling to hash fragments
2025-06-28 22:46:21 +01:00
tnga
c0c146b2b9 fix: handle undefined robots data and improve object destructuring in RobotsTxt component 2025-06-16 07:20:26 +01:00
tnga
64510f7e7e fix: add toString() to prevent title attribute TypeError on non-string values 2025-06-16 07:15:01 +01:00
tnga
4603828b92 fix: change web-check.zyz link to expected web-check.xyz 2025-06-12 19:54:33 +01:00
tnga
cdf7875ddb fix: Fix navigation links and add smooth scrolling to hash fragments
- Update Link components in Home.tsx to use correct /check prefix for routing
- Add useEffect hook in About.tsx to handle smooth scrolling to hash fragments
- Add delay to ensure page renders before scrolling to target element
2025-06-12 14:09:52 +01:00
Alicia Sykes
50a11a5f50 Merge pull request #243 from Lissy93/sec/fix-com-inj-vul
security: Replace exec with execFile
2025-04-12 12:13:01 +01:00
Alicia Sykes
145711bdc7 ref: Bump version to 2.0.1 2025-04-12 12:12:51 +01:00
Alicia Sykes
0e4958aa10 security: Replace exec with execFile 2025-04-12 12:11:11 +01:00
Alicia Sykes
99653868c7 ref: Update data-domain 2025-04-03 13:05:33 +01:00
Alicia Sykes
20d08290af Merge pull request #228 from CrazyWolf13/patch-1
Really fix the screenshot api endpoint
2025-03-29 10:51:22 +00:00
Alicia Sykes
90883843e6 Merge pull request #237 from Lissy93/contributors-readme-action-8zk_vySnji
docs(contributor): contributors readme action update
2025-03-29 10:48:40 +00:00
liss-bot
eb63741e04 docs: Updates contributors list 2025-03-23 02:18:05 +00:00
Tobias
bbf519e110 fix screenshot.js 2025-02-26 13:55:48 +01:00
Alicia Sykes
f233de9bca Merge pull request #205 from Lissy93/sad/disable-everything-temporarily
feat: Temporarily disable, because I am poor.
2024-12-17 20:16:57 +00:00
Alicia Sykes
da0204c156 feat: Temporarily disable, because I am poor. 2024-12-17 20:16:36 +00:00
Alicia Sykes
7ca22daa9a Merge pull request #162 from 34bits/patch-2
Update AdditionalResources.tsx
2024-08-17 15:26:13 +01:00
Alicia Sykes
7ca8412cc9 Merge pull request #170 from Lissy93/contributors-readme-action-YNmkpszRFZ
docs(contributor): contributors readme action update
2024-08-17 15:20:20 +01:00
liss-bot
bc6afa635c docs: Updates contributors list 2024-08-11 03:06:52 +01:00
NGN
95469b971f Update AdditionalResources.tsx
I changed the URL in MDN HTTP Observatory from  link: 'https://observatory.mozilla.org/', to link: 'https://developer.mozilla.org/en-US/observatory', because

MDN HTTP Observatory is launched, and Mozilla Observatory is now deprecated.

Here is the article: https://developer.mozilla.org/en-US/blog/mdn-http-observatory-launch/
2024-07-23 08:29:48 +03:00
16 changed files with 240 additions and 66 deletions

83
.github/README.md vendored
View File

@@ -1021,6 +1021,13 @@ Credit to the following users for contributing to Web-Check
<sub><b>PhiRequiem</b></sub> <sub><b>PhiRequiem</b></sub>
</a> </a>
</td> </td>
<td align="center">
<a href="https://github.com/ntaiko">
<img src="https://avatars.githubusercontent.com/u/108784453?v=4" width="80;" alt="ntaiko"/>
<br />
<sub><b>Nikolaos G. Ntaiko</b></sub>
</a>
</td>
<td align="center"> <td align="center">
<a href="https://github.com/Myzel394"> <a href="https://github.com/Myzel394">
<img src="https://avatars.githubusercontent.com/u/50424412?v=4" width="80;" alt="Myzel394"/> <img src="https://avatars.githubusercontent.com/u/50424412?v=4" width="80;" alt="Myzel394"/>
@@ -1028,6 +1035,8 @@ Credit to the following users for contributing to Web-Check
<sub><b>Myzel394</b></sub> <sub><b>Myzel394</b></sub>
</a> </a>
</td> </td>
</tr>
<tr>
<td align="center"> <td align="center">
<a href="https://github.com/murrple-1"> <a href="https://github.com/murrple-1">
<img src="https://avatars.githubusercontent.com/u/5559656?v=4" width="80;" alt="murrple-1"/> <img src="https://avatars.githubusercontent.com/u/5559656?v=4" width="80;" alt="murrple-1"/>
@@ -1035,8 +1044,6 @@ Credit to the following users for contributing to Web-Check
<sub><b>Murray Christopherson</b></sub> <sub><b>Murray Christopherson</b></sub>
</a> </a>
</td> </td>
</tr>
<tr>
<td align="center"> <td align="center">
<a href="https://github.com/t3chn0m4g3"> <a href="https://github.com/t3chn0m4g3">
<img src="https://avatars.githubusercontent.com/u/4318452?v=4" width="80;" alt="t3chn0m4g3"/> <img src="https://avatars.githubusercontent.com/u/4318452?v=4" width="80;" alt="t3chn0m4g3"/>
@@ -1072,6 +1079,8 @@ Credit to the following users for contributing to Web-Check
<sub><b>Ed Preston</b></sub> <sub><b>Ed Preston</b></sub>
</a> </a>
</td> </td>
</tr>
<tr>
<td align="center"> <td align="center">
<a href="https://github.com/dimitri-kandassamy"> <a href="https://github.com/dimitri-kandassamy">
<img src="https://avatars.githubusercontent.com/u/21193806?v=4" width="80;" alt="dimitri-kandassamy"/> <img src="https://avatars.githubusercontent.com/u/21193806?v=4" width="80;" alt="dimitri-kandassamy"/>
@@ -1079,8 +1088,6 @@ Credit to the following users for contributing to Web-Check
<sub><b>Dimitri Kandassamy</b></sub> <sub><b>Dimitri Kandassamy</b></sub>
</a> </a>
</td> </td>
</tr>
<tr>
<td align="center"> <td align="center">
<a href="https://github.com/0xflotus"> <a href="https://github.com/0xflotus">
<img src="https://avatars.githubusercontent.com/u/26602940?v=4" width="80;" alt="0xflotus"/> <img src="https://avatars.githubusercontent.com/u/26602940?v=4" width="80;" alt="0xflotus"/>
@@ -1102,19 +1109,12 @@ Huge thanks to these wonderful people, who sponsor me on GitHub, their support h
<tbody> <tbody>
<tr> <tr>
<td align="center"> <td align="center">
<a href="https://github.com/koconder"> <a href="https://github.com/vincentkoc">
<img src="https://avatars.githubusercontent.com/u/25068?u=582657b23622aaa3dfe68bd028a780f272f456fa&v=4" width="80;" alt="koconder"/> <img src="https://avatars.githubusercontent.com/u/25068?v=4" width="80;" alt="vincentkoc"/>
<br /> <br />
<sub><b>Vincent Koc</b></sub> <sub><b>Vincent Koc</b></sub>
</a> </a>
</td> </td>
<td align="center">
<a href="https://github.com/tbjers">
<img src="https://avatars.githubusercontent.com/u/1117052?v=4" width="80;" alt="tbjers"/>
<br />
<sub><b>Torgny Bjers</b></sub>
</a>
</td>
<td align="center"> <td align="center">
<a href="https://github.com/AnandChowdhary"> <a href="https://github.com/AnandChowdhary">
<img src="https://avatars.githubusercontent.com/u/2841780?u=747e554b3a7f12eb20b7910e1c87d817844f714f&v=4" width="80;" alt="AnandChowdhary"/> <img src="https://avatars.githubusercontent.com/u/2841780?u=747e554b3a7f12eb20b7910e1c87d817844f714f&v=4" width="80;" alt="AnandChowdhary"/>
@@ -1143,8 +1143,6 @@ Huge thanks to these wonderful people, who sponsor me on GitHub, their support h
<sub><b>Ulises Gascón</b></sub> <sub><b>Ulises Gascón</b></sub>
</a> </a>
</td> </td>
</tr>
<tr>
<td align="center"> <td align="center">
<a href="https://github.com/digitalarche"> <a href="https://github.com/digitalarche">
<img src="https://avatars.githubusercontent.com/u/6546135?u=564756d7f44ab2206819eb3148f6d822673f5066&v=4" width="80;" alt="digitalarche"/> <img src="https://avatars.githubusercontent.com/u/6546135?u=564756d7f44ab2206819eb3148f6d822673f5066&v=4" width="80;" alt="digitalarche"/>
@@ -1152,6 +1150,8 @@ Huge thanks to these wonderful people, who sponsor me on GitHub, their support h
<sub><b>Digital Archeology</b></sub> <sub><b>Digital Archeology</b></sub>
</a> </a>
</td> </td>
</tr>
<tr>
<td align="center"> <td align="center">
<a href="https://github.com/InDieTasten"> <a href="https://github.com/InDieTasten">
<img src="https://avatars.githubusercontent.com/u/7047377?u=8d8f8017628b38bc46dcbf3620e194b01d3fb2d1&v=4" width="80;" alt="InDieTasten"/> <img src="https://avatars.githubusercontent.com/u/7047377?u=8d8f8017628b38bc46dcbf3620e194b01d3fb2d1&v=4" width="80;" alt="InDieTasten"/>
@@ -1173,6 +1173,13 @@ Huge thanks to these wonderful people, who sponsor me on GitHub, their support h
<sub><b>Brian McGonagill</b></sub> <sub><b>Brian McGonagill</b></sub>
</a> </a>
</td> </td>
<td align="center">
<a href="https://github.com/arcestia">
<img src="https://avatars.githubusercontent.com/u/7936962?v=4" width="80;" alt="arcestia"/>
<br />
<sub><b>Laurensius Jeffrey</b></sub>
</a>
</td>
<td align="center"> <td align="center">
<a href="https://github.com/vlad-tim"> <a href="https://github.com/vlad-tim">
<img src="https://avatars.githubusercontent.com/u/11474041?u=eee43705b54d2ec9f51fc4fcce5ad18dd17c87e4&v=4" width="80;" alt="vlad-tim"/> <img src="https://avatars.githubusercontent.com/u/11474041?u=eee43705b54d2ec9f51fc4fcce5ad18dd17c87e4&v=4" width="80;" alt="vlad-tim"/>
@@ -1189,13 +1196,6 @@ Huge thanks to these wonderful people, who sponsor me on GitHub, their support h
</td> </td>
</tr> </tr>
<tr> <tr>
<td align="center">
<a href="https://github.com/patvdv">
<img src="https://avatars.githubusercontent.com/u/12430107?u=e8911c2fb91af4d30432f76da8c40927b2830bd7&v=4" width="80;" alt="patvdv"/>
<br />
<sub><b>Patrick Van Der Veken</b></sub>
</a>
</td>
<td align="center"> <td align="center">
<a href="https://github.com/mryesiller"> <a href="https://github.com/mryesiller">
<img src="https://avatars.githubusercontent.com/u/24632172?u=0d20f2d615158f87cd60a3398d3efb026c32f291&v=4" width="80;" alt="mryesiller"/> <img src="https://avatars.githubusercontent.com/u/24632172?u=0d20f2d615158f87cd60a3398d3efb026c32f291&v=4" width="80;" alt="mryesiller"/>
@@ -1204,17 +1204,10 @@ Huge thanks to these wonderful people, who sponsor me on GitHub, their support h
</a> </a>
</td> </td>
<td align="center"> <td align="center">
<a href="https://github.com/forwardemail"> <a href="https://github.com/sushibait">
<img src="https://avatars.githubusercontent.com/u/32481436?v=4" width="80;" alt="forwardemail"/> <img src="https://avatars.githubusercontent.com/u/26634535?v=4" width="80;" alt="sushibait"/>
<br /> <br />
<sub><b>Forward Email - Open-source & Privacy-focused Email Service (2023)</b></sub> <sub><b>Shiverme Timbers</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/Bastii717">
<img src="https://avatars.githubusercontent.com/u/53431819?u=604977bed6ad6875ada890d0d3765a4cacc2fa14&v=4" width="80;" alt="Bastii717"/>
<br />
<sub><b>Bastii717</b></sub>
</a> </a>
</td> </td>
<td align="center"> <td align="center">
@@ -1224,6 +1217,13 @@ Huge thanks to these wonderful people, who sponsor me on GitHub, their support h
<sub><b>Umbrel</b></sub> <sub><b>Umbrel</b></sub>
</a> </a>
</td> </td>
<td align="center">
<a href="https://github.com/OlliVHH">
<img src="https://avatars.githubusercontent.com/u/84959562?v=4" width="80;" alt="OlliVHH"/>
<br />
<sub><b>HamburgerJung</b></sub>
</a>
</td>
<td align="center"> <td align="center">
<a href="https://github.com/frankdez93"> <a href="https://github.com/frankdez93">
<img src="https://avatars.githubusercontent.com/u/87549420?v=4" width="80;" alt="frankdez93"/> <img src="https://avatars.githubusercontent.com/u/87549420?v=4" width="80;" alt="frankdez93"/>
@@ -1231,8 +1231,6 @@ Huge thanks to these wonderful people, who sponsor me on GitHub, their support h
<sub><b>Frankdez93</b></sub> <sub><b>Frankdez93</b></sub>
</a> </a>
</td> </td>
</tr>
<tr>
<td align="center"> <td align="center">
<a href="https://github.com/terminaltrove"> <a href="https://github.com/terminaltrove">
<img src="https://avatars.githubusercontent.com/u/121595180?v=4" width="80;" alt="terminaltrove"/> <img src="https://avatars.githubusercontent.com/u/121595180?v=4" width="80;" alt="terminaltrove"/>
@@ -1240,19 +1238,28 @@ Huge thanks to these wonderful people, who sponsor me on GitHub, their support h
<sub><b>Terminal Trove</b></sub> <sub><b>Terminal Trove</b></sub>
</a> </a>
</td> </td>
</tr>
<tr>
<td align="center"> <td align="center">
<a href="https://github.com/nrvo"> <a href="https://github.com/st617">
<img src="https://avatars.githubusercontent.com/u/151435968?u=e1dcb307fd0efdc45cddbe9490a7b956e4da6835&v=4" width="80;" alt="nrvo"/> <img src="https://avatars.githubusercontent.com/u/128325650?v=4" width="80;" alt="st617"/>
<br /> <br />
<sub><b>Nrvo</b></sub> <sub><b>st617</b></sub>
</a> </a>
</td> </td>
<td align="center"> <td align="center">
<a href="https://github.com/hudsonrock-partnerships"> <a href="https://github.com/hudsonrock-partnerships">
<img src="https://avatars.githubusercontent.com/u/163282900?v=4" width="80;" alt="hudsonrock-partnerships"/> <img src="https://avatars.githubusercontent.com/u/163282900?u=5f2667f7fe5d284ac7a2da6b0800ea8970b0fcbf&v=4" width="80;" alt="hudsonrock-partnerships"/>
<br /> <br />
<sub><b>hudsonrock-partnerships</b></sub> <sub><b>hudsonrock-partnerships</b></sub>
</a> </a>
</td>
<td align="center">
<a href="https://github.com/CarterPerez-dev">
<img src="https://avatars.githubusercontent.com/u/188120068?v=4" width="80;" alt="CarterPerez-dev"/>
<br />
<sub><b>Carter Perez</b></sub>
</a>
</td> </td>
</tr> </tr>
<tbody> <tbody>

View File

@@ -8,6 +8,9 @@ const TIMEOUT = process.env.API_TIMEOUT_LIMIT ? parseInt(process.env.API_TIMEOUT
// If present, set CORS allowed origins for responses // If present, set CORS allowed origins for responses
const ALLOWED_ORIGINS = process.env.API_CORS_ORIGIN || '*'; const ALLOWED_ORIGINS = process.env.API_CORS_ORIGIN || '*';
// Disable everything :( Setting this env var will turn off the instance, and show message
const DISABLE_EVERYTHING = !!process.env.VITE_DISABLE_EVERYTHING;
// Set the platform currently being used // Set the platform currently being used
let PLATFORM = 'NETLIFY'; let PLATFORM = 'NETLIFY';
if (process.env.PLATFORM) { PLATFORM = process.env.PLATFORM.toUpperCase(); } if (process.env.PLATFORM) { PLATFORM = process.env.PLATFORM.toUpperCase(); }
@@ -21,7 +24,6 @@ const headers = {
'Content-Type': 'application/json;charset=UTF-8', 'Content-Type': 'application/json;charset=UTF-8',
}; };
const timeoutErrorMsg = 'You can re-trigger this request, by clicking "Retry"\n' const timeoutErrorMsg = 'You can re-trigger this request, by clicking "Retry"\n'
+ 'If you\'re running your own instance of Web Check, then you can ' + 'If you\'re running your own instance of Web Check, then you can '
+ 'resolve this issue, by increasing the timeout limit in the ' + 'resolve this issue, by increasing the timeout limit in the '
@@ -31,6 +33,14 @@ const timeoutErrorMsg = 'You can re-trigger this request, by clicking "Retry"\n'
+ 'in order to keep running costs affordable, so that Web Check can ' + 'in order to keep running costs affordable, so that Web Check can '
+ 'remain freely available for everyone.'; + 'remain freely available for everyone.';
const disabledErrorMsg = 'Error - WebCheck Temporarily Disabled.\n\n'
+ 'We\'re sorry, but due to the increased cost of running Web Check '
+ 'we\'ve had to temporatily disable the public instand. '
+ 'We\'re activley looking for affordable ways to keep Web Check running, '
+ 'while free to use for everybody.\n'
+ 'In the meantime, since we\'ve made our code free and open source, '
+ 'you can get Web Check running on your own system, by following the instructions in our GitHub repo';
// A middleware function used by all API routes on all platforms // A middleware function used by all API routes on all platforms
const commonMiddleware = (handler) => { const commonMiddleware = (handler) => {
@@ -45,6 +55,11 @@ const commonMiddleware = (handler) => {
// Vercel // Vercel
const vercelHandler = async (request, response) => { const vercelHandler = async (request, response) => {
if (DISABLE_EVERYTHING) {
response.status(503).json({ error: disabledErrorMsg });
}
const queryParams = request.query || {}; const queryParams = request.query || {};
const rawUrl = queryParams.url; const rawUrl = queryParams.url;
@@ -83,6 +98,15 @@ const commonMiddleware = (handler) => {
const queryParams = event.queryStringParameters || event.query || {}; const queryParams = event.queryStringParameters || event.query || {};
const rawUrl = queryParams.url; const rawUrl = queryParams.url;
if (DISABLE_EVERYTHING) {
callback(null, {
statusCode: 503,
body: JSON.stringify({ error: 'Web-Check is temporarily disabled. Please try again later.' }),
headers,
});
return;
}
if (!rawUrl) { if (!rawUrl) {
callback(null, { callback(null, {
statusCode: 500, statusCode: 500,

View File

@@ -2,12 +2,17 @@ import net from 'net';
import middleware from './_common/middleware.js'; import middleware from './_common/middleware.js';
// A list of commonly used ports. // A list of commonly used ports.
const PORTS = [ const DEFAULT_PORTS_TO_CHECK = [
20, 21, 22, 23, 25, 53, 80, 67, 68, 69, 20, 21, 22, 23, 25, 53, 80, 67, 68, 69,
110, 119, 123, 143, 156, 161, 162, 179, 194, 110, 119, 123, 143, 156, 161, 162, 179, 194,
389, 443, 587, 993, 995, 389, 443, 587, 993, 995,
3000, 3306, 3389, 5060, 5900, 8000, 8080, 8888 3000, 3306, 3389, 5060, 5900, 8000, 8080, 8888
]; ];
/*
* Checks if the env PORTS_TO_CHECK is set, if so the string is split via "," to get an array of ports to check.
* If the env is not set, return the default commonly used ports.
*/
const PORTS = process.env.PORTS_TO_CHECK ? process.env.PORTS_TO_CHECK.split(",") : DEFAULT_PORTS_TO_CHECK
async function checkPort(port, domain) { async function checkPort(port, domain) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {

View File

@@ -1,10 +1,67 @@
import puppeteer from 'puppeteer-core'; import puppeteer from 'puppeteer-core';
import chromium from 'chrome-aws-lambda'; import chromium from 'chrome-aws-lambda';
import middleware from './_common/middleware.js'; import middleware from './_common/middleware.js';
import { execFile } from 'child_process';
import { promises as fs } from 'fs';
import path from 'path';
import pkg from 'uuid';
const { v4: uuidv4 } = pkg;
// Helper function for direct chromium screenshot as fallback
const directChromiumScreenshot = async (url) => {
console.log(`[DIRECT-SCREENSHOT] Starting direct screenshot process for URL: ${url}`);
// Create a tmp filename
const tmpDir = '/tmp';
const uuid = uuidv4();
const screenshotPath = path.join(tmpDir, `screenshot-${uuid}.png`);
console.log(`[DIRECT-SCREENSHOT] Will save screenshot to: ${screenshotPath}`);
return new Promise((resolve, reject) => {
const chromePath = process.env.CHROME_PATH || '/usr/bin/chromium';
const args = [
'--headless',
'--disable-gpu',
'--no-sandbox',
`--screenshot=${screenshotPath}`,
url
];
console.log(`[DIRECT-SCREENSHOT] Executing: ${chromePath} ${args.join(' ')}`);
execFile(chromePath, args, async (error, stdout, stderr) => {
if (error) {
console.error(`[DIRECT-SCREENSHOT] Chromium error: ${error.message}`);
return reject(error);
}
try {
// Read the screenshot file
const screenshotData = await fs.readFile(screenshotPath);
console.log(`[DIRECT-SCREENSHOT] Screenshot read successfully`);
// Convert to base64
const base64Data = screenshotData.toString('base64');
await fs.unlink(screenshotPath).catch(err =>
console.warn(`[DIRECT-SCREENSHOT] Failed to delete temp file: ${err.message}`)
);
resolve(base64Data);
} catch (readError) {
console.error(`[DIRECT-SCREENSHOT] Failed reading screenshot: ${readError.message}`);
reject(readError);
}
});
});
};
const screenshotHandler = async (targetUrl) => { const screenshotHandler = async (targetUrl) => {
console.log(`[SCREENSHOT] Request received for URL: ${targetUrl}`);
if (!targetUrl) { if (!targetUrl) {
console.error('[SCREENSHOT] URL is missing from queryStringParameters');
throw new Error('URL is missing from queryStringParameters'); throw new Error('URL is missing from queryStringParameters');
} }
@@ -15,26 +72,45 @@ const screenshotHandler = async (targetUrl) => {
try { try {
new URL(targetUrl); new URL(targetUrl);
} catch (error) { } catch (error) {
console.error(`[SCREENSHOT] URL provided is invalid: ${targetUrl}`);
throw new Error('URL provided is invalid'); throw new Error('URL provided is invalid');
} }
// First try direct Chromium
try {
console.log(`[SCREENSHOT] Using direct Chromium method for URL: ${targetUrl}`);
const base64Screenshot = await directChromiumScreenshot(targetUrl);
console.log(`[SCREENSHOT] Direct screenshot successful`);
return { image: base64Screenshot };
} catch (directError) {
console.error(`[SCREENSHOT] Direct screenshot method failed: ${directError.message}`);
console.log(`[SCREENSHOT] Falling back to puppeteer method...`);
}
// fall back puppeteer
let browser = null; let browser = null;
try { try {
console.log(`[SCREENSHOT] Launching puppeteer browser`);
browser = await puppeteer.launch({ browser = await puppeteer.launch({
args: [...chromium.args, '--no-sandbox'], // Add --no-sandbox flag args: [...chromium.args, '--no-sandbox'], // Add --no-sandbox flag
defaultViewport: { width: 800, height: 600 }, defaultViewport: { width: 800, height: 600 },
executablePath: process.env.CHROME_PATH || await chromium.executablePath, executablePath: process.env.CHROME_PATH || '/usr/bin/chromium',
headless: chromium.headless, headless: true,
ignoreHTTPSErrors: true, ignoreHTTPSErrors: true,
ignoreDefaultArgs: ['--disable-extensions'], ignoreDefaultArgs: ['--disable-extensions'],
}); });
console.log(`[SCREENSHOT] Creating new page`);
let page = await browser.newPage(); let page = await browser.newPage();
console.log(`[SCREENSHOT] Setting page preferences`);
await page.emulateMediaFeatures([{ name: 'prefers-color-scheme', value: 'dark' }]); await page.emulateMediaFeatures([{ name: 'prefers-color-scheme', value: 'dark' }]);
page.setDefaultNavigationTimeout(8000); page.setDefaultNavigationTimeout(8000);
console.log(`[SCREENSHOT] Navigating to URL: ${targetUrl}`);
await page.goto(targetUrl, { waitUntil: 'domcontentloaded' }); await page.goto(targetUrl, { waitUntil: 'domcontentloaded' });
console.log(`[SCREENSHOT] Checking if body element exists`);
await page.evaluate(() => { await page.evaluate(() => {
const selector = 'body'; const selector = 'body';
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@@ -46,13 +122,20 @@ const screenshotHandler = async (targetUrl) => {
}); });
}); });
console.log(`[SCREENSHOT] Taking screenshot`);
const screenshotBuffer = await page.screenshot(); const screenshotBuffer = await page.screenshot();
console.log(`[SCREENSHOT] Converting screenshot to base64`);
const base64Screenshot = screenshotBuffer.toString('base64'); const base64Screenshot = screenshotBuffer.toString('base64');
console.log(`[SCREENSHOT] Screenshot complete, returning image`);
return { image: base64Screenshot }; return { image: base64Screenshot };
} catch (error) {
console.error(`[SCREENSHOT] Puppeteer screenshot failed: ${error.message}`);
throw error;
} finally { } finally {
if (browser !== null) { if (browser !== null) {
console.log(`[SCREENSHOT] Closing browser`);
await browser.close(); await browser.close();
} }
} }

View File

@@ -1,7 +1,7 @@
{ {
"name": "web-check", "name": "web-check",
"type": "module", "type": "module",
"version": "2.0.0", "version": "2.0.2",
"homepage": "https://web-check.xyz", "homepage": "https://web-check.xyz",
"scripts": { "scripts": {
"start": "node server", "start": "node server",

View File

@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="155" height="20" role="img" aria-label="Website: web-check.zyz"><title>Website: web-check.zyz</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="155" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="70" height="20" fill="#1c1d28"/><rect x="70" width="85" height="20" fill="#9fef00"/><rect width="155" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyBmaWxsPSJ3aGl0ZSIgcm9sZT0iaW1nIiB2aWV3Qm94PSIwIDAgMjQgMjQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHRpdGxlPkdvb2dsZSBDbG91ZCBTdG9yYWdlPC90aXRsZT48cGF0aCBkPSJNMjQgMi40djguNGgtMi40VjIuNEgyNHpNMCAxMC44aDIuNFYyLjRIMHY4LjR6bTMtOC40aDE4djguNEgzVjIuNHptMTIuNiA0LjJhMS44IDEuOCAwIDEgMCAzLjYgMCAxLjggMS44IDAgMCAwLTMuNiAwem0tMTAuOC42SDEyVjZINC44djEuMnptMTYuOCAxNC40SDI0di04LjRoLTIuNHY4LjR6TTAgMjEuNmgyLjR2LTguNEgwdjguNHptMy04LjRoMTh2OC40SDN2LTguNHptMTIuNiA0LjJhMS44IDEuOCAwIDEgMCAzLjYgMCAxLjggMS44IDAgMCAwLTMuNiAwek00LjggMThIMTJ2LTEuMkg0LjhWMTh6Ii8+PC9zdmc+"/><text aria-hidden="true" x="445" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="430">Website</text><text x="445" y="140" transform="scale(.1)" fill="#fff" textLength="430">Website</text><text aria-hidden="true" x="1115" y="150" fill="#ccc" fill-opacity=".3" transform="scale(.1)" textLength="750">web-check.zyz</text><text x="1115" y="140" transform="scale(.1)" fill="#333" textLength="750">webcheck.zyz</text></g></svg> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="155" height="20" role="img" aria-label="Website: web-check.xyz"><title>Website: web-check.xyz</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="155" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="70" height="20" fill="#1c1d28"/><rect x="70" width="85" height="20" fill="#9fef00"/><rect width="155" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><image x="5" y="3" width="14" height="14" xlink:href="data:image/svg+xml;base64,PHN2ZyBmaWxsPSJ3aGl0ZSIgcm9sZT0iaW1nIiB2aWV3Qm94PSIwIDAgMjQgMjQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHRpdGxlPkdvb2dsZSBDbG91ZCBTdG9yYWdlPC90aXRsZT48cGF0aCBkPSJNMjQgMi40djguNGgtMi40VjIuNEgyNHpNMCAxMC44aDIuNFYyLjRIMHY4LjR6bTMtOC40aDE4djguNEgzVjIuNHptMTIuNiA0LjJhMS44IDEuOCAwIDEgMCAzLjYgMCAxLjggMS44IDAgMCAwLTMuNiAwem0tMTAuOC42SDEyVjZINC44djEuMnptMTYuOCAxNC40SDI0di04LjRoLTIuNHY4LjR6TTAgMjEuNmgyLjR2LTguNEgwdjguNHptMy04LjRoMTh2OC40SDN2LTguNHptMTIuNiA0LjJhMS44IDEuOCAwIDEgMCAzLjYgMCAxLjggMS44IDAgMCAwLTMuNiAwek00LjggMThIMTJ2LTEuMkg0LjhWMTh6Ii8+PC9zdmc+"/><text aria-hidden="true" x="445" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="430">Website</text><text x="445" y="140" transform="scale(.1)" fill="#fff" textLength="430">Website</text><text aria-hidden="true" x="1115" y="150" fill="#ccc" fill-opacity=".3" transform="scale(.1)" textLength="750">web-check.xyz</text><text x="1115" y="140" transform="scale(.1)" fill="#333" textLength="750">webcheck.zyz</text></g></svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -0,0 +1,27 @@
<div class="banner">
<p>
⚠️ Web Check is temporarily disabled due to excess demand and associated costs.
We apologize for any inconvenience and are working on a solution.
</p>
</div>
<style>
.banner {
position: relative;
top: 0;
left: 0;
width: 100%;
background-color: var(--primary);
color: var(--background);
padding: 0.75rem 1rem;
text-align: center;
z-index: 1000;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.banner p {
margin: 0;
font-size: 0.95rem;
line-height: 1.4;
}
</style>

View File

@@ -22,7 +22,7 @@ const siteInfo = {
site: import.meta.env.SITE_URL || 'https://web-check.xyz', site: import.meta.env.SITE_URL || 'https://web-check.xyz',
analytics: { analytics: {
enable: import.meta.env.ENABLE_ANALYTICS, enable: import.meta.env.ENABLE_ANALYTICS,
domain: 'web-check.xyz', domain: 'web-check.as93.net',
script: 'https://no-track.as93.net/js/script.js', script: 'https://no-track.as93.net/js/script.js',
}, },
}; };
@@ -92,8 +92,7 @@ const makeBreadcrumbs = () => {
<!-- Non-tracking hit counter --> <!-- Non-tracking hit counter -->
{analytics.enable && ( {analytics.enable && (
<script defer is:inline type="text/partytown" <script defer data-domain={analytics.domain} src={analytics.script}></script>
data-domain={analytics.domain} src={analytics.script}></script>
)} )}
<!-- Schema.org markup for Google --> <!-- Schema.org markup for Google -->

View File

@@ -1,12 +1,15 @@
--- ---
import BaseLayout from '@layouts/Base.astro'; import BaseLayout from '@layouts/Base.astro';
import HeroForm from '@components/homepage/HeroForm.astro'; import HeroForm from '@components/homepage/HeroForm.astro';
import TempDisabled from '@/components/homepage/TempDisabled.astro';
import HomeBackground from '@/components/homepage/HomeBackground'; import HomeBackground from '@/components/homepage/HomeBackground';
import AboutSection from '@/components/homepage/AboutSection.astro'; import AboutSection from '@/components/homepage/AboutSection.astro';
import Footer from '@components/scafold/Footer.astro'; import Footer from '@components/scafold/Footer.astro';
const isBossServer = import.meta.env.BOSS_SERVER === true; const isBossServer = import.meta.env.BOSS_SERVER === true;
const disableEverything = import.meta.env.VITE_DISABLE_EVERYTHING === true;
// Redirect strait to /check or /check/:url if running as self-hosted instance // Redirect strait to /check or /check/:url if running as self-hosted instance
if (!isBossServer) { if (!isBossServer) {
const searchUrl = new URLSearchParams(new URL(Astro.request.url).search).get('url'); const searchUrl = new URLSearchParams(new URL(Astro.request.url).search).get('url');
@@ -20,6 +23,7 @@ if (!isBossServer) {
<Fragment slot="head"> <Fragment slot="head">
{!isBossServer && (<meta http-equiv="refresh" content="0; url=/check" />)} {!isBossServer && (<meta http-equiv="refresh" content="0; url=/check" />)}
</Fragment> </Fragment>
{ disableEverything && <TempDisabled />}
<main> <main>
<HeroForm /> <HeroForm />
<AboutSection /> <AboutSection />

View File

@@ -151,7 +151,7 @@ export const ExpandableRow = (props: RowProps) => {
return ( return (
<StyledRow as="li" key={`${row.lbl}-${index}`}> <StyledRow as="li" key={`${row.lbl}-${index}`}>
<span className="lbl" title={row.title?.toString()}>{row.lbl}</span> <span className="lbl" title={row.title?.toString()}>{row.lbl}</span>
<span className="val" title={row.val} onClick={() => copyToClipboard(row.val)}> <span className="val" title={row.val?.toString()} onClick={() => copyToClipboard(row.val)}>
{formatValue(row.val)} {formatValue(row.val)}
</span> </span>
{ row.plaintext && <PlainText>{row.plaintext}</PlainText> } { row.plaintext && <PlainText>{row.plaintext}</PlainText> }

View File

@@ -11,15 +11,17 @@ const cardStyles = `
`; `;
const RobotsTxtCard = ( props: { data: { robots: RowProps[]}, title: string, actionButtons: any}): JSX.Element => { const RobotsTxtCard = ( props: { data: { robots: RowProps[]}, title: string, actionButtons: any}): JSX.Element => {
const robots = props.data; const { data } = props;
const robots = data?.robots || [];
return ( return (
<Card heading={props.title} actionButtons={props.actionButtons} styles={cardStyles}> <Card heading={props.title} actionButtons={props.actionButtons} styles={cardStyles}>
<div className="content"> <div className="content">
{ {
robots.robots.length === 0 && <p>No crawl rules found.</p> robots.length === 0 && <p>No crawl rules found.</p>
} }
{ {
robots.robots.map((row: RowProps, index: number) => { robots.map((row: RowProps, index: number) => {
return ( return (
<Row key={`${row.lbl}-${index}`} lbl={row.lbl} val={row.val} /> <Row key={`${row.lbl}-${index}`} lbl={row.lbl} val={row.val} />
) )

View File

@@ -213,11 +213,11 @@ const resources = [
searchLink: 'https://radar.cloudflare.com/domains/domain/{URL}', searchLink: 'https://radar.cloudflare.com/domains/domain/{URL}',
}, },
{ {
title: 'Mozilla Observatory', title: 'Mozilla HTTP Observatory',
link: 'https://observatory.mozilla.org/', link: 'https://developer.mozilla.org/en-US/observatory',
icon: 'https://i.ibb.co/hBWh9cj/logo-mozm-5e95c457fdd1.png', icon: 'https://i.ibb.co/hBWh9cj/logo-mozm-5e95c457fdd1.png',
description: 'Assesses website security posture by analyzing various security headers and practices', description: 'Assesses website security posture by analyzing various security headers and practices',
searchLink: 'https://observatory.mozilla.org/analyze/{URL}', searchLink: 'https://developer.mozilla.org/en-US/observatory/analyze?host={URL}',
}, },
{ {
title: 'AbuseIPDB', title: 'AbuseIPDB',

View File

@@ -4,6 +4,7 @@ import 'react-toastify/dist/ReactToastify.css';
import type { LoadingState } from 'web-check-live/components/misc/ProgressBar'; import type { LoadingState } from 'web-check-live/components/misc/ProgressBar';
import type { AddressType } from 'web-check-live/utils/address-type-checker'; import type { AddressType } from 'web-check-live/utils/address-type-checker';
import keys from 'web-check-live/utils/get-keys';
interface UseIpAddressProps<ResultType = any> { interface UseIpAddressProps<ResultType = any> {
// Unique identifier for this job type // Unique identifier for this job type
@@ -37,6 +38,10 @@ const useMotherOfAllHooks = <ResultType = any>(params: UseIpAddressProps<ResultT
// Fire off the HTTP fetch request, then set results and update loading / error state // Fire off the HTTP fetch request, then set results and update loading / error state
const doTheFetch = () => { const doTheFetch = () => {
if (keys.disableEverything) {
updateLoadingJobs(jobId, 'skipped', 'Web-Check is temporarily disabled. Please try again later.', reset);
return Promise.resolve();
}
return fetchRequest() return fetchRequest()
.then((res: any) => { .then((res: any) => {
if (!res) { // No response :( if (!res) { // No response :(

View File

@@ -2,6 +2,7 @@
const keys = { const keys = {
shodan: import.meta.env.REACT_APP_SHODAN_API_KEY || "default_value_if_not_set", shodan: import.meta.env.REACT_APP_SHODAN_API_KEY || "default_value_if_not_set",
whoApi: import.meta.env.REACT_APP_WHO_API_KEY || "default_value_if_not_set", whoApi: import.meta.env.REACT_APP_WHO_API_KEY || "default_value_if_not_set",
disableEverything: import.meta.env.VITE_DISABLE_EVERYTHING === 'true',
}; };
// const keys = process && process.env ? { // const keys = process && process.env ? {
// shodan: process.env.REACT_APP_SHODAN_API_KEY, // shodan: process.env.REACT_APP_SHODAN_API_KEY,

View File

@@ -1,4 +1,6 @@
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
import colors from 'web-check-live/styles/colors'; import colors from 'web-check-live/styles/colors';
import Heading from 'web-check-live/components/Form/Heading'; import Heading from 'web-check-live/components/Form/Heading';
@@ -118,6 +120,21 @@ const makeAnchor = (title: string): string => {
}; };
const About = (): JSX.Element => { const About = (): JSX.Element => {
const location = useLocation();
useEffect(() => {
// Scroll to hash fragment if present
if (location.hash) {
// Add a small delay to ensure the page has fully rendered
setTimeout(() => {
const element = document.getElementById(location.hash.slice(1));
if (element) {
element.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
}, 100);
}
}, [location]);
return ( return (
<div> <div>
<AboutContainer> <AboutContainer>

View File

@@ -278,7 +278,7 @@ const Home = (): JSX.Element => {
<Heading as="h2" size="small" color={colors.primary}>Supported Checks</Heading> <Heading as="h2" size="small" color={colors.primary}>Supported Checks</Heading>
<ul> <ul>
{docs.map((doc, index) => (<li key={index}>{doc.title}</li>))} {docs.map((doc, index) => (<li key={index}>{doc.title}</li>))}
<li><Link to="/about">+ more!</Link></li> <li><Link to="/check/about">+ more!</Link></li>
</ul> </ul>
</div> </div>
<div className="links"> <div className="links">
@@ -288,7 +288,7 @@ const Home = (): JSX.Element => {
<a target="_blank" rel="noreferrer" href="https://app.netlify.com/start/deploy?repository=https://github.com/lissy93/web-check" title="Deploy your own private or public instance of Web-Check to Netlify"> <a target="_blank" rel="noreferrer" href="https://app.netlify.com/start/deploy?repository=https://github.com/lissy93/web-check" title="Deploy your own private or public instance of Web-Check to Netlify">
<Button>Deploy your own</Button> <Button>Deploy your own</Button>
</a> </a>
<Link to="/about#api-documentation" title="View the API documentation, to use Web-Check programmatically"> <Link to="/check/about#api-documentation" title="View the API documentation, to use Web-Check programmatically">
<Button>API Docs</Button> <Button>API Docs</Button>
</Link> </Link>
</div> </div>