Skip to content

feat: add Cisco skill scanning and security ops reporting#1

Merged
internet-dot merged 2 commits intomainfrom
feat/cisco-skill-security-ops
Mar 29, 2026
Merged

feat: add Cisco skill scanning and security ops reporting#1
internet-dot merged 2 commits intomainfrom
feat/cisco-skill-security-ops

Conversation

@kantorcodes
Copy link
Copy Markdown
Member

Summary

  • expand the scanner to model structured findings, normalized scoring, and applicable-surface scoring for modern Codex plugin manifests
  • integrate Cisco skill-scanner for plugin skill analysis with policy controls and expose a new Skill Security category
  • add security-ops outputs and gates including markdown/SARIF reporting, severity-based CI failure thresholds, and richer README/package metadata

Verification

  • ./.venv/bin/python -m pytest
  • ./.venv/bin/ruff check src tests
  • ./.venv/bin/python -m build

Notes

  • Cisco scanning is available through the new optional cisco extra and can be required per run with --cisco-skill-scan on.
  • Local continuity notes under .claude/ were intentionally not included in this PR.

Signed-off-by: Michael Kantor <6068672+kantorcodes@users.noreply.github.com>
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request updates the Codex Plugin Scanner to version 1.1.0, introducing Cisco-backed skill scanning and a security-ops focus. Key features include new report formats (SARIF, Markdown), severity-based CI gating, and a normalized scoring system that handles non-applicable checks. The review feedback highlights a scoring logic error when the Cisco scanner is unavailable, an inefficiency in the GitHub Action documentation, and a missing data extraction for skipped skills in the Cisco integration.

Comment on lines +86 to +92
return CheckResult(
name="Cisco skill scan completed",
passed=True,
points=3,
max_points=3,
message=summary.message,
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

When the Cisco skill scanner is unavailable in 'auto' mode, this check incorrectly awards full points (3/3). This rewards projects for not having the optional cisco dependencies installed. Instead, the check should be marked as not applicable (0/0 points) to ensure scores are normalized correctly, as described in the README.

Suggested change
return CheckResult(
name="Cisco skill scan completed",
passed=True,
points=3,
max_points=3,
message=summary.message,
)
return CheckResult(
name="Cisco skill scan completed",
passed=True,
points=0,
max_points=0,
message=summary.message,
applicable=False,
)

README.md Outdated
Comment on lines +130 to +133
- name: Scan plugin
run: codex-plugin-scanner ./my-plugin
run: codex-plugin-scanner ./my-plugin --fail-on-severity high
- name: Upload SARIF
run: codex-plugin-scanner ./my-plugin --format sarif --output codex-plugin-scanner.sarif
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The GitHub Action example runs the scanner twice, which is inefficient. You can combine these two steps into a single run to both check for failures and generate the SARIF report. This will make the CI pipeline faster.

Suggested change
- name: Scan plugin
run: codex-plugin-scanner ./my-plugin
run: codex-plugin-scanner ./my-plugin --fail-on-severity high
- name: Upload SARIF
run: codex-plugin-scanner ./my-plugin --format sarif --output codex-plugin-scanner.sarif
- name: Scan plugin
run: codex-plugin-scanner ./my-plugin --fail-on-severity high --format sarif --output codex-plugin-scanner.sarif

message=f"Cisco skill scanner completed using the {policy_name} policy preset.",
findings=tuple(findings),
skills_scanned=int(summary.get("total_skills_scanned", 0)),
skills_skipped=skills_skipped,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The skills_skipped field is always an empty tuple. The _analyzability_check relies on this field to report on skipped skills. If the cisco-ai-skill-scanner payload contains information on skipped skills, it should be extracted and populated here. For example, it might be in the summary dictionary from the payload.



def _availability_check(summary: CiscoSkillScanSummary, mode: str) -> CheckResult:
if summary.status in {CiscoIntegrationStatus.ENABLED, CiscoIntegrationStatus.SKIPPED}:
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

WARNING: Logic issue: when status is UNAVAILABLE or FAILED and mode is not "on", this falls through to the else branch at line 86 which returns passed=True with 3 points.

When cisco_skill_scan="auto" and the Cisco scanner is installed but the scan itself fails (status=FAILED), or when it's unavailable in auto mode, the check silently passes and awards points. The else branch should not unconditionally grant points — it should check whether the scanner was expected to be available.

CategoryResult(name="Best Practices", checks=run_best_practice_checks(resolved)),
CategoryResult(name="Marketplace", checks=run_marketplace_checks(resolved)),
CategoryResult(name="Skill Security", checks=run_skill_security_checks(resolved, scan_options)),
CategoryResult(name="Code Quality", checks=run_code_quality_checks(resolved)),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

WARNING: run_cisco_skill_scan is called redundantly. run_skill_security_checks on this line calls run_cisco_skill_scan internally, and then _build_integration_results on line 91 calls it again with the same arguments. This means the Cisco skill scanner executes twice per scan. Consider caching the result or having _build_integration_results reuse the summary already produced by the skill security checks.



def _is_safe_source(plugin_dir: Path, source: str) -> bool:
if source.startswith(("http://", "https://", "git+", "github://")):
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

SUGGESTION: Allowing http:// sources is a security risk. Marketplace sources fetched over plain HTTP are vulnerable to MITM attacks. Consider requiring https:// or git+ schemes only.

@kilo-code-bot
Copy link
Copy Markdown

kilo-code-bot bot commented Mar 29, 2026

Code Review Summary

Status: No New Issues Found | Recommendation: Merge

All 3 issues from the previous review have been resolved in commit df5d4d5.

Previous Issues — Resolved

Severity File Issue Status
WARNING src/codex_plugin_scanner/checks/skill_security.py Auto-mode fallthrough awarded points when Cisco scanner was UNAVAILABLE/FAILED ✅ Fixed — now returns points=0, max_points=0, applicable=False (line 102-109)
WARNING src/codex_plugin_scanner/scanner.py run_cisco_skill_scan called redundantly (twice per scan) ✅ Fixed — introduced SkillSecurityContext to share a single scan result via resolve_skill_security_context (line 72)
SUGGESTION src/codex_plugin_scanner/checks/marketplace.py _is_safe_source allowed http:// URLs (MITM risk) ✅ Fixed — now only permits https://, git+, github:// schemes; any other URL scheme is rejected (line 12-25)

Changes in This Commit

  • skill_security.py: Refactored into SkillSecurityContext dataclass for sharing scan state; fixed availability logic for FAILED status in auto mode.
  • scanner.py: Eliminated duplicate Cisco scan by resolving context once and passing it to both run_skill_security_checks and _build_integration_results.
  • cisco_skill_scanner.py: Added _extract_skipped_skills and _extract_analyzers_used helpers that properly extract data from the Cisco scanner payload. skills_skipped is no longer always empty.
  • marketplace.py: Blocked http:// sources via urlparse scheme check.
  • README.md: Combined GitHub Action into a single scan+SARIF step.
  • Tests: Added tests for auto-mode unavailability, single-scan execution, HTTP source rejection, and skipped-skill extraction.
Files Reviewed (7 files)
  • README.md - no new issues
  • src/codex_plugin_scanner/checks/marketplace.py - no new issues
  • src/codex_plugin_scanner/checks/skill_security.py - no new issues
  • src/codex_plugin_scanner/integrations/cisco_skill_scanner.py - no new issues
  • src/codex_plugin_scanner/scanner.py - no new issues
  • tests/test_marketplace.py - no new issues
  • tests/test_skill_security.py - no new issues

Reviewed by mimo-v2-pro-20260318 · 344,844 tokens

Signed-off-by: Michael Kantor <6068672+kantorcodes@users.noreply.github.com>
Copy link
Copy Markdown
Collaborator

@internet-dot internet-dot left a comment

Choose a reason for hiding this comment

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

LGTM. All checks passing, clean feature addition.

@internet-dot internet-dot merged commit a889aea into main Mar 29, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants