🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

@kilocode/openclaw-security-advisor

Package Overview
Dependencies
Maintainers
10
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@kilocode/openclaw-security-advisor - npm Package Compare versions

Comparing version
0.1.0
to
0.1.1
+1
-0
CHANGELOG.md

@@ -12,2 +12,3 @@ # Changelog

- KiloClaw platform detection now uses four independent signals instead of relying on a single env var, so detection holds across KiloClaw deployments of varying age. `detectPlatform()` now walks (in order, short-circuiting on the first hit): (1) `plugins.entries.kiloclaw-customizer.enabled` in `openclaw.json`, (2) `plugins.load.paths` containing the kiloclaw customizer install path, (3) `process.env.KILOCLAW_SANDBOX_ID`, (4) `process.env.KILOCODE_FEATURE === "kiloclaw"`. The two config-side signals are written by the KiloClaw controller at boot and are present on every KiloClaw instance since the customizer plugin was introduced, so they catch older deployments that predate the env-var signals. Internal signature change: `detectPlatform()` now takes the loaded openclaw config so it can inspect the config-side signals.
- First-time device auth no longer triggers a brief gateway restart after the token is captured. The plugin now registers `reload.noopPrefixes` for `plugins.entries.openclaw-security-advisor.config.authToken`, so the SecretRef patch written to `openclaw.json` after device auth is classified as a noop by the gateway reload planner instead of falling through to the default `plugins.* → restart` rule. The security checkup report is returned in the same response with no connection interruption. Scope is intentionally limited to the `authToken` field — `apiBaseUrl` and other config changes still take effect via the normal restart path.

@@ -14,0 +15,0 @@ - Release workflow: consolidated post-publish git/GitHub operations into a single atomic step with retries, eliminating a race condition where the version bump commit and tag could be pushed separately. Registry verification is now informational-only and never blocks tag/release steps.

+10
-6

@@ -129,3 +129,3 @@ import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";

try {
return await doCheckup(apiBase, configToken);
return await doCheckup(api, apiBase, configToken);
} catch (err) {

@@ -148,3 +148,3 @@ if (err instanceof AuthExpiredError) {

try {
return await doCheckup(apiBase, envToken);
return await doCheckup(api, apiBase, envToken);
} catch (err) {

@@ -169,3 +169,3 @@ if (err instanceof AuthExpiredError) {

try {
return await doCheckup(apiBase, savedToken);
return await doCheckup(api, apiBase, savedToken);
} catch (err) {

@@ -196,3 +196,3 @@ if (!(err instanceof AuthExpiredError)) throw err;

try {
return await doCheckup(apiBase, pollResult.token);
return await doCheckup(api, apiBase, pollResult.token);
} catch (err) {

@@ -276,3 +276,7 @@ if (err instanceof AuthExpiredError) {

async function doCheckup(apiBase: string, token: string): Promise<string> {
async function doCheckup(
api: PluginApi,
apiBase: string,
token: string,
): Promise<string> {
const auditResult = await runAudit();

@@ -289,3 +293,3 @@ if (!auditResult.ok) {

source: {
platform: detectPlatform(),
platform: detectPlatform(api.runtime.config.loadConfig()),
method: "plugin",

@@ -292,0 +296,0 @@ pluginVersion: PLUGIN_VERSION,

{
"name": "@kilocode/openclaw-security-advisor",
"version": "0.1.0",
"version": "0.1.1",
"type": "module",

@@ -5,0 +5,0 @@ "license": "MIT",

@@ -8,5 +8,71 @@ /**

* side of that check.
*
* Detection walks multiple independent signals in order of decreasing
* reliability across deployment age. The goal is that at least one
* signal fires on every KiloClaw instance ever deployed, regardless
* of whether the instance predates a given env var. Any hit short-
* circuits to "kiloclaw".
*
* Ordering (stopping at the first hit):
* 2. openclaw.json has `plugins.entries["kiloclaw-customizer"].enabled`
* truthy — the kiloclaw controller writes this at boot for every
* kiloclaw instance, predating any of the env-var signals. Most
* durable universal signal today.
* 3. openclaw.json `plugins.load.paths` contains the kiloclaw
* customizer install path — same writer, redundant cross-check.
* 4. `process.env.KILOCLAW_SANDBOX_ID` is set — present on every
* kiloclaw instance since 2026-03-22.
* 5. `process.env.KILOCODE_FEATURE === "kiloclaw"` — the original
* env-var signal, present on kiloclaw since 2026-02-17.
*
* We intentionally do NOT add a loose `KILOCLAW_*`-prefix heuristic;
* the four signals above are precise and one of them will hit on any
* real kiloclaw deployment.
*/
export function detectPlatform(): "kiloclaw" | "openclaw" {
return process.env.KILOCODE_FEATURE === "kiloclaw" ? "kiloclaw" : "openclaw";
export type Platform = "kiloclaw" | "openclaw";
const CUSTOMIZER_ID = "kiloclaw-customizer";
const CUSTOMIZER_LOAD_PATH =
"/usr/local/lib/node_modules/@kiloclaw/kiloclaw-customizer";
export function detectPlatform(
config: unknown,
env: NodeJS.ProcessEnv = process.env,
): Platform {
if (hasKiloclawCustomizerEntry(config)) return "kiloclaw";
if (hasKiloclawCustomizerLoadPath(config)) return "kiloclaw";
if (hasKiloclawSandboxIdEnv(env)) return "kiloclaw";
if (hasKilocodeFeatureEnv(env)) return "kiloclaw";
return "openclaw";
}
function hasKiloclawCustomizerEntry(config: unknown): boolean {
const entry = getPath(config, ["plugins", "entries", CUSTOMIZER_ID]);
if (!entry || typeof entry !== "object") return false;
const enabled = (entry as Record<string, unknown>).enabled;
return enabled === true;
}
function hasKiloclawCustomizerLoadPath(config: unknown): boolean {
const paths = getPath(config, ["plugins", "load", "paths"]);
return Array.isArray(paths) && paths.includes(CUSTOMIZER_LOAD_PATH);
}
function hasKiloclawSandboxIdEnv(env: NodeJS.ProcessEnv): boolean {
const v = env.KILOCLAW_SANDBOX_ID;
return typeof v === "string" && v.length > 0;
}
function hasKilocodeFeatureEnv(env: NodeJS.ProcessEnv): boolean {
return env.KILOCODE_FEATURE === "kiloclaw";
}
function getPath(root: unknown, path: string[]): unknown {
let cur: unknown = root;
for (const key of path) {
if (!cur || typeof cur !== "object") return undefined;
cur = (cur as Record<string, unknown>)[key];
}
return cur;
}