@upx-us/shield 0.7.4 → 0.7.5

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/CHANGELOG.md CHANGED
@@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ---
6
6
 
7
+ ## [0.7.5] — 2026-03-13
8
+
9
+ ### Security
10
+ - **Block direct platform backend calls** — `loadCredentials()` now detects and overrides any `SHIELD_API_URL` pointing to a platform backend (legacy Replit URLs, `uss.upx.com`). Plugin traffic is enforced to only reach the Shield ingest proxy. A second-layer check in the RPC client rejects blocked URLs even if config loading is bypassed.
11
+ - **Fix RPC `apiUrl` resolution** — RPC handlers now use the validated `apiUrl` from credentials instead of a non-existent config field (which silently fell through to `null`).
12
+
13
+ ---
7
14
  ## [0.7.4] — 2026-03-13
8
15
 
9
16
  ### Changed
package/dist/index.js CHANGED
@@ -995,9 +995,8 @@ exports.default = {
995
995
  .catch((err) => respond(false, { error: err instanceof Error ? err.message : String(err) }));
996
996
  });
997
997
  const rpcCreds = (0, config_1.loadCredentials)();
998
- const rpcConfig = (0, config_1.loadConfig)({});
999
998
  const platformApiConfig = {
1000
- apiUrl: rpcConfig.platformApiUrl ?? null,
999
+ apiUrl: rpcCreds?.apiUrl || null,
1001
1000
  instanceId: state.instanceId || rpcCreds?.instanceId || '',
1002
1001
  hmacSecret: rpcCreds?.hmacSecret || '',
1003
1002
  };
@@ -21,6 +21,7 @@ export declare function deriveAgentsDirFromInstallPath(startDir?: string): strin
21
21
  export declare const SHIELD_CONFIG_PATH: string;
22
22
  export declare function injectConfigEnv(): void;
23
23
  export declare function loadCredentials(): ShieldCredentials;
24
+ export declare function enforceIngestUrl(url: string): string;
24
25
  export declare function loadCredentialsFromPluginConfig(_pluginConfig: Record<string, unknown>): ShieldCredentials;
25
26
  export interface ConfigOverrides {
26
27
  credentials?: ShieldCredentials;
@@ -37,6 +37,7 @@ exports.SHIELD_CONFIG_PATH = void 0;
37
37
  exports.deriveAgentsDirFromInstallPath = deriveAgentsDirFromInstallPath;
38
38
  exports.injectConfigEnv = injectConfigEnv;
39
39
  exports.loadCredentials = loadCredentials;
40
+ exports.enforceIngestUrl = enforceIngestUrl;
40
41
  exports.loadCredentialsFromPluginConfig = loadCredentialsFromPluginConfig;
41
42
  exports.loadConfig = loadConfig;
42
43
  const os_1 = require("os");
@@ -128,13 +129,32 @@ function loadCredentials() {
128
129
  }
129
130
  return val;
130
131
  }
132
+ const rawApiUrl = process.env.SHIELD_API_URL || file.SHIELD_API_URL || '';
133
+ const apiUrl = enforceIngestUrl(rawApiUrl);
131
134
  return {
132
- apiUrl: process.env.SHIELD_API_URL || file.SHIELD_API_URL || '',
135
+ apiUrl,
133
136
  hmacSecret: resolve('SHIELD_HMAC_SECRET', 'SHIELD_SECRET'),
134
137
  instanceId: resolve('SHIELD_INSTANCE_ID', 'SHIELD_FINGERPRINT'),
135
138
  shieldEnv: process.env.SHIELD_ENV || file.SHIELD_ENV || '',
136
139
  };
137
140
  }
141
+ const CANONICAL_INGEST_URL = 'https://openclaw-shield.upx.com';
142
+ const BLOCKED_HOST_PATTERNS = [
143
+ /^https?:\/\/uss\.upx\.com/i,
144
+ /^https?:\/\/[a-z0-9-]+\.replit\.app/i,
145
+ /^https?:\/\/egupx-/i,
146
+ ];
147
+ function enforceIngestUrl(url) {
148
+ if (!url)
149
+ return CANONICAL_INGEST_URL;
150
+ const isBlocked = BLOCKED_HOST_PATTERNS.some(p => p.test(url));
151
+ if (isBlocked) {
152
+ log.warn('config', `SHIELD_API_URL points to a platform backend ("${url}") — this is not permitted. ` +
153
+ `Overriding with ${CANONICAL_INGEST_URL}. Remove SHIELD_API_URL from your config to fix this permanently.`);
154
+ return CANONICAL_INGEST_URL;
155
+ }
156
+ return url;
157
+ }
138
158
  function loadCredentialsFromPluginConfig(_pluginConfig) {
139
159
  return loadCredentials();
140
160
  }
@@ -57,6 +57,13 @@ async function callPlatformApi(config, path, params, method) {
57
57
  error: 'Platform API not configured. This feature requires the Shield platform API which is not yet available for your instance. Check your Shield dashboard for updates.',
58
58
  };
59
59
  }
60
+ const BLOCKED = [/^https?:\/\/uss\.upx\.com/i, /^https?:\/\/[a-z0-9-]+\.replit\.app/i, /^https?:\/\/egupx-/i];
61
+ if (BLOCKED.some(p => p.test(config.apiUrl))) {
62
+ return {
63
+ ok: false,
64
+ error: 'Shield API URL points to a platform backend — direct access is not permitted. Reconfigure Shield to use the ingest endpoint.',
65
+ };
66
+ }
60
67
  const url = new URL(path, config.apiUrl);
61
68
  const httpMethod = method || (params ? 'POST' : 'GET');
62
69
  if (httpMethod === 'GET' && params) {
@@ -2,7 +2,7 @@
2
2
  "id": "shield",
3
3
  "name": "OpenClaw Shield",
4
4
  "description": "Real-time security monitoring \u2014 streams enriched, redacted security events to the Shield detection platform.",
5
- "version": "0.7.4",
5
+ "version": "0.7.5",
6
6
  "skills": [
7
7
  "./skills"
8
8
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@upx-us/shield",
3
- "version": "0.7.4",
3
+ "version": "0.7.5",
4
4
  "description": "Security monitoring plugin for OpenClaw agents — streams enriched security events to the Shield detection platform",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",