one
Version:
One is a new React Framework that makes Vite serve both native and web.
254 lines (252 loc) • 8.96 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all) __defProp(target, name, {
get: all[name],
enumerable: true
});
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
get: () => from[key],
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
});
}
return to;
};
var __toCommonJS = mod => __copyProps(__defProp({}, "__esModule", {
value: true
}), mod);
var securityScan_exports = {};
__export(securityScan_exports, {
runSecurityScan: () => runSecurityScan,
scanBundleForSecrets: () => scanBundleForSecrets
});
module.exports = __toCommonJS(securityScan_exports);
var import_promises = require("fs/promises");
var import_path = require("path");
var SECRET_PATTERNS = [
// api tokens / keys with known prefixes
["Anthropic API key", /sk-ant-[A-Za-z0-9_-]{20,}/g], ["OpenAI API key", /sk-proj-[A-Za-z0-9_-]{20,}/g], ["Stripe secret key", /sk_live_[A-Za-z0-9]{20,}/g], ["Stripe webhook secret", /whsec_[A-Za-z0-9]{20,}/g], ["GitHub token", /gh[ps]_[A-Za-z0-9]{36,}/g], ["GitHub PAT", /github_pat_[A-Za-z0-9_]{20,}/g], ["AWS access key", RegExp("(?<![A-Za-z0-9])AKIA[0-9A-Z]{16}(?![A-Za-z0-9])", "g")], ["Postmark server token", /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/g], ["Bearer token assignment", /["']Bearer\s+[A-Za-z0-9_.-]{20,}["']/g], ["Generic secret assignment", /(?:secret|password|api_key|apikey)\s*[:=]\s*["'][A-Za-z0-9_-]{16,}["']/gi],
// known env var names that should never be inlined
["BETTER_AUTH_SECRET value", /BETTER_AUTH_SECRET["']\s*[:=]\s*["'][^"']+["']/g], ["POSTMARK_SERVER_TOKEN value", /POSTMARK_SERVER_TOKEN["']\s*[:=]\s*["'][^"']+["']/g], ["ANTHROPIC_API_KEY value", /ANTHROPIC_API_KEY["']\s*[:=]\s*["'][^"']+["']/g]];
var SAFE_UUIDS = /* @__PURE__ */new Set(["00000000-0000-0000-0000-000000000000", "09259e3b-7be8-46f6-9801-106bf1866e1c",
// WebRTC SDP
"4ad15a19-80e2-4105-bf43-48039fd2963e"]);
var BUILTIN_SAFE_PATTERNS = [/sk_live_your_/, /sk_live_your_key/, /rk_\w+_\w+/,
// tamagui theme tokens
/sk_all_element/,
// DOM property names
/sk_personal_data/];
function createSafeMatcher(userPatterns) {
var safeStrings = new Set(SAFE_UUIDS);
var safeRegexes = [...BUILTIN_SAFE_PATTERNS];
if (userPatterns) {
var _iteratorNormalCompletion = true,
_didIteratorError = false,
_iteratorError = void 0;
try {
for (var _iterator = userPatterns[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var p = _step.value;
if (typeof p === "string") {
safeStrings.add(p);
} else {
safeRegexes.push(p);
}
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return != null) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
}
return function (match) {
if (safeStrings.has(match)) return true;
return safeRegexes.some(function (p2) {
return p2.test(match);
});
};
}
async function collectJSFiles(dir) {
var files = [];
async function walk(currentDir) {
var entries;
try {
entries = await (0, import_promises.readdir)(currentDir, {
withFileTypes: true
});
} catch (unused) {
return;
}
var _iteratorNormalCompletion = true,
_didIteratorError = false,
_iteratorError = void 0;
try {
for (var _iterator = entries[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var entry = _step.value;
var fullPath = (0, import_path.join)(currentDir, entry.name);
if (entry.isDirectory()) {
await walk(fullPath);
} else if (entry.name.endsWith(".js")) {
files.push(fullPath);
}
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return != null) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
}
await walk(dir);
return files;
}
async function scanBundleForSecrets(distDir, userSafePatterns) {
var isSafe = createSafeMatcher(userSafePatterns);
var files = await collectJSFiles(distDir);
var findings = [];
var _iteratorNormalCompletion = true,
_didIteratorError = false,
_iteratorError = void 0;
try {
for (var _iterator = files[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var fullPath = _step.value;
var relativePath = fullPath.slice(distDir.length + 1);
var content = void 0;
try {
content = await (0, import_promises.readFile)(fullPath, "utf-8");
} catch (unused) {
continue;
}
var _iteratorNormalCompletion1 = true,
_didIteratorError1 = false,
_iteratorError1 = void 0;
try {
for (var _iterator1 = SECRET_PATTERNS[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true) {
var [label, pattern] = _step1.value;
pattern.lastIndex = 0;
var match = void 0;
while ((match = pattern.exec(content)) !== null) {
var _ref;
var _beforeMatch_match;
var matched = match[0];
if (isSafe(matched)) continue;
var beforeMatch = content.slice(0, match.index);
var line = ((_ref = (_beforeMatch_match = beforeMatch.match(/\n/g)) === null || _beforeMatch_match === void 0 ? void 0 : _beforeMatch_match.length) !== null && _ref !== void 0 ? _ref : 0) + 1;
findings.push({
file: relativePath,
label,
match: matched.length > 40 ? `${matched.slice(0, 20)}...${matched.slice(-10)}` : matched,
line
});
}
}
} catch (err) {
_didIteratorError1 = true;
_iteratorError1 = err;
} finally {
try {
if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
_iterator1.return();
}
} finally {
if (_didIteratorError1) {
throw _iteratorError1;
}
}
}
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return != null) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
return {
clean: findings.length === 0,
findings
};
}
async function runSecurityScan(clientDir, level, safePatterns) {
console.info(`
\u{1F512} scanning client bundles for leaked secrets...
`);
var {
clean,
findings
} = await scanBundleForSecrets(clientDir, safePatterns);
if (clean) {
console.info(`
\u{1F512} security scan passed \u2014 no secrets found
`);
return true;
}
var icon = level === "error" ? "\u{1F6A8}" : "\u26A0\uFE0F";
var header = level === "error" ? `${icon} ${findings.length} secret(s) leaked into client bundle:` : `${icon} ${findings.length} potential secret(s) found in client bundle:`;
console.error(`
${header}
`);
var _iteratorNormalCompletion = true,
_didIteratorError = false,
_iteratorError = void 0;
try {
for (var _iterator = findings[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var f = _step.value;
console.error(` ${f.label}`);
console.error(` file: ${f.file}:${f.line}`);
console.error(` match: ${f.match}
`);
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return != null) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
if (level === "error") {
console.error(` Set build.securityScan to 'warn' to continue building despite findings.
`);
return false;
}
console.warn(` Set build.securityScan to 'error' to fail builds when secrets are detected.
`);
return true;
}
//# sourceMappingURL=securityScan.native.js.map