Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c0b0671baa | |||
| e53b0bd11f | |||
| 0bf992ecbf | |||
| f7fa54c12d | |||
| b9994e2e0e |
@@ -16,7 +16,7 @@ jobs:
|
|||||||
target: macos-arm64
|
target: macos-arm64
|
||||||
- os: macos-15-intel
|
- os: macos-15-intel
|
||||||
target: macos-x86_64
|
target: macos-x86_64
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-22.04
|
||||||
target: linux-x86_64
|
target: linux-x86_64
|
||||||
- os: windows-latest
|
- os: windows-latest
|
||||||
target: windows-x86_64
|
target: windows-x86_64
|
||||||
|
|||||||
@@ -9,10 +9,24 @@ if [ ! -f /app/certs/ca.p12 ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Caido enforces a Host allowlist (DNS-rebinding protection) and rejects requests
|
||||||
|
# whose Host header is a hostname it doesn't recognize. To reach Caido over a
|
||||||
|
# hostname (rather than an IP literal), set STRIX_CAIDO_ALLOWED_DOMAINS to a
|
||||||
|
# comma-separated list of hostnames to allow. Unset by default.
|
||||||
|
# See https://docs.caido.io/app/guides/domain_allowlist
|
||||||
|
CAIDO_UI_DOMAIN_ARGS=()
|
||||||
|
if [ -n "${STRIX_CAIDO_ALLOWED_DOMAINS:-}" ]; then
|
||||||
|
IFS=',' read -ra _caido_domains <<< "${STRIX_CAIDO_ALLOWED_DOMAINS}"
|
||||||
|
for _d in "${_caido_domains[@]}"; do
|
||||||
|
[ -n "$_d" ] && CAIDO_UI_DOMAIN_ARGS+=(--ui-domain "$_d")
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
caido-cli --listen 0.0.0.0:${CAIDO_PORT} \
|
caido-cli --listen 0.0.0.0:${CAIDO_PORT} \
|
||||||
--allow-guests \
|
--allow-guests \
|
||||||
--no-logging \
|
--no-logging \
|
||||||
--no-open \
|
--no-open \
|
||||||
|
"${CAIDO_UI_DOMAIN_ARGS[@]}" \
|
||||||
--import-ca-cert /app/certs/ca.p12 \
|
--import-ca-cert /app/certs/ca.p12 \
|
||||||
--import-ca-cert-pass "" > "$CAIDO_LOG" 2>&1 &
|
--import-ca-cert-pass "" > "$CAIDO_LOG" 2>&1 &
|
||||||
|
|
||||||
|
|||||||
+30
-23
@@ -438,30 +438,37 @@ class ReportState:
|
|||||||
targets = self.run_record.get("targets_info") or []
|
targets = self.run_record.get("targets_info") or []
|
||||||
if not isinstance(targets, list):
|
if not isinstance(targets, list):
|
||||||
return None
|
return None
|
||||||
for target in targets:
|
repo_targets = [
|
||||||
if not isinstance(target, dict) or target.get("type") != "repository":
|
target
|
||||||
continue
|
for target in targets
|
||||||
details = target.get("details") or {}
|
if isinstance(target, dict) and target.get("type") == "repository"
|
||||||
if not isinstance(details, dict):
|
]
|
||||||
continue
|
# Provenance binds the whole run to one repo; with multiple repo targets
|
||||||
uri = details.get("target_repo")
|
# that's ambiguous, so omit it rather than mis-attributing later repos'
|
||||||
if not isinstance(uri, str) or not uri.strip():
|
# findings to the first repo's URI/commit.
|
||||||
continue
|
if len(repo_targets) != 1:
|
||||||
|
return None
|
||||||
|
target = repo_targets[0]
|
||||||
|
details = target.get("details") or {}
|
||||||
|
if not isinstance(details, dict):
|
||||||
|
return None
|
||||||
|
uri = details.get("target_repo")
|
||||||
|
if not isinstance(uri, str) or not uri.strip():
|
||||||
|
return None
|
||||||
|
|
||||||
context: dict[str, Any] = {"repositoryUri": uri.strip()}
|
context: dict[str, Any] = {"repositoryUri": uri.strip()}
|
||||||
full_name = _parse_repo_full_name(uri)
|
full_name = _parse_repo_full_name(uri)
|
||||||
if full_name:
|
if full_name:
|
||||||
context["repositoryFullName"] = full_name
|
context["repositoryFullName"] = full_name
|
||||||
cloned = details.get("cloned_repo_path")
|
cloned = details.get("cloned_repo_path")
|
||||||
if isinstance(cloned, str) and cloned.strip():
|
if isinstance(cloned, str) and cloned.strip():
|
||||||
commit, branch = _git_head(cloned.strip())
|
commit, branch = _git_head(cloned.strip())
|
||||||
if commit:
|
if commit:
|
||||||
context["commitSha"] = commit
|
context["commitSha"] = commit
|
||||||
if branch:
|
if branch:
|
||||||
context["branch"] = branch
|
context["branch"] = branch
|
||||||
context["ref"] = f"refs/heads/{branch}"
|
context["ref"] = f"refs/heads/{branch}"
|
||||||
return context
|
return context
|
||||||
return None
|
|
||||||
|
|
||||||
def _sync_llm_usage_record(self) -> None:
|
def _sync_llm_usage_record(self) -> None:
|
||||||
self.run_record["llm_usage"] = self._build_llm_usage_record()
|
self.run_record["llm_usage"] = self._build_llm_usage_record()
|
||||||
|
|||||||
@@ -114,7 +114,8 @@ async def create_or_reuse(
|
|||||||
)
|
)
|
||||||
|
|
||||||
caido_endpoint = await session.resolve_exposed_port(_CONTAINER_CAIDO_PORT)
|
caido_endpoint = await session.resolve_exposed_port(_CONTAINER_CAIDO_PORT)
|
||||||
host_caido_url = f"http://{caido_endpoint.host}:{caido_endpoint.port}"
|
scheme = "https" if caido_endpoint.tls else "http"
|
||||||
|
host_caido_url = f"{scheme}://{caido_endpoint.host}:{caido_endpoint.port}"
|
||||||
logger.debug("Caido host endpoint resolved: %s", host_caido_url)
|
logger.debug("Caido host endpoint resolved: %s", host_caido_url)
|
||||||
|
|
||||||
caido_client = await bootstrap_caido(
|
caido_client = await bootstrap_caido(
|
||||||
|
|||||||
@@ -63,6 +63,18 @@ _HANDLER_TAG = "_strix_scan_handler"
|
|||||||
# ``openai.agents`` is the openai-agents SDK's canonical logger root.
|
# ``openai.agents`` is the openai-agents SDK's canonical logger root.
|
||||||
_TRACKED_ROOTS: tuple[str, ...] = ("strix", "openai.agents")
|
_TRACKED_ROOTS: tuple[str, ...] = ("strix", "openai.agents")
|
||||||
|
|
||||||
|
_STDOUT_QUIET_ROOTS: frozenset[str] = frozenset({"openai.agents"})
|
||||||
|
|
||||||
|
|
||||||
|
class _StdoutQuietFilter(logging.Filter):
|
||||||
|
def filter(self, record: logging.LogRecord) -> bool:
|
||||||
|
if record.levelno >= logging.WARNING:
|
||||||
|
return True
|
||||||
|
return not any(
|
||||||
|
record.name == root or record.name.startswith(root + ".")
|
||||||
|
for root in _STDOUT_QUIET_ROOTS
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def configure_dependency_logging() -> None:
|
def configure_dependency_logging() -> None:
|
||||||
"""Quiet dependency logging/warnings that obscure Strix scan logs."""
|
"""Quiet dependency logging/warnings that obscure Strix scan logs."""
|
||||||
@@ -119,6 +131,7 @@ def setup_scan_logging(run_dir: Path, *, debug: bool | None = None) -> Callable[
|
|||||||
stream_handler.setLevel(logging.DEBUG if debug else logging.ERROR)
|
stream_handler.setLevel(logging.DEBUG if debug else logging.ERROR)
|
||||||
stream_handler.setFormatter(formatter)
|
stream_handler.setFormatter(formatter)
|
||||||
stream_handler.addFilter(context_filter)
|
stream_handler.addFilter(context_filter)
|
||||||
|
stream_handler.addFilter(_StdoutQuietFilter())
|
||||||
setattr(stream_handler, _HANDLER_TAG, True)
|
setattr(stream_handler, _HANDLER_TAG, True)
|
||||||
|
|
||||||
tracked_loggers = [logging.getLogger(name) for name in _TRACKED_ROOTS]
|
tracked_loggers = [logging.getLogger(name) for name in _TRACKED_ROOTS]
|
||||||
|
|||||||
@@ -41,6 +41,15 @@ def test_repository_context_uri_only_without_clone() -> None:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_repository_context_none_for_multiple_repository_targets() -> None:
|
||||||
|
state = ReportState(run_name="t")
|
||||||
|
state.run_record["targets_info"] = [
|
||||||
|
{"type": "repository", "details": {"target_repo": "https://github.com/acme/widget"}},
|
||||||
|
{"type": "repository", "details": {"target_repo": "https://github.com/acme/api"}},
|
||||||
|
]
|
||||||
|
assert state._sarif_repository_context() is None
|
||||||
|
|
||||||
|
|
||||||
def test_repository_context_derives_commit_and_branch_from_clone(tmp_path: Path) -> None:
|
def test_repository_context_derives_commit_and_branch_from_clone(tmp_path: Path) -> None:
|
||||||
repo = tmp_path / "widget"
|
repo = tmp_path / "widget"
|
||||||
repo.mkdir()
|
repo.mkdir()
|
||||||
|
|||||||
Reference in New Issue
Block a user