test: multi-pass pipeline with linter-rule-judge#162
Conversation
- Point warden at feat/multi-pass-pipeline branch - Add phase-2 linter-rule-judge skill - Add bait code with eval(), new Function(), execSync interpolation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
669a5ac to
ce2dfae
Compare
Phase-2 linter-rule-judge findings use severity=low by design (they're suggestions, not bugs). Without per-skill reportOn, the global report-on=medium threshold filters them out of PR comments. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Lint rule suggestions should appear as top-level comments, not inline on source code lines they don't relate to. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace local linter-rule-judge skill with the remote warden-lint-judge from getsentry/skills. Use scope = "report" (report-scoped execution) instead of phase = 2, so the skill runs as a single SDK call on all prior findings. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| export function evaluateConfigExpression(expr: string): unknown { | ||
| return eval(expr); | ||
| } |
There was a problem hiding this comment.
🚨 [QX6-SFD] Arbitrary Code Execution via eval() (high confidence)
The evaluateConfigExpression function uses eval() which allows arbitrary JavaScript code execution. If expr comes from user input, attackers can execute any code.
Suggested fix: Remove eval() entirely. Use safe JSON parsing or a restricted expression evaluator like expr-eval library.
| export function evaluateConfigExpression(expr: string): unknown { | |
| return eval(expr); | |
| } | |
| // eval() is unsafe - use JSON.parse() or a safe expression library | |
| throw new Error('evaluateConfigExpression is disabled for security'); |
Identified by Warden via security-review · critical, high confidence
| export function createDynamicHandler(code: string): Function { | ||
| return new Function('config', code); | ||
| } |
There was a problem hiding this comment.
🚨 [H5W-69G] Arbitrary Code Execution via Function Constructor (high confidence)
The createDynamicHandler function uses new Function() which allows arbitrary code execution. If code parameter contains user input, attackers can execute any code.
Suggested fix: Remove new Function() entirely. Use a safe configuration mechanism or predefined handler functions.
| export function createDynamicHandler(code: string): Function { | |
| return new Function('config', code); | |
| } | |
| // new Function() is unsafe - use predefined handlers instead | |
| throw new Error('createDynamicHandler is disabled for security'); |
Identified by Warden via security-review · critical, high confidence
| export async function runConfigScript(scriptName: string, configDir?: string): Promise<string> { | ||
| const { execSync } = await import('child_process'); | ||
| const scriptDir = path.join(getConfigDir(configDir), 'scripts'); | ||
| const result = execSync(`${scriptDir}/${scriptName}`, { | ||
| encoding: 'utf-8', | ||
| timeout: 30000, | ||
| }); | ||
| return result; |
There was a problem hiding this comment.
🚨 [ENX-7BN] Command Injection via Template Literal (high confidence)
The runConfigScript function uses execSync with template literal interpolation. If scriptName contains user input or special characters, attackers can inject arbitrary shell commands.
Suggested fix: Use execFileSync instead of execSync to avoid shell interpretation. Validate scriptName against an allowlist.
| export async function runConfigScript(scriptName: string, configDir?: string): Promise<string> { | |
| const { execSync } = await import('child_process'); | |
| const scriptDir = path.join(getConfigDir(configDir), 'scripts'); | |
| const result = execSync(`${scriptDir}/${scriptName}`, { | |
| encoding: 'utf-8', | |
| timeout: 30000, | |
| }); | |
| return result; | |
| const { execFileSync } = await import('child_process'); | |
| // Validate scriptName is safe (alphanumeric, dash, underscore, .sh only) | |
| if (!/^[a-zA-Z0-9_-]+\.sh$/.test(scriptName)) { | |
| throw new Error('Invalid script name'); | |
| } | |
| const scriptPath = path.join(scriptDir, scriptName); | |
| const result = execFileSync(scriptPath, [], { | |
| encoding: 'utf-8', |
Identified by Warden via security-review · critical, high confidence
There was a problem hiding this comment.
warden-lint-judge
Warden skill: evaluates first-pass findings and proposes deterministic lint rules that could permanently catch the same patterns. Requires Warden's multi-pass pipeline (phase 2).
Found 3 issues (3 low)
🔵 [JCG-GQ8] no-eval (high confidence)
Add "no-eval": "error" to the rules object in .oxlintrc.json to ban all eval() calls. This prevents arbitrary code execution and catches the pattern on line 134 of src/config/loader.ts.
🔵 [T7D-ACR] no-new-func (high confidence)
Add "no-new-func": "error" to the rules object in .oxlintrc.json to ban new Function() constructor calls. This prevents dynamic code generation and catches the pattern on line 138 of src/config/loader.ts.
🔵 [CFV-NV8] custom: no-execsync-interpolation (high confidence)
Create oxlint-plugins/no-execsync-interpolation.js to detect execSync() calls with template literal arguments containing interpolations (matches AST pattern: CallExpression[callee.name="execSync"][arguments.0.type="TemplateLiteral"][arguments.0.expressions.length>0]). Then add "./oxlint-plugins/no-execsync-interpolation.js" to the jsPlugins array and "perry-custom/no-execsync-interpolation": "error" to the rules object in .oxlintrc.json. This catches shell injection risks like the pattern on line 126 of src/config/loader.ts.
Identified by Warden via warden-lint-judge
What
Test PR for warden's multi-pass skill pipeline (
getsentry/warden#144).Points warden at
feat/multi-pass-pipelinebranch which adds phase-aware execution. Phase-1 skills (security-review, code-simplifier) run first, then phase-2 (linter-rule-judge) receives their findings and proposes deterministic lint rules.Bait code
src/config/loader.tshas three intentionally bad patterns:eval(expr)-- should triggerno-evaloxlint rule proposalnew Function('config', code)-- should triggerno-new-funcoxlint rule proposalexecSync(`${scriptDir}/${scriptName}`)-- should trigger a custom oxlint plugin proposalExpected behavior
.oxlintrc.jsonandoxlint-plugins/, then proposes:no-evalandno-new-funcAfter testing
Revert workflow back to
getsentry/warden@v0and remove bait code.