flareguard 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.lock +2962 -0
- package/Cargo.toml +66 -0
- package/LICENSE +21 -0
- package/README.md +115 -0
- package/bin/flareguard.js +78 -0
- package/package.json +50 -0
- package/scripts/postinstall.mjs +83 -0
- package/src/bindings/ast_scanner.rs +950 -0
- package/src/bindings/cli.rs +49 -0
- package/src/bindings/jsonc.rs +166 -0
- package/src/bindings/mod.rs +7 -0
- package/src/bindings/reporter.rs +328 -0
- package/src/bindings/types.rs +129 -0
- package/src/bindings/validator.rs +227 -0
- package/src/bindings/wrangler.rs +647 -0
- package/src/cli.rs +77 -0
- package/src/lib.rs +7 -0
- package/src/main.rs +451 -0
- package/src/origin/cli.rs +92 -0
- package/src/origin/cloudflare.rs +170 -0
- package/src/origin/confidence.rs +320 -0
- package/src/origin/crtsh.rs +144 -0
- package/src/origin/dns.rs +177 -0
- package/src/origin/enumerator.rs +271 -0
- package/src/origin/error.rs +19 -0
- package/src/origin/mock.rs +320 -0
- package/src/origin/mod.rs +19 -0
- package/src/origin/models.rs +167 -0
- package/src/origin/prober.rs +260 -0
- package/src/origin/remediation.rs +73 -0
- package/src/origin/report.rs +625 -0
- package/src/origin/scanner.rs +217 -0
- package/src/secrets/cli.rs +94 -0
- package/src/secrets/env_parser.rs +464 -0
- package/src/secrets/ignore.rs +139 -0
- package/src/secrets/mod.rs +14 -0
- package/src/secrets/report/json_format.rs +97 -0
- package/src/secrets/report/mod.rs +48 -0
- package/src/secrets/report/sarif.rs +225 -0
- package/src/secrets/report/text.rs +105 -0
- package/src/secrets/rules/builtin.rs +280 -0
- package/src/secrets/rules/entropy.rs +66 -0
- package/src/secrets/rules/mod.rs +7 -0
- package/src/secrets/rules/types.rs +183 -0
- package/src/secrets/scanner.rs +444 -0
- package/src/zone/cli.rs +111 -0
- package/src/zone/client/cf_client.rs +405 -0
- package/src/zone/client/mod.rs +5 -0
- package/src/zone/client/provider.rs +12 -0
- package/src/zone/mock_data.rs +481 -0
- package/src/zone/mod.rs +125 -0
- package/src/zone/models/audit.rs +194 -0
- package/src/zone/models/cloudflare.rs +252 -0
- package/src/zone/models/mod.rs +7 -0
- package/src/zone/models/sarif.rs +89 -0
- package/src/zone/reporters/html_rep.rs +345 -0
- package/src/zone/reporters/json_rep.rs +7 -0
- package/src/zone/reporters/mod.rs +9 -0
- package/src/zone/reporters/sarif_rep.rs +100 -0
- package/src/zone/reporters/terminal.rs +322 -0
- package/src/zone/rules/definitions.rs +201 -0
- package/src/zone/rules/evaluator.rs +484 -0
- package/src/zone/rules/mod.rs +5 -0
- package/src/zone/scoring.rs +104 -0
package/Cargo.toml
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "flareguard"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
edition = "2024"
|
|
5
|
+
authors = ["Brandon Hubbard <bhubbard@users.noreply.github.com>"]
|
|
6
|
+
description = "Unified Cloudflare Security Guardian — AST secret scanning, Worker binding verification, Zone posture auditing, and origin IP leak hunting."
|
|
7
|
+
license = "MIT"
|
|
8
|
+
readme = "README.md"
|
|
9
|
+
repository = "https://github.com/bhubbard/flareguard"
|
|
10
|
+
homepage = "https://bhubbard.github.io/flareguard"
|
|
11
|
+
keywords = ["cloudflare", "security", "waf", "workers", "cli"]
|
|
12
|
+
categories = ["command-line-utilities", "development-tools"]
|
|
13
|
+
|
|
14
|
+
[lib]
|
|
15
|
+
name = "flareguard"
|
|
16
|
+
path = "src/lib.rs"
|
|
17
|
+
|
|
18
|
+
[[bin]]
|
|
19
|
+
name = "flareguard"
|
|
20
|
+
path = "src/main.rs"
|
|
21
|
+
|
|
22
|
+
[dependencies]
|
|
23
|
+
# CLI & Args
|
|
24
|
+
clap = { version = "4.5", features = ["derive", "cargo", "env"] }
|
|
25
|
+
clap_complete = "4.5"
|
|
26
|
+
|
|
27
|
+
# Async & Networking
|
|
28
|
+
tokio = { version = "1.43", features = ["full"] }
|
|
29
|
+
reqwest = { version = "0.12", features = ["json"] }
|
|
30
|
+
futures = "0.3"
|
|
31
|
+
hickory-resolver = "0.26"
|
|
32
|
+
|
|
33
|
+
# Parallelism & Performance
|
|
34
|
+
rayon = "1.10"
|
|
35
|
+
memmap2 = "0.9"
|
|
36
|
+
|
|
37
|
+
# Serialization & Formats
|
|
38
|
+
serde = { version = "1.0", features = ["derive"] }
|
|
39
|
+
serde_json = "1.0"
|
|
40
|
+
toml = "1.1"
|
|
41
|
+
|
|
42
|
+
# Terminal Formatting
|
|
43
|
+
colored = "3.0"
|
|
44
|
+
comfy-table = { version = "7.1", features = ["custom_styling"] }
|
|
45
|
+
|
|
46
|
+
# Pattern Matching & Graph
|
|
47
|
+
regex = "1.11"
|
|
48
|
+
glob = "0.3"
|
|
49
|
+
walkdir = "2.5"
|
|
50
|
+
ipnet = "2.12"
|
|
51
|
+
sha2 = "0.10"
|
|
52
|
+
hex = "0.4"
|
|
53
|
+
chrono = { version = "0.4", features = ["serde"] }
|
|
54
|
+
|
|
55
|
+
# OXC AST Parser for JS/TS
|
|
56
|
+
oxc_allocator = "0.146.0"
|
|
57
|
+
oxc_ast = "0.146.0"
|
|
58
|
+
oxc_parser = "0.146.0"
|
|
59
|
+
oxc_span = "0.146.0"
|
|
60
|
+
|
|
61
|
+
# Error Handling
|
|
62
|
+
thiserror = "2.0"
|
|
63
|
+
anyhow = "1.0"
|
|
64
|
+
|
|
65
|
+
[dev-dependencies]
|
|
66
|
+
tempfile = "3.17"
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Brandon Hubbard
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# 🛡️ Flareguard
|
|
2
|
+
|
|
3
|
+
> **The Unified Cloudflare Security & Architecture Guardian**
|
|
4
|
+
> High-performance Rust CLI & library providing AST secret scanning, Worker binding verification, Zone security posture auditing, and origin IP leak hunting.
|
|
5
|
+
|
|
6
|
+
[](https://github.com/bhubbard/flareguard/actions)
|
|
7
|
+
[](https://crates.io/crates/flareguard)
|
|
8
|
+
[](https://www.npmjs.com/package/flareguard)
|
|
9
|
+
[](LICENSE)
|
|
10
|
+
[](https://bhubbard.github.io/flareguard)
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## ⚡ The 4 Pillars of Flareguard
|
|
15
|
+
|
|
16
|
+
| Pillar | Subcommand | Description |
|
|
17
|
+
|---|---|---|
|
|
18
|
+
| **🔑 Secrets** | `flareguard secrets` | High-throughput multithreaded scanner preventing Cloudflare API tokens, Global Keys, and Turnstile secrets from leaking into client bundles or git history. |
|
|
19
|
+
| **⚡ Bindings** | `flareguard bindings` | OXC JavaScript/TypeScript AST scanner that cross-references `wrangler.toml` / `wrangler.jsonc` declarations against actual code usage (D1, KV, R2, Vectorize, Hyperdrive, AI). |
|
|
20
|
+
| **🌐 Zone Audit** | `flareguard zone` | Comprehensive live security posture auditor for Cloudflare zones (SSL/TLS Strict, HSTS, WAF Managed Rules, Bot Fight Mode, DNSSEC, security headers). |
|
|
21
|
+
| **🎯 Origin Hunter** | `flareguard origin` | Probes and discovers unmasked backend origin IPs behind Cloudflare reverse proxies using DNS SPF/MX records, CRT.sh Certificate Transparency logs, and active HTTP signatures. |
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
## 🔑 Supported Secret Detection Rules (15 Built-in Rules)
|
|
27
|
+
|
|
28
|
+
| Rule ID | Name | Severity | Description |
|
|
29
|
+
|---|---|---|---|
|
|
30
|
+
| **CF-001** | Cloudflare API Token | `CRITICAL` | Scoped API token (40 characters) |
|
|
31
|
+
| **CF-002** | Cloudflare Global API Key | `CRITICAL` | Legacy global account key (37-hex characters) |
|
|
32
|
+
| **CF-003** | Cloudflare Origin CA Key | `CRITICAL` | Origin certificate creation key (`v1.0-` prefix) |
|
|
33
|
+
| **CF-004** | Cloudflare Turnstile Secret Key | `CRITICAL` | Server-side verification secret (`0x4AAAA...`) |
|
|
34
|
+
| **CF-005** | Zero Trust Access Service Token | `CRITICAL` | Service token secret for Zero Trust policies |
|
|
35
|
+
| **CF-006** | Cloudflare Account ID Context | `MEDIUM` | Account ID assigned in sensitive config contexts |
|
|
36
|
+
| **CF-007** | R2 / S3 Secret Access Key | `CRITICAL` | Object storage secret key (40 characters) |
|
|
37
|
+
| **CF-008** | Database URI / D1 Secret | `CRITICAL` | Embedded Postgres/MySQL connection string or D1 token |
|
|
38
|
+
| **CF-009** | Standalone High-Entropy Token | `HIGH` | High Shannon-entropy token matching Cloudflare signatures |
|
|
39
|
+
| **CF-010** | Hyperdrive Origin Secret | `CRITICAL` | Database credentials or pooling passwords |
|
|
40
|
+
| **CF-011** | Cloudflare Tunnel Token | `CRITICAL` | `cloudflared` ingress tunnel credentials (`eyJh...`) |
|
|
41
|
+
| **CF-012** | AI Gateway & LLM API Key | `CRITICAL` | AI Gateway token, OpenAI (`sk-proj`), Anthropic (`sk-ant`), Gemini (`AIzaSy`) |
|
|
42
|
+
| **CF-013** | Vectorize Admin Secret | `CRITICAL` | Vector database index management key |
|
|
43
|
+
| **CF-014** | Email / MailChannels Secret | `HIGH` | DKIM / transactional mail dispatch credentials |
|
|
44
|
+
| **CF-015** | SSL/TLS Private Key | `CRITICAL` | Unencrypted RSA/EC private key (`BEGIN PRIVATE KEY`) |
|
|
45
|
+
|
|
46
|
+
## 🚀 Installation & Quickstart
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# Install via Cargo (Rust)
|
|
50
|
+
cargo install flareguard
|
|
51
|
+
|
|
52
|
+
# Or install globally via npm
|
|
53
|
+
npm install -g flareguard
|
|
54
|
+
|
|
55
|
+
# Or run directly via npx without installation
|
|
56
|
+
npx flareguard --help
|
|
57
|
+
|
|
58
|
+
# Or build from source
|
|
59
|
+
git clone https://github.com/bhubbard/flareguard.git
|
|
60
|
+
cd flareguard
|
|
61
|
+
cargo build --release
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### 1. Scan for Leaked Cloudflare Secrets
|
|
65
|
+
```bash
|
|
66
|
+
# Scan static build directory (e.g. dist, public)
|
|
67
|
+
flareguard secrets dist/
|
|
68
|
+
|
|
69
|
+
# Run in CI mode (fails with exit code 1 on leaks)
|
|
70
|
+
flareguard secrets dist/ --check --format sarif --output results.sarif
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### 2. Validate Worker / Pages Bindings
|
|
74
|
+
```bash
|
|
75
|
+
# Validate wrangler.jsonc or wrangler.toml against src/ AST usage
|
|
76
|
+
flareguard bindings src/ --config wrangler.jsonc --strict
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### 3. Audit Cloudflare Zone Security
|
|
80
|
+
```bash
|
|
81
|
+
# Live zone audit via API Token
|
|
82
|
+
flareguard zone --token $CF_API_TOKEN --zone example.com --check
|
|
83
|
+
|
|
84
|
+
# Offline mock audit
|
|
85
|
+
flareguard zone --mock
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### 4. Hunt for Unmasked Origin IPs
|
|
89
|
+
```bash
|
|
90
|
+
# Scan domain for direct-to-origin leak vectors
|
|
91
|
+
flareguard origin example.com --check
|
|
92
|
+
|
|
93
|
+
# Offline mock scan
|
|
94
|
+
flareguard origin --mock
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### 5. End-to-End Workspace Check
|
|
98
|
+
```bash
|
|
99
|
+
# Run all local security checks across repository
|
|
100
|
+
flareguard check .
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## 📜 Architecture & Core Principles
|
|
106
|
+
|
|
107
|
+
- **Zero-Latency Parallelism:** Rayon-powered parallel directory traversal and memory-mapped file inspection (`memmap2`).
|
|
108
|
+
- **Precision AST Analysis:** Powered by **OXC** (Oxford JavaScript Compiler in Rust) for nanosecond JS/TS parsing without runtime node/v8 dependencies.
|
|
109
|
+
- **Actionable Remediation:** Every finding includes clear, copy-paste shell commands and Cloudflare dashboard remediation instructions.
|
|
110
|
+
- **Enterprise CI/CD Integration:** Direct SARIF output for GitHub Actions Code Scanning and customizable compliance gates.
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## 📄 License
|
|
115
|
+
MIT © 2026 Brandon Hubbard ([brandonhubbard.com](https://brandonhubbard.com))
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawnSync } from "node:child_process";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import { createRequire } from "node:module";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import process from "node:process";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
|
|
9
|
+
const require = createRequire(import.meta.url);
|
|
10
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
11
|
+
const root = path.resolve(__dirname, "..");
|
|
12
|
+
const exe = process.platform === "win32" ? "flareguard.exe" : "flareguard";
|
|
13
|
+
|
|
14
|
+
const PLATFORM_PACKAGES = {
|
|
15
|
+
"darwin-arm64": "@flareguard/darwin-arm64",
|
|
16
|
+
"darwin-x64": "@flareguard/darwin-x64",
|
|
17
|
+
"linux-x64": "@flareguard/linux-x64",
|
|
18
|
+
"linux-arm64": "@flareguard/linux-arm64",
|
|
19
|
+
"win32-x64": "@flareguard/win32-x64",
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export function getBinaryPath() {
|
|
23
|
+
if (process.env.FLAREGUARD_BIN && fs.existsSync(process.env.FLAREGUARD_BIN)) {
|
|
24
|
+
return process.env.FLAREGUARD_BIN;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// 1. Check if optional platform-specific package is installed
|
|
28
|
+
const platformKey = `${process.platform}-${process.arch}`;
|
|
29
|
+
const pkgName = PLATFORM_PACKAGES[platformKey];
|
|
30
|
+
if (pkgName) {
|
|
31
|
+
try {
|
|
32
|
+
const resolved = require.resolve(`${pkgName}/bin/${exe}`);
|
|
33
|
+
if (fs.existsSync(resolved)) {
|
|
34
|
+
return resolved;
|
|
35
|
+
}
|
|
36
|
+
} catch {
|
|
37
|
+
// Platform package not present; fall through
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// 2. Check local builds or vendored binary locations
|
|
42
|
+
const candidates = [
|
|
43
|
+
path.resolve(root, "dist/bin", exe),
|
|
44
|
+
path.resolve(root, "target/release", exe),
|
|
45
|
+
path.resolve(root, "target/debug", exe),
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
for (const candidate of candidates) {
|
|
49
|
+
if (fs.existsSync(candidate)) {
|
|
50
|
+
if (process.platform !== "win32") {
|
|
51
|
+
try {
|
|
52
|
+
const mode = fs.statSync(candidate).mode;
|
|
53
|
+
if ((mode & 0o111) === 0) {
|
|
54
|
+
fs.chmodSync(candidate, 0o755);
|
|
55
|
+
}
|
|
56
|
+
} catch {
|
|
57
|
+
// Ignore
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return candidate;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return exe;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const bin = getBinaryPath();
|
|
68
|
+
const res = spawnSync(bin, process.argv.slice(2), { stdio: "inherit" });
|
|
69
|
+
if (res.error) {
|
|
70
|
+
if (res.error.code === "ENOENT") {
|
|
71
|
+
console.error(`[flareguard] Could not find native binary '${bin}'.`);
|
|
72
|
+
console.error("Please run `cargo build --release` or install flareguard via Cargo or prebuilt npm platform package.");
|
|
73
|
+
} else {
|
|
74
|
+
console.error(`[flareguard] Execution error: ${res.error.message}`);
|
|
75
|
+
}
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
process.exit(res.status ?? 0);
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "flareguard",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Unified Cloudflare Security Guardian — AST secret scanning, Worker binding verification, Zone posture auditing, and origin IP leak hunting.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"cloudflare",
|
|
7
|
+
"security",
|
|
8
|
+
"waf",
|
|
9
|
+
"workers",
|
|
10
|
+
"cli",
|
|
11
|
+
"secrets",
|
|
12
|
+
"audit"
|
|
13
|
+
],
|
|
14
|
+
"homepage": "https://bhubbard.github.io/flareguard",
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/bhubbard/flareguard/issues"
|
|
17
|
+
},
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"author": "Brandon Hubbard <bkhubbard@gmail.com>",
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/bhubbard/flareguard.git"
|
|
23
|
+
},
|
|
24
|
+
"bin": {
|
|
25
|
+
"flareguard": "bin/flareguard.js"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"bin",
|
|
29
|
+
"scripts/postinstall.mjs",
|
|
30
|
+
"Cargo.toml",
|
|
31
|
+
"Cargo.lock",
|
|
32
|
+
"src",
|
|
33
|
+
"README.md",
|
|
34
|
+
"LICENSE"
|
|
35
|
+
],
|
|
36
|
+
"type": "module",
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build:cargo": "cargo build --release",
|
|
39
|
+
"postinstall": "node scripts/postinstall.mjs",
|
|
40
|
+
"prepare:publish": "node scripts/set-optional-deps.mjs",
|
|
41
|
+
"test": "cargo test"
|
|
42
|
+
},
|
|
43
|
+
"engines": {
|
|
44
|
+
"node": ">=18.0.0"
|
|
45
|
+
},
|
|
46
|
+
"//optionalDependencies": [
|
|
47
|
+
"The @flareguard/* prebuilt-binary packages are attached at publish",
|
|
48
|
+
"time by scripts/set-optional-deps.mjs, not committed here."
|
|
49
|
+
]
|
|
50
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawnSync } from "node:child_process";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import { createRequire } from "node:module";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import process from "node:process";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
|
|
9
|
+
const require = createRequire(import.meta.url);
|
|
10
|
+
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
11
|
+
const exe = process.platform === "win32" ? "flareguard.exe" : "flareguard";
|
|
12
|
+
|
|
13
|
+
const PLATFORM_PACKAGES = {
|
|
14
|
+
"darwin-arm64": "@flareguard/darwin-arm64",
|
|
15
|
+
"darwin-x64": "@flareguard/darwin-x64",
|
|
16
|
+
"linux-x64": "@flareguard/linux-x64",
|
|
17
|
+
"linux-arm64": "@flareguard/linux-arm64",
|
|
18
|
+
"win32-x64": "@flareguard/win32-x64",
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
function log(message) {
|
|
22
|
+
console.log(`[flareguard] ${message}`);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function runnable(file) {
|
|
26
|
+
if (!fs.existsSync(file)) return false;
|
|
27
|
+
const res = spawnSync(file, ["--version"], { stdio: "ignore", timeout: 10_000 });
|
|
28
|
+
return !res.error && res.status === 0;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function alreadyPresent() {
|
|
32
|
+
const pkg = PLATFORM_PACKAGES[`${process.platform}-${process.arch}`];
|
|
33
|
+
if (pkg) {
|
|
34
|
+
try {
|
|
35
|
+
if (runnable(require.resolve(`${pkg}/bin/${exe}`))) return true;
|
|
36
|
+
} catch {
|
|
37
|
+
// Not installed; keep looking
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return ["dist/bin", "target/release"].some((dir) => runnable(path.join(root, dir, exe)));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function hasCargo() {
|
|
45
|
+
const res = spawnSync("cargo", ["--version"], { stdio: "ignore" });
|
|
46
|
+
return res.status === 0;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function main() {
|
|
50
|
+
if (alreadyPresent()) return;
|
|
51
|
+
|
|
52
|
+
if (!hasCargo()) {
|
|
53
|
+
log(
|
|
54
|
+
`No prebuilt binary found for ${process.platform}-${process.arch} and cargo is not installed.\n` +
|
|
55
|
+
` To build from source, install Rust (https://rustup.rs) and run \`cargo build --release\`,\n` +
|
|
56
|
+
` or set FLAREGUARD_BIN to an existing flareguard binary.`,
|
|
57
|
+
);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
log("No prebuilt binary for this platform — compiling with cargo...");
|
|
62
|
+
const res = spawnSync("cargo", ["build", "--release"], { cwd: root, stdio: "inherit" });
|
|
63
|
+
|
|
64
|
+
if (res.status !== 0) {
|
|
65
|
+
log("cargo build failed. Run `cargo build --release` manually to see the error.");
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const built = path.join(root, "target", "release", exe);
|
|
70
|
+
const destDir = path.join(root, "dist", "bin");
|
|
71
|
+
if (fs.existsSync(built)) {
|
|
72
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
73
|
+
fs.copyFileSync(built, path.join(destDir, exe));
|
|
74
|
+
if (process.platform !== "win32") fs.chmodSync(path.join(destDir, exe), 0o755);
|
|
75
|
+
log("Engine built successfully.");
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
try {
|
|
80
|
+
main();
|
|
81
|
+
} catch (err) {
|
|
82
|
+
log(`Postinstall skipped: ${err.message}`);
|
|
83
|
+
}
|