rr-debug-race — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited rr-debug-race (Agent Skill) and scored it 96/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 1 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 1 flagged
The text {match} tells the agent to skip the normal "ask the user first" gate. Used adversarially it removes the human-in-the-loop check before destructive or sensitive actions, turning a normally-gated agent into a fire-and-forget executor.
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Use this skill when you suspect a data race, deadlock, or concurrency bug. rr records the exact thread interleaving that occurred, then replays it deterministically so you can inspect every thread's state at every point.
exact interleaving and replays it identically every time.
exact write from the racing thread.
Run the program under rr. If the race is intermittent, you may need multiple attempts:
rr_record(command=$ARGUMENTS, trace_dir="<project>/rr-trace-<random>")For sanitizer-detected races, enable ThreadSanitizer to make the race more visible:
rr_record(command=["./program"], env={"TSAN_OPTIONS": "halt_on_error=1"}, trace_dir=...)rr_ps(trace_dir="<trace>")
rr_replay_start(trace_dir="<trace>", pid=<pid>)Before diving in, understand the thread landscape:
rr_continue()At the crash or end point:
rr_thread_list()Note which threads exist and their states. Switch between threads to see what each was doing:
rr_thread_select(<tid>)
rr_backtrace()
rr_locals()Identify the shared variable or memory that is being raced on. This might be obvious from the crash (e.g., corrupted pointer) or from sanitizer output.
Set a watchpoint on the contested data:
rr_watchpoint_set("shared_variable")Or on a memory address:
rr_watchpoint_set("*(int*)0x7fff5678")Use continue (forward and reverse) to find every access to the contested data:
rr_continue() # Find the next write
rr_backtrace() # Who wrote it?
rr_thread_list() # Which thread?Save checkpoints at each access point:
rr_checkpoint_save() # Save before moving on
rr_continue() # Next accessOnce you have the sequence of accesses across threads, identify where synchronization is missing:
Use rr_continue(reverse=True) with the watchpoint to walk backwards through all writes and find the first unsynchronized access.
Use rr_when() to note event numbers at key points:
rr_when() # Note event number
rr_run_to_event(N) # Jump to a specific pointrr_replay_stop()
rr_rm(trace_dir="<trace>")stop it, then inspect thread states in replay — all threads will be at their blocking points.
as a specific interleaving, not truly parallel execution. This makes it easier to reason about.
rr_evaluate("pthread_mutex_trylock(&mutex)") to check lock states at any point.~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.