grep
This commit is contained in:
@@ -115,6 +115,7 @@ WHITE-BOX TESTING (code provided):
|
||||
- Static coverage floor: execute at least one structural AST mapping pass (`sg` and/or Tree-sitter) per repository and keep artifact output
|
||||
- Static coverage target per repository: run one `semgrep` pass, one secrets pass (`gitleaks` and/or `trufflehog`), one `trivy fs` pass, and one AST-structural pass (`sg` and/or Tree-sitter); if any are skipped, record why in the shared wiki
|
||||
- Keep AST artifacts bounded and high-signal: scope to relevant paths/hypotheses, avoid whole-repo generic function dumps
|
||||
- AST target selection rule: build `sg-targets.txt` from `semgrep.json` scope first (`paths.scanned`, fallback to unique `results[].path`), then run `xargs ... sg run` against that file list. Only use path-heuristic fallback if semgrep scope is unavailable, and log fallback reason in the wiki.
|
||||
- Shared memory: Use notes as shared working memory; discover wiki notes with `list_notes`, then read the selected one via `get_note(note_id=...)` before analysis
|
||||
- Before `agent_finish`/`finish_scan`, update the shared repo wiki with scanner summaries, key routes/sinks, and dynamic follow-up plan
|
||||
- Dynamic: Run the application and test live to validate exploitability
|
||||
|
||||
@@ -14,6 +14,8 @@ Increase white-box coverage by combining source-aware triage with dynamic valida
|
||||
## Recommended Workflow
|
||||
|
||||
1. Build a quick source map before deep exploitation, including at least one AST-structural pass (`sg` or `tree-sitter`) scoped to relevant paths.
|
||||
- For `sg` baseline, derive `sg-targets.txt` from `semgrep.json` scope first (`paths.scanned`, fallback to unique `results[].path`) and run `xargs ... sg run` on that list.
|
||||
- Only fall back to path heuristics when semgrep scope is unavailable, and record the fallback reason in the repo wiki.
|
||||
2. Run first-pass static triage to rank high-risk paths.
|
||||
3. Use triage outputs to prioritize dynamic PoC validation.
|
||||
4. Keep findings evidence-driven: no report without validation.
|
||||
|
||||
@@ -103,9 +103,12 @@ def _ensure_notes_loaded() -> None:
|
||||
notes_path = _get_notes_jsonl_path()
|
||||
if notes_path:
|
||||
_notes_storage.update(_load_notes_from_jsonl(notes_path))
|
||||
for note_id, note in _notes_storage.items():
|
||||
if note.get("category") == "wiki":
|
||||
_persist_wiki_note(note_id, note)
|
||||
try:
|
||||
for note_id, note in _notes_storage.items():
|
||||
if note.get("category") == "wiki":
|
||||
_persist_wiki_note(note_id, note)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
_loaded_notes_run_dir = run_dir_key
|
||||
|
||||
|
||||
@@ -170,3 +170,45 @@ def test_append_note_content_appends_delta(tmp_path: Path, monkeypatch) -> None:
|
||||
finally:
|
||||
_reset_notes_state()
|
||||
set_global_tracer(previous_tracer) # type: ignore[arg-type]
|
||||
|
||||
|
||||
def test_list_and_get_note_handle_wiki_repersist_oserror_gracefully(
|
||||
tmp_path: Path, monkeypatch
|
||||
) -> None:
|
||||
monkeypatch.chdir(tmp_path)
|
||||
_reset_notes_state()
|
||||
|
||||
previous_tracer = get_global_tracer()
|
||||
tracer = Tracer("wiki-repersist-oserror-run")
|
||||
set_global_tracer(tracer)
|
||||
|
||||
try:
|
||||
created = notes_actions.create_note(
|
||||
title="Repo wiki",
|
||||
content="initial wiki content",
|
||||
category="wiki",
|
||||
tags=["repo:demo"],
|
||||
)
|
||||
assert created["success"] is True
|
||||
note_id = created["note_id"]
|
||||
assert isinstance(note_id, str)
|
||||
|
||||
_reset_notes_state()
|
||||
|
||||
def _raise_oserror(*_args, **_kwargs) -> None:
|
||||
raise OSError("disk full")
|
||||
|
||||
monkeypatch.setattr(notes_actions, "_persist_wiki_note", _raise_oserror)
|
||||
|
||||
listed = notes_actions.list_notes(category="wiki")
|
||||
assert listed["success"] is True
|
||||
assert listed["total_count"] == 1
|
||||
assert listed["notes"][0]["note_id"] == note_id
|
||||
|
||||
fetched = notes_actions.get_note(note_id=note_id)
|
||||
assert fetched["success"] is True
|
||||
assert fetched["note"]["note_id"] == note_id
|
||||
assert fetched["note"]["content"] == "initial wiki content"
|
||||
finally:
|
||||
_reset_notes_state()
|
||||
set_global_tracer(previous_tracer) # type: ignore[arg-type]
|
||||
|
||||
Reference in New Issue
Block a user