diff --git a/.github/SECURITY.md b/.github/SECURITY.md new file mode 100644 index 00000000..842343c1 --- /dev/null +++ b/.github/SECURITY.md @@ -0,0 +1,17 @@ +# Security Policy + +byteflow.tools is a privacy-first, browser-local developer tools project. Most tool payloads should stay in the user's browser and must not be included in public reports. + +## Reporting a Vulnerability + +Report suspected vulnerabilities privately through GitHub Security Advisories: + +https://github.com/baixiangcpp/byteflow.tools/security/advisories/new + +Do not open a public issue for exploitable behavior, data exposure, bypasses, or reports that require private reproduction details. Do not include production secrets, API keys, JWTs, certificates, private keys, customer data, logs, HAR files, uploaded files, screenshots with private data, or full request/response bodies. + +For non-security bugs and feature requests, use GitHub Issues. + +## Supported Version + +Security fixes target the hosted site and the current `main` branch. diff --git a/public/.well-known/security.txt b/public/.well-known/security.txt new file mode 100644 index 00000000..f63cf29b --- /dev/null +++ b/public/.well-known/security.txt @@ -0,0 +1,5 @@ +Contact: https://github.com/baixiangcpp/byteflow.tools/security/advisories/new +Policy: https://github.com/baixiangcpp/byteflow.tools/security/policy +Canonical: https://byteflow.tools/.well-known/security.txt +Preferred-Languages: en +Expires: 2027-06-24T00:00:00Z diff --git a/public/_redirects b/public/_redirects index a53cbd1e..71bb5347 100644 --- a/public/_redirects +++ b/public/_redirects @@ -1,3 +1,4 @@ +/security.txt /.well-known/security.txt 301 /en/cron-expression-generator /en/crontab-generator 301 /zh-CN/cron-expression-generator /zh-CN/crontab-generator 301 /zh-TW/cron-expression-generator /zh-TW/crontab-generator 301 diff --git a/scripts/generators/generate-legacy-routes.js b/scripts/generators/generate-legacy-routes.js index 4b4bb06f..04a5480b 100644 --- a/scripts/generators/generate-legacy-routes.js +++ b/scripts/generators/generate-legacy-routes.js @@ -9,6 +9,9 @@ const TOOL_ALIASES_PATH = path.join(ROOT, "src/core/registry/tool-aliases.json") const REDIRECTS_PATH = path.join(ROOT, "public/_redirects") const LOCALES = ["en", "zh-CN", "zh-TW", "ja", "ko", "de", "fr"] const REDIRECT_STATUSES = new Set([301, 302]) +const STATIC_REDIRECT_LINES = [ + "/security.txt /.well-known/security.txt 301", +] const CHECK_ONLY = process.argv.includes("--check") function readText(filePath) { @@ -90,6 +93,7 @@ export function loadLegacyTaxonomyRedirects() { function buildRedirectLines(routes, taxonomyRedirects = loadLegacyTaxonomyRedirects()) { return [ + ...STATIC_REDIRECT_LINES, ...routes.flatMap((route) => { if (!REDIRECT_STATUSES.has(route.status)) return [] return LOCALES.map((locale) => `/${locale}/${route.sourceSlug} /${locale}/${route.targetSlug} ${route.status}`) diff --git a/src/app/[lang]/contact/page.tsx b/src/app/[lang]/contact/page.tsx index 6ab8727e..9f01c4fa 100644 --- a/src/app/[lang]/contact/page.tsx +++ b/src/app/[lang]/contact/page.tsx @@ -3,12 +3,13 @@ import { useLang } from "@/core/i18n/lang-provider" import { toast } from "sonner" import { Button } from "@/components/ui/button" -import { Github, Mail, MessageSquare, ExternalLink } from "lucide-react" +import { Github, Mail, MessageSquare, ExternalLink, ShieldCheck } from "lucide-react" import { safeClipboardWrite } from "@/core/clipboard/clipboard" const EMAIL_ADDRESS = "contact@byteflow.tools" const GITHUB_REPOSITORY_URL = "https://github.com/baixiangcpp/byteflow.tools" const GITHUB_ISSUES_URL = "https://github.com/baixiangcpp/byteflow.tools/issues" +const SECURITY_ADVISORY_URL = "https://github.com/baixiangcpp/byteflow.tools/security/advisories/new" export default function ContactPage() { const { t } = useLang() @@ -17,6 +18,7 @@ export default function ContactPage() { const links = [ { icon: Github, title: "GitHub", desc: p.contact_github_desc, href: GITHUB_REPOSITORY_URL, external: true }, { icon: MessageSquare, title: p.contact_issues_title, desc: p.contact_issues_desc, href: GITHUB_ISSUES_URL, external: true }, + { icon: ShieldCheck, title: p.contact_security_title, desc: p.contact_security_desc, href: SECURITY_ADVISORY_URL, external: true }, ] const handleCopyEmail = async () => { @@ -37,7 +39,7 @@ export default function ContactPage() {
{p.contact_intro}
-+ {requireTranslationValue(labels.hosts_label, "common.external_network_notice.hosts_label")}:{" "} + {hosts.join(", ")} +
++ {requireTranslationValue(labels.purpose_label, "common.external_network_notice.purpose_label")}:{" "} + {purpose} +
++ {requireTranslationValue(labels.data_sent_label, "common.external_network_notice.data_sent_label")}:{" "} + {dataSentLabel} +
++ + {rightsGuidance || requireTranslationValue(labels.confirm_rights, "common.external_network_notice.confirm_rights")} +
+ +{error ? toolT.empty_state_error : toolT.empty_state_no_match}
+{isEvaluating ? toolT.evaluating_label : error ? toolT.empty_state_error : toolT.empty_state_no_match}