Skip to content

fix(security): bound skill-file audit read (restore removed fs dependency)#110589

Merged
steipete merged 1 commit into
mainfrom
claude/fix-audit-extra-fs-import
Jul 18, 2026
Merged

fix(security): bound skill-file audit read (restore removed fs dependency)#110589
steipete merged 1 commit into
mainfrom
claude/fix-audit-extra-fs-import

Conversation

@steipete

Copy link
Copy Markdown
Contributor

What Problem This Solves

main is broken: src/security/audit-extra.async.ts calls fs.readFile(params.skillFilePath, ...) at line ~196 but has no fs import, so typecheck fails (Cannot find name 'fs') and blocks CI.

Why This Change Was Made

The "bound file reads in audit" series (#101773, #101775) converted the plugin-manifest read to the safe readRegularFile helper and removed the now-unused import fs from "node:fs/promises" — but missed the SKILL.md read added by #109363, which still used fs.readFile. That left an orphaned reference and a broken build.

User Impact

Restores a green build. Consistent with the series intent, the skill-file audit read is now bounded via readRegularFile (cap 256_000 bytes, matching the workspace loader's DEFAULT_MAX_SKILL_FILE_BYTES) instead of an unbounded fs.readFile, so an oversized attacker-controlled SKILL.md cannot force an unbounded read during the code-safety scan.

Evidence

  • Single-file change: adds MAX_SKILL_AUDIT_FILE_BYTES = 256_000 and converts the one orphaned fs.readFile to readRegularFile({...}).then(({buffer}) => buffer.toString("utf-8")), mirroring the existing manifest-read pattern at line ~114. No remaining fs.method() calls; no fs import needed.
  • The file was green at ab99029 (had import fs); this restores correctness after the import was removed.

@steipete
steipete requested a review from a team as a code owner July 18, 2026 09:18
@openclaw-barnacle openclaw-barnacle Bot added size: XS maintainer Maintainer-authored PR labels Jul 18, 2026
@steipete steipete self-assigned this Jul 18, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 889a003f7e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

fs.readFile(params.skillFilePath, "utf-8"),
readRegularFile({
filePath: params.skillFilePath,
maxBytes: MAX_SKILL_AUDIT_FILE_BYTES,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Respect configured skill file audit limit

When skills.limits.maxSkillFileBytes is raised above the default, loadWorkspaceSkillEntries still loads those larger SKILL.md files, but the audit now always reads them with this fixed 256 KB cap. In that configuration a loadable >256 KB skill makes readRegularFile reject, the catch in collectInstalledSkillsCodeSafetyFindings emits only skills.code_safety.scan_failed, and scanSkillContent/scanSource never report critical SKILL.md findings such as pipe-to-shell instructions. Please use the same effective maxSkillFileBytes limit that was used to load the skills instead of hard-coding the default here.

Useful? React with 👍 / 👎.

@steipete
steipete force-pushed the claude/fix-audit-extra-fs-import branch from 889a003 to d4733b0 Compare July 18, 2026 09:30
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jul 18, 2026
@steipete
steipete force-pushed the claude/fix-audit-extra-fs-import branch from d4733b0 to 847f5a1 Compare July 18, 2026 09:36
@clawsweeper clawsweeper Bot added P1 High-priority user-facing bug, regression, or broken workflow. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. labels Jul 18, 2026
@clawsweeper

clawsweeper Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 18, 2026, 5:39 AM ET / 09:39 UTC.

Summary
The branch replaces the skill audit's orphaned fs.readFile call with readRegularFile and a 256 KB SKILL.md read limit.

PR surface: Source +6. Total +6 across 1 file.

Reproducibility: yes. from source: configure skills.limits.maxSkillFileBytes above 256 KB, load a SKILL.md between 256 KB and that limit containing a scanner trigger, then run the deep audit; the proposed read rejects and emits only skills.code_safety.scan_failed.

Review metrics: none identified.

Stored data model
Persistent data-model change detected: serialized state: src/security/audit-extra.async.ts. Confirm migration or upgrade compatibility proof before merge.

Merge readiness
Overall: 🧂 unranked krab
Proof: 🧂 unranked krab
Patch quality: 🦐 gold shrimp
Result: blocked until real behavior proof is added.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • Use the loader's effective configured file limit rather than a fixed cap.
  • [P1] Add focused default and override-limit regression coverage.
  • [P1] Post redacted after-fix security audit --deep output; updating the PR body should trigger a fresh review, or a maintainer can comment @clawsweeper re-review.

Proof guidance:

  • [P1] Needs real behavior proof before merge: The PR body describes the code change but contains no after-fix run of the real audit path; add redacted terminal output showing the repaired audit behavior, including the configured-limit case. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Risk before merge

  • [P1] Merging the fixed 256 KB cap would let an existing configuration that raises skills.limits.maxSkillFileBytes load a larger skill while the deep audit reports only a generic scan failure and misses its critical SKILL.md findings.
  • [P1] The branch needs after-fix proof from a real audit path, including an oversized-default but configured-allowed SKILL.md with a known dangerous instruction; redact any local paths or private content before posting it.

Maintainer options:

  1. Use the effective configured skill-file limit (recommended)
    Replace the fixed audit cap with the loader's canonical effective maxSkillFileBytes value and add an override-limit regression test before merge.
  2. Keep the fixed security-audit cap
    Accept that configured larger skills can load but will receive only a scan-failed warning during deep audit, with explicit maintainer approval of that reduced coverage.
  3. Pause the bounded-read change
    Close or defer this branch if a shared effective-limit seam cannot be added without broadening the audit contract safely.
Copy recommended automerge instruction
@clawsweeper automerge

Special instructions:
Use the same resolved skills.limits.maxSkillFileBytes contract for audit reads; add default and configured-override regression coverage, then provide redacted real audit output.

Next step before merge

  • [P1] A narrow code repair is clear: preserve the bounded read while using the loader's configured effective limit; the contributor must separately supply real audit proof.

Security
Needs attention: The diff improves bounded-read handling but currently creates a security-audit coverage gap for configured larger skill files.

Review findings

  • [P2] Respect the configured skill file audit limit — src/security/audit-extra.async.ts:101-104
Review details

Best possible solution:

Derive the audit read limit from the same canonical resolved skill-file limit used by the workspace loader, add coverage for both the default and an overridden limit, then show a real security audit --deep result that reports the expected dangerous SKILL.md finding.

Do we have a high-confidence way to reproduce the issue?

Yes, from source: configure skills.limits.maxSkillFileBytes above 256 KB, load a SKILL.md between 256 KB and that limit containing a scanner trigger, then run the deep audit; the proposed read rejects and emits only skills.code_safety.scan_failed.

Is this the best way to solve the issue?

No. Bounded reads are the right direction, but the cap must follow the same effective configured limit that admitted the skill rather than silently overriding that contract in the audit path.

Full review comments:

  • [P2] Respect the configured skill file audit limit — src/security/audit-extra.async.ts:101-104
    The loader admits SKILL.md files using skills.limits.maxSkillFileBytes, but this fixed 256 KB cap rejects any configured-allowed larger file. The catch then emits only skills.code_safety.scan_failed, so critical SKILL.md findings are skipped. This was raised in the prior review and remains on the current head; derive the cap from the same effective loader limit and cover an override-limit case.
    Confidence: 0.98

Overall correctness: patch is incorrect
Overall confidence: 0.96

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against f14947d256d8.

Label changes

Label changes:

  • add P1: Current main has a build-blocking audit regression, while this proposed repair also affects security-audit coverage for configured skills.
  • add merge-risk: 🚨 compatibility: Existing users can configure skills.limits.maxSkillFileBytes above 256 KB, but the proposed fixed audit cap does not honor that persisted configuration.
  • add merge-risk: 🚨 security-boundary: A loadable SKILL.md above the fixed cap can avoid content-level critical findings during a deep security audit.

Label justifications:

  • P1: Current main has a build-blocking audit regression, while this proposed repair also affects security-audit coverage for configured skills.
  • merge-risk: 🚨 compatibility: Existing users can configure skills.limits.maxSkillFileBytes above 256 KB, but the proposed fixed audit cap does not honor that persisted configuration.
  • merge-risk: 🚨 security-boundary: A loadable SKILL.md above the fixed cap can avoid content-level critical findings during a deep security audit.
  • rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🧂 unranked krab and patch quality is 🦐 gold shrimp.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR body describes the code change but contains no after-fix run of the real audit path; add redacted terminal output showing the repaired audit behavior, including the configured-limit case. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Evidence reviewed

PR surface:

Source +6. Total +6 across 1 file.

View PR surface stats
Area Files Added Removed Net
Source 1 8 2 +6
Tests 0 0 0 0
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 1 8 2 +6

Security concerns:

  • [medium] Configured larger skills bypass content-level audit findings — src/security/audit-extra.async.ts:101
    A SKILL.md permitted by skills.limits.maxSkillFileBytes above 256 KB fails this fixed-cap read, causing a generic scan-failed warning rather than scanner findings for dangerous content.
    Confidence: 0.98

Acceptance criteria:

  • [P1] node scripts/run-vitest.mjs src/security/audit-extra.async.test.ts --run.
  • [P1] Run a redacted real openclaw security audit --deep scenario with a configured skills.limits.maxSkillFileBytes above 256 KB and a scanner-triggering SKILL.md.

What I checked:

Likely related people:

What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@steipete
steipete merged commit 95d632e into main Jul 18, 2026
140 of 144 checks passed
@steipete
steipete deleted the claude/fix-audit-extra-fs-import branch July 18, 2026 09:44
@steipete

Copy link
Copy Markdown
Contributor Author

Merged via squash.

steipete added a commit to mushuiyu886/openclaw that referenced this pull request Jul 18, 2026
steipete added a commit that referenced this pull request Jul 18, 2026
* fix(plugin-sdk): reject failed raw channel sends

* fix(plugin-sdk): preserve raw result helper compatibility

* test(plugin-sdk): cover raw send fallback errors

Co-authored-by: 杨浩宇0668001029 <[email protected]>

* fix(security): bound skill-file audit read via safe reader (restore removed fs dependency) (#110589)

---------

Co-authored-by: Peter Steinberger <[email protected]>
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 19, 2026
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 19, 2026
…9906)

* fix(plugin-sdk): reject failed raw channel sends

* fix(plugin-sdk): preserve raw result helper compatibility

* test(plugin-sdk): cover raw send fallback errors

Co-authored-by: 杨浩宇0668001029 <[email protected]>

* fix(security): bound skill-file audit read via safe reader (restore removed fs dependency) (openclaw#110589)

---------

Co-authored-by: Peter Steinberger <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

maintainer Maintainer-authored PR merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. P1 High-priority user-facing bug, regression, or broken workflow. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. size: XS status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant