mirror of
https://github.com/openclaw/clawhub.git
synced 2026-08-14 00:47:57 +00:00
fix: restore prepublication ClawScan authentication (#3142)
* fix: preserve prepublication judge errors * fix: pass codex credential to prepublication scans * fix: keep node tests out of vitest
This commit is contained in:
@@ -91,6 +91,7 @@ jobs:
|
||||
|
||||
- name: Run pre-publication publish worker
|
||||
env:
|
||||
CODEX_API_KEY: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }}
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
SECURITY_SCAN_WORKER_TOKEN: ${{ secrets.SECURITY_SCAN_WORKER_TOKEN }}
|
||||
VIRUSTOTAL_API_KEY: ${{ secrets.VT_API_KEY }}
|
||||
|
||||
@@ -113,6 +113,7 @@ describe("pre-publication publish worker workflow", () => {
|
||||
"${{ vars.PREPUBLICATION_TRUFFLEHOG_IMAGE || 'ghcr.io/trufflesecurity/trufflehog:3.95.6@sha256:96f8429082cb2d4ae73b1096dcdb2f5aa139881d97042b0c5e5fa226a392e056' }}",
|
||||
});
|
||||
expect(String(job.env?.PREPUBLICATION_TRUFFLEHOG_IMAGE)).toContain("@sha256:");
|
||||
expect(job.env).not.toHaveProperty("CODEX_API_KEY");
|
||||
expect(job.env).not.toHaveProperty("OPENAI_API_KEY");
|
||||
expect(job.env).not.toHaveProperty("SECURITY_SCAN_WORKER_TOKEN");
|
||||
expect(job.env).not.toHaveProperty("CODEX_SECURITY_SCAN_TIMEOUT_MS");
|
||||
@@ -134,6 +135,7 @@ describe("pre-publication publish worker workflow", () => {
|
||||
expect(steps.find((step) => step.name === "Install SkillSpector")).toBeUndefined();
|
||||
expect(JSON.stringify(job)).not.toContain("CODEX_SECURITY_SCAN_SHADOW_CLAWSCAN");
|
||||
expect(runStep?.env).toEqual({
|
||||
CODEX_API_KEY: "${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }}",
|
||||
OPENAI_API_KEY: "${{ secrets.OPENAI_API_KEY }}",
|
||||
SECURITY_SCAN_WORKER_TOKEN: "${{ secrets.SECURITY_SCAN_WORKER_TOKEN }}",
|
||||
VIRUSTOTAL_API_KEY: "${{ secrets.VT_API_KEY }}",
|
||||
@@ -144,6 +146,9 @@ describe("pre-publication publish worker workflow", () => {
|
||||
expect(stepUsesSecret(step, "SECURITY_SCAN_WORKER_TOKEN"), stepName).toBe(
|
||||
stepName === "Run pre-publication publish worker",
|
||||
);
|
||||
expect(stepUsesSecret(step, "CODEX_API_KEY"), stepName).toBe(
|
||||
stepName === "Run pre-publication publish worker",
|
||||
);
|
||||
expect(stepUsesSecret(step, "OPENAI_API_KEY"), stepName).toBe(
|
||||
stepName === "Run pre-publication publish worker",
|
||||
);
|
||||
|
||||
@@ -643,6 +643,61 @@ JSON
|
||||
}
|
||||
});
|
||||
|
||||
it("preserves the redacted ClawScan judge failure reason", async () => {
|
||||
const workspace = await tempDir();
|
||||
await mkdir(join(workspace, "artifact"), { recursive: true });
|
||||
await writeFile(join(workspace, "artifact", "SKILL.md"), "# Demo\n");
|
||||
const fakeClawScan = join(workspace, "fake-clawscan");
|
||||
await writeFile(
|
||||
fakeClawScan,
|
||||
`#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
output=""
|
||||
while [ "$#" -gt 0 ]; do
|
||||
if [ "$1" = "--output" ]; then
|
||||
output="$2"
|
||||
break
|
||||
fi
|
||||
shift
|
||||
done
|
||||
cat > "$output" <<'JSON'
|
||||
{"schemaVersion":"clawscan-run-v1","profile":"clawhub","scanners":{"clawscan-static":{"status":"completed"},"skillspector":{"status":"completed"},"virustotal":{"status":"completed"}},"judge":{"status":"failed","error":"Codex request was rate limited.","result":null}}
|
||||
JSON
|
||||
`,
|
||||
);
|
||||
await chmod(fakeClawScan, 0o755);
|
||||
const previousCommand = process.env.PREPUBLICATION_CLAWSCAN_COMMAND;
|
||||
process.env.PREPUBLICATION_CLAWSCAN_COMMAND = fakeClawScan;
|
||||
|
||||
try {
|
||||
await expect(
|
||||
runNativeClawScan(
|
||||
{
|
||||
job: {
|
||||
_id: String(attempt.attemptId),
|
||||
attempts: 1,
|
||||
hasMaliciousSignal: false,
|
||||
leaseToken: attempt.claimId,
|
||||
source: "pre-publication",
|
||||
targetKind: "skillVersion",
|
||||
waitForVtUntil: 0,
|
||||
},
|
||||
target: {},
|
||||
},
|
||||
workspace,
|
||||
),
|
||||
).resolves.toEqual({
|
||||
check: {
|
||||
status: "failed",
|
||||
summary: "ClawScan judge status was failed: Codex request was rate limited.",
|
||||
},
|
||||
});
|
||||
} finally {
|
||||
if (previousCommand === undefined) delete process.env.PREPUBLICATION_CLAWSCAN_COMMAND;
|
||||
else process.env.PREPUBLICATION_CLAWSCAN_COMMAND = previousCommand;
|
||||
}
|
||||
});
|
||||
|
||||
it("maps TruffleHog verified-secret exit code to a blocked result", async () => {
|
||||
const workspace = await tempDir();
|
||||
await mkdir(join(workspace, "artifact"), { recursive: true });
|
||||
|
||||
@@ -405,12 +405,18 @@ function storedAnalysisFromClawScanArtifact(artifact: unknown): {
|
||||
const judge = asRecord(record?.judge);
|
||||
const result = asRecord(judge?.result);
|
||||
const judgeStatus = readString(judge, ["status"]);
|
||||
const judgeError = readString(judge, ["error"]);
|
||||
const scannerFailures = collectClawScanScannerFailures(asRecord(record?.scanners));
|
||||
if (scannerFailures.length > 0) {
|
||||
return { error: `ClawScan scanner did not complete: ${scannerFailures.join(", ")}` };
|
||||
}
|
||||
if (judgeStatus !== "completed") {
|
||||
return { error: `ClawScan judge status was ${judgeStatus ?? "missing"}` };
|
||||
return {
|
||||
error: [
|
||||
`ClawScan judge status was ${judgeStatus ?? "missing"}`,
|
||||
...(judgeError ? [judgeError] : []),
|
||||
].join(": "),
|
||||
};
|
||||
}
|
||||
const verdict = readString(result, ["verdict", "status"]);
|
||||
if (!verdict) return { error: "ClawScan judge did not return a verdict" };
|
||||
|
||||
@@ -41,6 +41,7 @@ export default defineConfig({
|
||||
"**/dist/**",
|
||||
"**/coverage/**",
|
||||
"**/convex/_generated/**",
|
||||
".github/scripts/catalog-feed-schema-version-guard.test.cjs",
|
||||
"packages/clawhub/**",
|
||||
"packages/clawhub-admin/test-artifact/**",
|
||||
"e2e/**",
|
||||
|
||||
Reference in New Issue
Block a user