@aion0/bastion 0.1.11 → 0.1.13
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/README.md +49 -6
- package/README.zh.md +48 -22
- package/config/default.yaml +2 -2
- package/dist/cli/commands/plugins.d.ts +3 -0
- package/dist/cli/commands/plugins.d.ts.map +1 -0
- package/dist/cli/commands/plugins.js +201 -0
- package/dist/cli/commands/plugins.js.map +1 -0
- package/dist/cli/commands/start.d.ts.map +1 -1
- package/dist/cli/commands/start.js +0 -18
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/cli/index.js +2 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/config/paths.d.ts +2 -0
- package/dist/config/paths.d.ts.map +1 -1
- package/dist/config/paths.js +2 -0
- package/dist/config/paths.js.map +1 -1
- package/dist/config/schema.d.ts +29 -1
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/core/bootstrap.d.ts.map +1 -1
- package/dist/core/bootstrap.js +10 -0
- package/dist/core/bootstrap.js.map +1 -1
- package/dist/dashboard/api-routes.d.ts.map +1 -1
- package/dist/dashboard/api-routes.js +114 -50
- package/dist/dashboard/api-routes.js.map +1 -1
- package/dist/dashboard/page.d.ts.map +1 -1
- package/dist/dashboard/page.js +132 -69
- package/dist/dashboard/page.js.map +1 -1
- package/dist/dlp/ai-validator.d.ts +5 -2
- package/dist/dlp/ai-validator.d.ts.map +1 -1
- package/dist/dlp/ai-validator.js +20 -2
- package/dist/dlp/ai-validator.js.map +1 -1
- package/dist/dlp/heuristic-validator.d.ts +24 -0
- package/dist/dlp/heuristic-validator.d.ts.map +1 -0
- package/dist/dlp/heuristic-validator.js +97 -0
- package/dist/dlp/heuristic-validator.js.map +1 -0
- package/dist/plugin-api/index.d.ts +1 -1
- package/dist/plugin-api/index.d.ts.map +1 -1
- package/dist/plugin-api/index.js.map +1 -1
- package/dist/plugin-api/types.d.ts +19 -0
- package/dist/plugin-api/types.d.ts.map +1 -1
- package/dist/plugins/builtin/audit-logger.js +1 -1
- package/dist/plugins/builtin/dlp-scanner.d.ts +2 -0
- package/dist/plugins/builtin/dlp-scanner.d.ts.map +1 -1
- package/dist/plugins/builtin/dlp-scanner.js +9 -3
- package/dist/plugins/builtin/dlp-scanner.js.map +1 -1
- package/dist/plugins/builtin/metrics-collector.js +1 -1
- package/dist/plugins/builtin/metrics-collector.js.map +1 -1
- package/dist/plugins/builtin/threat-scorer.d.ts +6 -0
- package/dist/plugins/builtin/threat-scorer.d.ts.map +1 -0
- package/dist/plugins/builtin/threat-scorer.js +266 -0
- package/dist/plugins/builtin/threat-scorer.js.map +1 -0
- package/dist/plugins/builtin/token-optimizer.js +1 -1
- package/dist/plugins/builtin/tool-guard.d.ts.map +1 -1
- package/dist/plugins/builtin/tool-guard.js +18 -5
- package/dist/plugins/builtin/tool-guard.js.map +1 -1
- package/dist/plugins/loader.d.ts.map +1 -1
- package/dist/plugins/loader.js +22 -5
- package/dist/plugins/loader.js.map +1 -1
- package/dist/plugins/types.d.ts +3 -0
- package/dist/plugins/types.d.ts.map +1 -1
- package/dist/storage/migrations.d.ts.map +1 -1
- package/dist/storage/migrations.js +43 -0
- package/dist/storage/migrations.js.map +1 -1
- package/dist/storage/repositories/taint-marks.d.ts +26 -0
- package/dist/storage/repositories/taint-marks.d.ts.map +1 -0
- package/dist/storage/repositories/taint-marks.js +27 -0
- package/dist/storage/repositories/taint-marks.js.map +1 -0
- package/dist/storage/repositories/threat-score-events.d.ts +27 -0
- package/dist/storage/repositories/threat-score-events.d.ts.map +1 -0
- package/dist/storage/repositories/threat-score-events.js +24 -0
- package/dist/storage/repositories/threat-score-events.js.map +1 -0
- package/dist/storage/repositories/threat-scores.d.ts +26 -0
- package/dist/storage/repositories/threat-scores.d.ts.map +1 -0
- package/dist/storage/repositories/threat-scores.js +42 -0
- package/dist/storage/repositories/threat-scores.js.map +1 -0
- package/dist/storage/repositories/tool-chain-detections.d.ts +24 -0
- package/dist/storage/repositories/tool-chain-detections.d.ts.map +1 -0
- package/dist/storage/repositories/tool-chain-detections.js +27 -0
- package/dist/storage/repositories/tool-chain-detections.js.map +1 -0
- package/dist/tool-guard/chain-detector.d.ts +18 -0
- package/dist/tool-guard/chain-detector.d.ts.map +1 -0
- package/dist/tool-guard/chain-detector.js +55 -0
- package/dist/tool-guard/chain-detector.js.map +1 -0
- package/dist/tool-guard/chain-rules.d.ts +10 -0
- package/dist/tool-guard/chain-rules.d.ts.map +1 -0
- package/dist/tool-guard/chain-rules.js +30 -0
- package/dist/tool-guard/chain-rules.js.map +1 -0
- package/dist/tool-guard/taint-tracker.d.ts +24 -0
- package/dist/tool-guard/taint-tracker.d.ts.map +1 -0
- package/dist/tool-guard/taint-tracker.js +70 -0
- package/dist/tool-guard/taint-tracker.js.map +1 -0
- package/integration/openclaw-docker/fix-issues/not-install-brew/Dockerfile.patch +31 -0
- package/integration/openclaw-docker/fix-issues/not-install-brew/docker-setup.sh.patch +33 -0
- package/package.json +1 -1
- package/dist/license/verify.d.ts +0 -18
- package/dist/license/verify.d.ts.map +0 -1
- package/dist/license/verify.js +0 -71
- package/dist/license/verify.js.map +0 -1
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.TaintTracker = void 0;
|
|
7
|
+
const node_crypto_1 = __importDefault(require("node:crypto"));
|
|
8
|
+
class TaintTracker {
|
|
9
|
+
sessionTaints = new Map();
|
|
10
|
+
ttlMs;
|
|
11
|
+
constructor(ttlMinutes = 60) {
|
|
12
|
+
this.ttlMs = ttlMinutes * 60 * 1000;
|
|
13
|
+
}
|
|
14
|
+
/** Create a fingerprint from matched content: SHA256 first 16 hex chars */
|
|
15
|
+
static fingerprint(content) {
|
|
16
|
+
return node_crypto_1.default.createHash('sha256').update(content).digest('hex').slice(0, 16);
|
|
17
|
+
}
|
|
18
|
+
markTaint(sessionId, requestId, patternName, matchedContent) {
|
|
19
|
+
const fingerprint = TaintTracker.fingerprint(matchedContent);
|
|
20
|
+
let taints = this.sessionTaints.get(sessionId);
|
|
21
|
+
if (!taints) {
|
|
22
|
+
taints = [];
|
|
23
|
+
this.sessionTaints.set(sessionId, taints);
|
|
24
|
+
}
|
|
25
|
+
taints.push({
|
|
26
|
+
sessionId,
|
|
27
|
+
requestId,
|
|
28
|
+
patternName,
|
|
29
|
+
fingerprint,
|
|
30
|
+
timestamp: Date.now(),
|
|
31
|
+
});
|
|
32
|
+
return fingerprint;
|
|
33
|
+
}
|
|
34
|
+
/** Check if tool input contains any tainted content fingerprints */
|
|
35
|
+
checkToolInput(sessionId, toolInput) {
|
|
36
|
+
const taints = this.getActiveTaints(sessionId);
|
|
37
|
+
if (taints.length === 0)
|
|
38
|
+
return null;
|
|
39
|
+
// Generate sliding-window fingerprints from tool input and check against taints
|
|
40
|
+
// For efficiency, we check if any taint fingerprint appears as a substring hash
|
|
41
|
+
for (const taint of taints) {
|
|
42
|
+
// Check if the fingerprinted content appears in tool input by re-hashing substrings
|
|
43
|
+
// This is a simplified approach: we hash various substrings of the input
|
|
44
|
+
// For practical use, we check if the original matched content reappears
|
|
45
|
+
// by comparing fingerprints of input chunks
|
|
46
|
+
const inputFingerprint = TaintTracker.fingerprint(toolInput);
|
|
47
|
+
if (inputFingerprint === taint.fingerprint) {
|
|
48
|
+
return { patternName: taint.patternName, fingerprint: taint.fingerprint };
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
getActiveTaints(sessionId) {
|
|
54
|
+
const taints = this.sessionTaints.get(sessionId);
|
|
55
|
+
if (!taints)
|
|
56
|
+
return [];
|
|
57
|
+
const cutoff = Date.now() - this.ttlMs;
|
|
58
|
+
// Remove expired taints
|
|
59
|
+
const active = taints.filter(t => t.timestamp > cutoff);
|
|
60
|
+
if (active.length !== taints.length) {
|
|
61
|
+
this.sessionTaints.set(sessionId, active);
|
|
62
|
+
}
|
|
63
|
+
return active;
|
|
64
|
+
}
|
|
65
|
+
cleanup(sessionId) {
|
|
66
|
+
this.sessionTaints.delete(sessionId);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
exports.TaintTracker = TaintTracker;
|
|
70
|
+
//# sourceMappingURL=taint-tracker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"taint-tracker.js","sourceRoot":"","sources":["../../src/tool-guard/taint-tracker.ts"],"names":[],"mappings":";;;;;;AAAA,8DAAiC;AAejC,MAAa,YAAY;IACf,aAAa,GAAG,IAAI,GAAG,EAAuB,CAAC;IAC/C,KAAK,CAAS;IAEtB,YAAY,aAAqB,EAAE;QACjC,IAAI,CAAC,KAAK,GAAG,UAAU,GAAG,EAAE,GAAG,IAAI,CAAC;IACtC,CAAC;IAED,2EAA2E;IAC3E,MAAM,CAAC,WAAW,CAAC,OAAe;QAChC,OAAO,qBAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAChF,CAAC;IAED,SAAS,CAAC,SAAiB,EAAE,SAAiB,EAAE,WAAmB,EAAE,cAAsB;QACzF,MAAM,WAAW,GAAG,YAAY,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC;QAC7D,IAAI,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC/C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,GAAG,EAAE,CAAC;YACZ,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QAC5C,CAAC;QACD,MAAM,CAAC,IAAI,CAAC;YACV,SAAS;YACT,SAAS;YACT,WAAW;YACX,WAAW;YACX,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,CAAC,CAAC;QACH,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,oEAAoE;IACpE,cAAc,CAAC,SAAiB,EAAE,SAAiB;QACjD,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;QAC/C,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QAErC,gFAAgF;QAChF,gFAAgF;QAChF,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,oFAAoF;YACpF,yEAAyE;YACzE,wEAAwE;YACxE,4CAA4C;YAC5C,MAAM,gBAAgB,GAAG,YAAY,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;YAC7D,IAAI,gBAAgB,KAAK,KAAK,CAAC,WAAW,EAAE,CAAC;gBAC3C,OAAO,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC;YAC5E,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED,eAAe,CAAC,SAAiB;QAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACjD,IAAI,CAAC,MAAM;YAAE,OAAO,EAAE,CAAC;QAEvB,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC;QACvC,wBAAwB;QACxB,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,MAAM,CAAC,CAAC;QACxD,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC;YACpC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QAC5C,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,OAAO,CAAC,SAAiB;QACvB,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACvC,CAAC;CACF;AAnED,oCAmEC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
--- Dockerfile.upstream 2026-03-02 00:45:51
|
|
2
|
+
+++ Dockerfile 2026-03-02 00:11:32
|
|
3
|
+
@@ -89,6 +89,28 @@
|
|
4
|
+
rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*; \
|
|
5
|
+
fi
|
|
6
|
+
|
|
7
|
+
+# Optional: Install Linuxbrew for skill dependency management.
|
|
8
|
+
+# Build with: docker build --build-arg OPENCLAW_INSTALL_BREW=1 ...
|
|
9
|
+
+# Adds ~500MB but enables brew-based skill installation (uv, go, signal-cli, etc.)
|
|
10
|
+
+ARG OPENCLAW_INSTALL_BREW=""
|
|
11
|
+
+RUN if [ -n "$OPENCLAW_INSTALL_BREW" ]; then \
|
|
12
|
+
+ apt-get update && \
|
|
13
|
+
+ DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends build-essential curl file git procps && \
|
|
14
|
+
+ if ! id -u linuxbrew >/dev/null 2>&1; then useradd -m -s /bin/bash linuxbrew; fi && \
|
|
15
|
+
+ mkdir -p /home/linuxbrew/.linuxbrew && \
|
|
16
|
+
+ chown -R linuxbrew:linuxbrew /home/linuxbrew && \
|
|
17
|
+
+ su - linuxbrew -c "NONINTERACTIVE=1 CI=1 /bin/bash -c '$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)'" && \
|
|
18
|
+
+ if [ ! -e /home/linuxbrew/.linuxbrew/Library ]; then ln -s /home/linuxbrew/.linuxbrew/Homebrew/Library /home/linuxbrew/.linuxbrew/Library; fi && \
|
|
19
|
+
+ if [ ! -x /home/linuxbrew/.linuxbrew/bin/brew ]; then echo "brew install failed"; exit 1; fi && \
|
|
20
|
+
+ chown -R node:node /home/linuxbrew/.linuxbrew && \
|
|
21
|
+
+ apt-get clean && \
|
|
22
|
+
+ rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*; \
|
|
23
|
+
+ fi
|
|
24
|
+
+ENV HOMEBREW_PREFIX=/home/linuxbrew/.linuxbrew
|
|
25
|
+
+ENV HOMEBREW_CELLAR=/home/linuxbrew/.linuxbrew/Cellar
|
|
26
|
+
+ENV HOMEBREW_REPOSITORY=/home/linuxbrew/.linuxbrew/Homebrew
|
|
27
|
+
+ENV PATH="/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin:${PATH}"
|
|
28
|
+
+
|
|
29
|
+
USER node
|
|
30
|
+
COPY --chown=node:node . .
|
|
31
|
+
# Normalize copied plugin/agent paths so plugin safety checks do not reject
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
--- docker-setup.sh.upstream 2026-03-02 00:47:22
|
|
2
|
+
+++ docker-setup.sh 2026-03-02 00:31:55
|
|
3
|
+
@@ -200,6 +200,7 @@
|
|
4
|
+
export OPENCLAW_GATEWAY_BIND="${OPENCLAW_GATEWAY_BIND:-lan}"
|
|
5
|
+
export OPENCLAW_IMAGE="$IMAGE_NAME"
|
|
6
|
+
export OPENCLAW_DOCKER_APT_PACKAGES="${OPENCLAW_DOCKER_APT_PACKAGES:-}"
|
|
7
|
+
+export OPENCLAW_INSTALL_BREW="${OPENCLAW_INSTALL_BREW:-}"
|
|
8
|
+
export OPENCLAW_EXTRA_MOUNTS="$EXTRA_MOUNTS"
|
|
9
|
+
export OPENCLAW_HOME_VOLUME="$HOME_VOLUME_NAME"
|
|
10
|
+
export OPENCLAW_ALLOW_INSECURE_PRIVATE_WS="${OPENCLAW_ALLOW_INSECURE_PRIVATE_WS:-}"
|
|
11
|
+
@@ -382,13 +383,20 @@
|
|
12
|
+
OPENCLAW_DOCKER_SOCKET \
|
|
13
|
+
DOCKER_GID \
|
|
14
|
+
OPENCLAW_INSTALL_DOCKER_CLI \
|
|
15
|
+
- OPENCLAW_ALLOW_INSECURE_PRIVATE_WS
|
|
16
|
+
+ OPENCLAW_ALLOW_INSECURE_PRIVATE_WS \
|
|
17
|
+
+ OPENCLAW_INSTALL_BREW
|
|
18
|
+
|
|
19
|
+
-if [[ "$IMAGE_NAME" == "openclaw:local" ]]; then
|
|
20
|
+
+if [[ -n "${OPENCLAW_SKIP_BUILD:-}" ]]; then
|
|
21
|
+
+ echo "==> Skipping image build/pull (OPENCLAW_SKIP_BUILD is set)"
|
|
22
|
+
+ if ! docker image inspect "$IMAGE_NAME" >/dev/null 2>&1; then
|
|
23
|
+
+ fail "Image '$IMAGE_NAME' not found locally. Run 'bastion openclaw build' first."
|
|
24
|
+
+ fi
|
|
25
|
+
+elif [[ "$IMAGE_NAME" == "openclaw:local" ]]; then
|
|
26
|
+
echo "==> Building Docker image: $IMAGE_NAME"
|
|
27
|
+
docker build \
|
|
28
|
+
--build-arg "OPENCLAW_DOCKER_APT_PACKAGES=${OPENCLAW_DOCKER_APT_PACKAGES}" \
|
|
29
|
+
--build-arg "OPENCLAW_INSTALL_DOCKER_CLI=${OPENCLAW_INSTALL_DOCKER_CLI:-}" \
|
|
30
|
+
+ --build-arg "OPENCLAW_INSTALL_BREW=${OPENCLAW_INSTALL_BREW}" \
|
|
31
|
+
-t "$IMAGE_NAME" \
|
|
32
|
+
-f "$ROOT_DIR/Dockerfile" \
|
|
33
|
+
"$ROOT_DIR"
|
package/package.json
CHANGED
package/dist/license/verify.d.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
export interface LicensePayload {
|
|
2
|
-
plan: string;
|
|
3
|
-
expiresAt: string;
|
|
4
|
-
features: string[];
|
|
5
|
-
}
|
|
6
|
-
export interface LicenseResult {
|
|
7
|
-
valid: boolean;
|
|
8
|
-
payload?: LicensePayload;
|
|
9
|
-
reason?: string;
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Verify a signed license token.
|
|
13
|
-
*
|
|
14
|
-
* Returns { valid: true, payload } on success,
|
|
15
|
-
* or { valid: false, reason } on failure.
|
|
16
|
-
*/
|
|
17
|
-
export declare function verifyLicenseToken(token: unknown): LicenseResult;
|
|
18
|
-
//# sourceMappingURL=verify.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/license/verify.ts"],"names":[],"mappings":"AAiBA,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,aAAa,CAmDhE"}
|
package/dist/license/verify.js
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.verifyLicenseToken = verifyLicenseToken;
|
|
7
|
-
const node_crypto_1 = __importDefault(require("node:crypto"));
|
|
8
|
-
/**
|
|
9
|
-
* Bastion Pro license verification.
|
|
10
|
-
*
|
|
11
|
-
* License token format: base64(JSON payload) + '.' + base64(Ed25519 signature)
|
|
12
|
-
*
|
|
13
|
-
* The Pro plugin sets a signed token; we verify it here with the embedded
|
|
14
|
-
* public key so a forged plugin cannot simply claim `valid: true`.
|
|
15
|
-
*/
|
|
16
|
-
// Ed25519 public key (PEM) — only Bastion can sign with the corresponding private key.
|
|
17
|
-
// Replace this with the real production key before shipping.
|
|
18
|
-
const LICENSE_PUBLIC_KEY = `-----BEGIN PUBLIC KEY-----
|
|
19
|
-
MCowBQYDK2VwAyEAPlr2YjKxlMzVGOZ2WFmYOFCT3JHaFz8rECPFwbzVSXg=
|
|
20
|
-
-----END PUBLIC KEY-----`;
|
|
21
|
-
/**
|
|
22
|
-
* Verify a signed license token.
|
|
23
|
-
*
|
|
24
|
-
* Returns { valid: true, payload } on success,
|
|
25
|
-
* or { valid: false, reason } on failure.
|
|
26
|
-
*/
|
|
27
|
-
function verifyLicenseToken(token) {
|
|
28
|
-
if (typeof token !== 'string' || !token.includes('.')) {
|
|
29
|
-
return { valid: false, reason: 'malformed token' };
|
|
30
|
-
}
|
|
31
|
-
const dotIndex = token.lastIndexOf('.');
|
|
32
|
-
const payloadB64 = token.slice(0, dotIndex);
|
|
33
|
-
const signatureB64 = token.slice(dotIndex + 1);
|
|
34
|
-
// Verify signature
|
|
35
|
-
let signatureValid;
|
|
36
|
-
try {
|
|
37
|
-
const key = node_crypto_1.default.createPublicKey(LICENSE_PUBLIC_KEY);
|
|
38
|
-
signatureValid = node_crypto_1.default.verify(null, // Ed25519 does not use a separate hash algorithm
|
|
39
|
-
Buffer.from(payloadB64, 'base64'), key, Buffer.from(signatureB64, 'base64'));
|
|
40
|
-
}
|
|
41
|
-
catch {
|
|
42
|
-
return { valid: false, reason: 'signature verification error' };
|
|
43
|
-
}
|
|
44
|
-
if (!signatureValid) {
|
|
45
|
-
return { valid: false, reason: 'invalid signature' };
|
|
46
|
-
}
|
|
47
|
-
// Decode payload
|
|
48
|
-
let payload;
|
|
49
|
-
try {
|
|
50
|
-
payload = JSON.parse(Buffer.from(payloadB64, 'base64').toString('utf-8'));
|
|
51
|
-
}
|
|
52
|
-
catch {
|
|
53
|
-
return { valid: false, reason: 'invalid payload' };
|
|
54
|
-
}
|
|
55
|
-
// Check expiry
|
|
56
|
-
if (typeof payload.expiresAt === 'string') {
|
|
57
|
-
const exp = new Date(payload.expiresAt);
|
|
58
|
-
if (exp.getTime() < Date.now()) {
|
|
59
|
-
return { valid: false, reason: 'license expired' };
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
return {
|
|
63
|
-
valid: true,
|
|
64
|
-
payload: {
|
|
65
|
-
plan: payload.plan ?? 'pro',
|
|
66
|
-
expiresAt: payload.expiresAt ?? '',
|
|
67
|
-
features: payload.features ?? [],
|
|
68
|
-
},
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
//# sourceMappingURL=verify.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/license/verify.ts"],"names":[],"mappings":";;;;;AAmCA,gDAmDC;AAtFD,8DAAiC;AAEjC;;;;;;;GAOG;AAEH,uFAAuF;AACvF,6DAA6D;AAC7D,MAAM,kBAAkB,GAAG;;yBAEF,CAAC;AAc1B;;;;;GAKG;AACH,SAAgB,kBAAkB,CAAC,KAAc;IAC/C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACtD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC;IACrD,CAAC;IAED,MAAM,QAAQ,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACxC,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;IAC5C,MAAM,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;IAE/C,mBAAmB;IACnB,IAAI,cAAuB,CAAC;IAC5B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,qBAAM,CAAC,eAAe,CAAC,kBAAkB,CAAC,CAAC;QACvD,cAAc,GAAG,qBAAM,CAAC,MAAM,CAC5B,IAAI,EAAE,iDAAiD;QACvD,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,EACjC,GAAG,EACH,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,CACpC,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,8BAA8B,EAAE,CAAC;IAClE,CAAC;IAED,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;IACvD,CAAC;IAED,iBAAiB;IACjB,IAAI,OAAgC,CAAC;IACrC,IAAI,CAAC;QACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;IAC5E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC;IACrD,CAAC;IAED,eAAe;IACf,IAAI,OAAO,OAAO,CAAC,SAAS,KAAK,QAAQ,EAAE,CAAC;QAC1C,MAAM,GAAG,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACxC,IAAI,GAAG,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;YAC/B,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC;QACrD,CAAC;IACH,CAAC;IAED,OAAO;QACL,KAAK,EAAE,IAAI;QACX,OAAO,EAAE;YACP,IAAI,EAAG,OAAO,CAAC,IAAe,IAAI,KAAK;YACvC,SAAS,EAAG,OAAO,CAAC,SAAoB,IAAI,EAAE;YAC9C,QAAQ,EAAG,OAAO,CAAC,QAAqB,IAAI,EAAE;SAC/C;KACF,CAAC;AACJ,CAAC"}
|