Skip to content

feat(audit): allow SkillSpector --baseline through external args - #2936

Open
Mohammed Alkindi (MohammedAlkindi) wants to merge 2 commits into
microsoft:mainfrom
MohammedAlkindi:fix/2331-skillspector-baseline
Open

feat(audit): allow SkillSpector --baseline through external args#2936
Mohammed Alkindi (MohammedAlkindi) wants to merge 2 commits into
microsoft:mainfrom
MohammedAlkindi:fix/2331-skillspector-baseline

Conversation

@MohammedAlkindi

Copy link
Copy Markdown
Contributor

Closes #2331

Description

The SkillSpector adapter's argument allowlist had no --baseline, so apm audit --external-args "--baseline ..." was rejected fail-closed and reviewed suppression baselines were unusable through APM.

--baseline is now allowlisted. Path handling is unchanged: validate_extra_args already resolves value tokens and rejects anything leaving the scan directory, so the issue's resolve and reject-outside bullets needed no new code. The one new rule is arity. extra_args are appended before the positional targets, so a bare --baseline makes SkillSpector read the first scan target as the baseline path and silently audit one path fewer. A new validate_value_arity pass rejects zero values and a second value, for --flag=value and --flag value alike.

Type of change

  • New feature
  • Documentation

Testing

16 new tests; the four external-scanner test files go from 77 to 93 passed. Fail-before on the unfixed tree: 6 of 7 adapter tests raise "argument '--baseline' is not allowed", and the no-baseline case passes both ways. Full tests/unit tests/test_console.py matches the pre-change baseline. ruff check and ruff format --check clean.

Spec conformance (OpenAPM v0.1)

  • N/A, this PR does not change OpenAPM-observable behaviour.

🤖 Generated with Claude Code

The SkillSpector adapter's passthrough allowlist had no --baseline
entry, so `apm audit --external skillspector --external-args
"--baseline .skillspector-baseline.yaml"` was rejected fail-closed and
reviewed suppression baselines could not be used through APM.

Add --baseline to ALLOWED_ARG_PREFIXES. Path resolution and
containment need no new code: validate_extra_args already resolves
value tokens and rejects anything that leaves the scan directory.

Add validate_value_arity, run after the allowlist gate, to require
exactly one value for declared flags. extra_args are appended before
the positional scan targets, so a bare --baseline would make
SkillSpector read the first target as the baseline path and silently
audit one path fewer; a stray second value would become an extra
target. Both --flag=value and --flag value are handled.

Closes microsoft#2331

Copilot AI 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.

🟡 Changes recommended

Unresolved baseline path-containment and inline-argument validation issues remain, and packaged usage guidance is stale.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds SkillSpector --baseline support to apm audit --external-args, with allowlisting, arity validation, tests, and documentation.

Changes:

  • Allowlists and forwards --baseline.
  • Adds value-arity validation and related tests.
  • Documents baseline usage and constraints.
File summaries
File Summary
tests/unit/test_skillspector_llm.py Tests baseline forwarding and safety behavior.
tests/unit/test_external_options.py Tests baseline value-arity validation.
src/apm_cli/security/external/skillspector.py Adds SkillSpector baseline support.
src/apm_cli/security/external/options.py Adds shared arity validation; inline values still need trailing-value enforcement.
docs/src/content/docs/integrations/external-scanners.md Documents baseline usage; packaged usage guidance also needs updating.
Review details
  • Files reviewed: 5/5 changed files
  • Comments generated: 3
  • Review effort level: Lite

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

"--language",
"--exclude",
"--include",
"--baseline",
Comment on lines +224 to +227
if separator:
if not inline_value:
raise ExternalScanError(missing)
continue
Comment on lines +122 to +124
`--baseline` points SkillSpector at a reviewed suppression baseline. It must
carry exactly one value, inside the working directory, so a bare `--baseline`
cannot swallow the first scan target:
The arity gate was asymmetric. `--baseline value extra.yaml` was
rejected, but `--baseline=value extra.yaml` was accepted: the inline
branch returned to the loop without looking at the following token,
so the stray value survived and became an extra positional scan
target. Check the next token in both spellings.

Containment did not cover the documented form. validate_extra_args
treats a separator-free token as a non-path, which is right for
`--model gpt-4o` but not for a path-valued flag: `--baseline
.skillspector-baseline.yaml` never reached ensure_path_within, so a
symlink of that name pointing outside the scan directory would have
been read despite the containment claim. Resolve every declared path
value through _reject_escaping_value, separators or not. This is the
allowlist's first path-valued entry, which is why the gap appeared.

validate_value_arity now takes base_dir, so each adapter states the
scan root it validates against. Four regression tests cover the
inline stray value and both escaping spellings.

Also document the exactly-one-value and in-working-directory
constraints in the packaged apm-usage guide, which describes the
same --external-args contract as the Starlight page.
@MohammedAlkindi

Copy link
Copy Markdown
Contributor Author

All three are addressed in 1adae94.

Declared path values now resolve regardless of separators, so the documented .skillspector-baseline.yaml spelling is contained. Inline --baseline=x checks the following token, so --baseline=base.yaml extra.yaml is rejected rather than becoming an extra scan target. commands.md:258 now carries the same exactly-one-value and in-working-directory wording as the Starlight page.

Checked with a directory junction named .skillspector-baseline.yaml resolving outside the scan root: on bd9fb6c both inputs are accepted, on 1adae94 both raise ExternalScanError. 62 unit tests pass in test_external_options.py and test_skillspector_llm.py.

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.

Allow SkillSpector --baseline through apm audit external args

2 participants